Modifying alignment of buttons in React components

Transforming the typical Tic Tac Toe game from the React tutorial, with an added one-player feature. Oddly, button alignment shifts out of place once a value is inserted; causing the button to drop by about 50px until the row is filled with values, after which they realign back into formation on the board. I'm puzzled as to why this occurs and would appreciate any assistance in maintaining consistent button alignment.

There's also unpredictability in the computer's logic when selecting a diagonal move; it seems simple to trap the computer into choosing either 0 or 2, where it then resorts to random selection to fill those squares. As per my understanding, the program "should..." recognize the necessity to choose these squares based on the given logic;

else if (squares[b] === 'X' && squares[b] === squares[c] && squares[a] === null){
      console.log("need O in ", a);
      return a;

I've maintained the console.log statements within the program to demonstrate how and where I faced issues while troubleshooting this problem. Any insights offered would be immensely valued. Thank you for taking the time to assist.

The alignment glitch can be viewed on JS Bin

<!doctype html>
<html>
<head>
<meta charset="UTF-8" />
<title>Tic Tac Toe</title>
<script src="https://unpkg.com/react@latest/dist/react.js"></script>
<script src="https://unpkg.com/react-dom@latest/dist/react-dom.js"></script>
<script src="https://unpkg.com/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="640605060108491710050a0005080b0a0124524a55514a54">[email protected]</a>/babel.min.js"></script>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id='root'></div>
<script type='text/babel' >

var numberXs = 0;

var lines = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

function Square(props){
  return(
    <button className="square" onClick={() => props.onClick()}>{props.value}</button>    
    );
}

class Board extends React.Component{
  renderSquare(i){
    return <Square value={this.props.squares[i]} onClick={() => this.props.onClick(i)} />
  }  

  render(){
    return(
    <div className="board" key={this.props.key}>
    <div className="row">
        {this.renderSquare(0)}
        {this.renderSquare(1)}
        {this.renderSquare(2)}
    </div>
    <div className="row">
        {this.renderSquare(3)}
        {this.renderSquare(4)}
        {this.renderSquare(5)}
    </div>
    <div className="row">
        {this.renderSquare(6)}
        {this.renderSquare(7)}
        {this.renderSquare(8)}
    </div>
    </div>
    );
  }
}

class Game extends React.Component{

   defaultState = {
      onePlayerGame: true,
      squares: Array(9).fill(null),
      xIsNext: true
    };

  constructor(props){
    super(props);
    this.onePlayer = this.onePlayer.bind(this);
    this.twoPlayer = this.twoPlayer.bind(this);
    this.handleMove = this.handleMove.bind(this);
    this.gameOver = this.gameOver.bind(this);
    this.state = this.defaultState;
  }

  onePlayer(){
    this.setState({onePlayerGame: true});
    return(
    document.getElementById('onePlayer').style.color = "red",
    document.getElementById('twoPlayer').style.color = "black"
    );
  }


  twoPlayer(){
    this.setState({ onePlayerGame: false});
    return(
    document.getElementById('onePlayer').style.color= "black",
    document.getElementById('twoPlayer').style.color =  "red"
    );
  }


  handleMove(i){
    var HALturn = true,
        HALmove;
    const squares = this.state.squares.slice();

    if (checkWinner(squares) || squares[i]){
      return;
    }

    if (this.state.onePlayerGame){
      squares[i] = 'X';
      numberXs += 1;
      this.setState({squares:squares});
      if (numberXs >= 5){
        return;
      }

      if (HALbest(squares)){
        HALmove = HALbest(squares);
        squares[HALmove] = 'O';
        this.setState({squares: squares});
        return;


      } else {
      while (HALturn) {
        HALmove = Math.floor(Math.random() * squares.length);
        if (squares[HALmove] === null){
          squares[HALmove] = 'O';
          this.setState({
            squares: squares
          });
          return;
          HALturn = false;
        } else {
          console.log("Additional random selection");
        }
      }
      }
    }

    else {
      squares[i] = this.state.xIsNext ? 'X':'O';
      this.setState({
        squares: squares,
        xIsNext: !this.state.xIsNext
      });
    } 
  }

  gameOver(){
    this.setState({...this.defaultState});
    numberXs = 0;
  }

  render(){
    var winner = checkWinner(this.state.squares);
    let status, endGame;
    if (winner) {
      status = "Winner is " + winner;
    } else if (!winner && numberXs === 5){
      status = "No Winner. Reset to play again.";
    } else {
      status = "Next Move: " + (this.state.xIsNext ? 'X': 'O');
    }


    return(
    <div id="main">
      <div>
       <button className="gameSelect" id="onePlayer" value={this.state.onePlayerGame} onClick={() => this.onePlayer()}  >One Player</button>
       <button className="gameSelect"  id="twoPlayer"value={this.state.onePlayerGame} onClick={() => this.twoPlayer()}  >Two Players</button>
      </div>

      <Board 
        squares={this.state.squares} 
        onClick={(i) => this.handleMove(i)} />
      <div id="status">{status}</div>
        <button className="gameSelect" id="resetButton" onClick={() => this.gameOver()}>Reset Game</button>
    </div>
    );
  }
}


function checkWinner(squares){
  for (var i = 0; i < lines.length; i++){
    const [a, b, c] = lines[i];
    if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]){
      return squares[a];
    }
  }
  return null;
}

function HALbest(squares){
  for (var i = 0; i < lines.length; i++){
    const [a, b, c] = lines[i];
    if (squares[a] === 'X' && squares[a] === squares[c] && squares[b] === null){
      console.log("need O in ", b);
      return b;
    } else if (squares[b] === 'X' && squares[b] === squares[c] && squares[a] === null){
      console.log("need O in ", a);
      return a;
    } else if ( squares[a] === 'X' &&  squares[a] === squares[b] && squares[c] === null  ){
      console.log("need O in ", c);
      return c;
    } 
  } 
  return null;
}


ReactDOM.render(
  <Game />,
  document.getElementById('root')
)

</script>
</body>
</html>

Aspect Ratio issues persisted despite utilizing this CSS adaptation;

#main {
  width: 80%;
  margin: auto;
  color: blue;
  text-align: center;
}

.gameSelect {
  width: 30%;
  text-align: center;
  background-color: white;
  border: 1px solid transparent;
  margin: 5px 0 5px 0;
}

.board {
  display: inline;
}

#onePlayer {
  color: red;
}

#status {
  margin: 25px 0 5px 0;
}

.row {
  margin: auto;
  height: 100px;
}

.square {
  width: 100px;
  height: 100px;
  background-color: white;
  font-size: 20px;
  margin: 0;
  display: inline;
}

Your continued support is greatly appreciated.

Answer №1

It's interesting that the alignment issue arises. Adding a vertical align of top to .square seems to do the trick (at least in Chrome and FireFox). Check out this link for reference

.square {
    ...
    vertical-align: top;
}

The logic problem stems from your javascript code specifying to only proceed with the 'best move' if it evaluates to true. If 0 is returned, it indicates not to make the best move.

if (HALbest(squares)){
   HALmove = HALbest(squares);
   squares[HALmove] = 'O';
   this.setState({squares: squares});
   return;
}

To rectify this, consider adjusting the condition as follows:

if (HALbest(squares) !== null){
   HALmove = HALbest(squares);
   squares[HALmove] = 'O';
   this.setState({squares: squares});
   return;
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the most efficient method for generating random dark colors using javascript code?

Looking for a function that specifically returns dark colors. Although I can generate random colors with the code below, how do I make sure it only retrieves dark ones? document.getElementById('mydiv').style.backgroundColor = '#' ...

Tips for utilizing FixedHeaderTable - Basic instructions required

After doing extensive research, I stumbled upon this plugin called Fixed Header Tables. Despite following the instructions provided on the main website, I couldn't get it to work. I was aiming to create a table with a fixed top row and left column fu ...

The drawing library (Google Maps) failed to load

I am looking to integrate drawing mode into Google Maps for my project. Below is the code snippet from my View: <!DOCTYPE html> <html> <head> <meta name="viewport" content="initial-scale=1.0, user-scalable=no"> <me ...

Optimizing the usage of override Button with Box component in Material-UI

Recently, I've been delving into the Box component in material-UI (https://material-ui.com/components/box/#box) and attempting to understand and write code for it. Specifically, I've been experimenting with overriding a Button component using th ...

MUI CSS: Mastering image manipulation

My MUI React Component features a Card that contains an image and buttons <Card key={index} className="xl:w-[350px] w-[310px] max-h-[450px]"> <img src={meme.url} className="center bg-cover" alt="" /> <Box cl ...

Is it possible for a mobile web application to continue running even when the screen is

Thinking about creating a mobile web application with the use of jQuery Mobile for tracking truck deliveries. I'm interested in sending GPS coordinates back to the server periodically. Is this possible even when the screen is turned off? If not, any ...

Creating a Future Prediction Graph with ECharts

I am looking to create a forecast chart that includes both Actual values (presented as a line chart) and projected values (displayed as a dotted chart). An example of what I have in mind can be seen here, created using Excel: Although I couldn't loca ...

What is the formula for determining the size of an image using JavaScript, jQuery, or Java?

I'm looking to determine the dimensions of an image. I have both the image src and base64 data available. My goal is to display the current size of the image. I am working with Java and JavaScript. Is there a way for me to calculate the image size usi ...

How to perfectly align content on a webpage

Can someone help me understand why my webpage is off-centered as it scales up? I have set a minimum width of 1000px, but it still appears to be centered at 30%-70%. Any insights on this issue would be greatly appreciated. <!DOCTYPE html PUBLIC "-//W3 ...

Tips for detecting successful file downloads from the client side using Mean/AngularJS

I have developed a chat application with the capability to send files through chat windows. I am now looking to automatically delete files from the server once they have been successfully downloaded by clients. My technology stack includes MEAN. rou ...

Exploring External Functions in Angular Beyond the Library

Transitioning from standard JavaScript to Angular has been a bit challenging for me, especially when working with the Google Places library (or any other asynchronous callback). Here is the code snippet: var sparkApp = angular.module('sparkApp' ...

Enhance your React Material Table experience by easily adding new fields when you create a

How can I ensure that the 'ahiddenfield' is visible when adding a new row in the Material Table shown below? I am uncertain about how to access the state just before a new row is added (Before onRowAdd). Is there a way to achieve this without too ...

Adding a prefix to the imported CSS file

My React app, created with create-react-app, is designed to be integrated as a "widget" within other websites rather than functioning as a standalone application. To achieve this, I provide website owners with minified JS and CSS files that they can inser ...

Error messages encountered following the latest update to the subsequent project

Recently, I upgraded a Next project from version 12 to 14, and now I'm encountering numerous import errors when attempting to run the project locally. There are too many errors to list completely, but here are a few examples: Import trace for requeste ...

What are the steps to modify the placeholder of the formik <Field/> component?

Struggling to figure out how to make the date input empty with Formik. I just want it to display nothing initially, but have been unable to do so after hours of trying different methods. <Field name="date" type="date" className ...

What are the appropriate situations for utilizing getStaticPaths()?

Right now, an API call is being made in a main component and the fetched data is saved in a Singleton. This singleton data needs to be accessed by the getStaticPaths() function. However, due to the fact that getStaticPaths() pre-renders it, the singleton ...

executing a Prisma database migration with various schemas

I am currently immersed in a Prisma project where my goal is to create a node module that can be utilized by other projects. The challenge now is to ensure that the database stays synchronized with the models and the primary project, so all testing platfor ...

What is the reason for Vue not updating the component after the Pinia state is modified (when deleting an object from an Array)?

When using my deleteHandler function in pinia, I noticed an issue where the users array was not being re-rendered even though the state changed in vue devtools. Interestingly, if I modify values within the array instead of deleting an object from it, Vue ...

Encountering an issue in Laravel when trying to retrieve data using relationships and the paginate() method

When I try to fetch data using paginate(10), Vue.js does not work. However, if I use paginate(5), it works fine. The code in the Controller with relationships in the model files is working fine and returns a 200 OK response. $results = Posts::with([' ...

Tips for inserting a button under a div when clicked

I am working on a layout where I have several div cards aligned side by side using the display: inline-block property. What I want to achieve is that when I click on a card, a button is added below the respective div. To accomplish this, I tried using jqu ...