尝试修复此浏览器井字游戏中的错误

问题描述 投票:0回答:1

我正在尝试用人工智能制作井字游戏。到目前为止,我已经应用了游戏逻辑、人工智能逻辑、玩家和游戏板处理。一切正常,但选择角色有一个问题,如果我选择按钮 X 或 O,它应该将其分配给人类玩家,另一个分配给人工智能。然而,虽然 X 按钮按预期工作,但我的 O 按钮仍然让人类玩家选择 X。我需要能够选择 O 并玩第二个,但游戏总是以我作为第一个玩家和第二个 AI 开始..

const chooseXObtn = document.querySelector(".chooseXO-btn");
const chooseXO = document.querySelector(".chooseXO");

function displayXO() {
  chooseXO.classList.toggle("closed");
  console.log("display work")
}

chooseXObtn.addEventListener("click", displayXO);


const gameBoard = (() => {
  let winner;
  let getWinner = () => winner;
  let gameboard = [
    ["", "", ""],
    ["", "", ""],
    ["", "", ""]
  ];

  const getBoard = () => gameboard;
  const getPosition = (row, column) => gameboard[row][column];
  const setPosition = (row, column, el) => {
    gameboard[row][column] = el;
    render();
  }
  const resetBoard = () => {
    gameboard = [
      ["", "", ""],
      ["", "", ""],
      ["", "", ""]
    ];
  };
  const getEmptyFieldsId = () => {
    let fields = [];
    for (let row = 0; row < gameboard.length; row++) {
      for (let col = 0; col < gameboard[row].length; col++) {
        const field = gameboard[row][col];
        if (field == "") {
          fields.push([row, col]);
        }
      }
    }
    return fields;
  };
  const setFieldForAiLogic = (row, column, player) => {
    if (player == undefined) {
      board[row][column] = "";
      return;
    }
    board[row][column] = player.getMark();
  }

  return {
    getBoard,
    getWinner,
    getPosition,
    setPosition,
    resetBoard,
    getEmptyFieldsId
  }

})();

const Player = (name, mark) => {
  const getName = () => name;
  const getMark = () => mark;
  const setMark = (mark) => this.mark = mark;

  return {
    getName,
    getMark,
    setMark
  }
}


const gameController = (() => {

    let humanPlayer = Player("Player1", "X");
    let aiPlayer = Player("AI", "O");
    let turn = true;
    let board;
    let winner = null;
    const setTurn = (falseortrue) => turn = falseortrue;
    const getWinner = () => winner;
    const whoseTurn = () => turn ? humanPlayer : aiPlayer;
    const switchTurn = () => turn = turn ? false : true;
    const startGame = () => {
      gameBoard.resetBoard();
      board = gameBoard.getBoard();
      render();
      winner = null;
      // Check who has the 'X' mark and let that player start
      if (humanPlayer.getMark() === 'X') {
        console.log("x called turn true");
        turn = true; // Human starts
      } else {
        console.log("o called turn = false");

        switchTurn(); // AI starts
      }
      // If AI starts, make a move for AI
      if (!turn) {
        let arr = _getbestMove(gameBoard.getBoard());
        console.log(arr)
        gameBoard.setPosition(arr[0], arr[1], whoseTurn().getMark());
        switchTurn();
      }
      // If Human starts, wait for their move
      else {
        // Wait for human to make a move
      }
    }


    const handleMove = (moveRow, moveColumn) => {
      if (!isGameOver(gameBoard.getBoard()) && whoseTurn().getMark() === "X") {
        gameBoard.setPosition(moveRow, moveColumn, whoseTurn().getMark());
        switchTurn();
        // If it's now AI's turn and the game is not over, make a move for AI
        if (!isGameOver(gameBoard.getBoard()) && whoseTurn().getMark() === "O") {
          let arr = _getbestMove(gameBoard.getBoard());
          console.log(arr)
          gameBoard.setPosition(arr[0], arr[1], whoseTurn().getMark());
          switchTurn();
        }
      }
    }

    const changeMark = (mark) => {
      if (mark == "X") {
        humanPlayer.setMark('X');
        aiPlayer.setMark("O");
        turn = true;
      } else if (mark == "O") {
        humanPlayer.setMark("O");
        aiPlayer.setMark("X");
        turn = false;
      } else throw 'incorrect sign';
    }

    const isGameOver = (board) => {
      //check row and columns
      for (let i = 0; i < 3; i++) {
        if (board[i][0] !== "" && board[i][0] === board[i][1] && board[i][1] === board[i][2]) {
          winner = board[i][0];
          return winner;

        } else if (board[0][i] !== "" && board[0][i] === board[1][i] && board[1][i] === board[2][i]) {
          winner = board[0][i];
          return winner;

        }

      }

      //check diagonals

      if (board[0][0] !== "" && board[0][0] === board[1][1] && board[1][1] === board[2][2]) {
        winner = board[0][0];
        return winner;

      } else if (board[2][0] !== "" && board[2][0] === board[1][1] && board[1][1] === board[0][2]) {
        winner = board[2][0];
        return winner;
      }

      //if draw
      let isDraw = true;

      for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
          if (board[i][j] === "") {
            isDraw = false;
          }
        }
      }
      if (isDraw) {
        return "draw";
      }

      // game still continues
      return null;
    }

    return {
      whoseTurn,
      startGame,
      handleMove,
      isGameOver,
      getWinner,
      changeMark
    }
  }

)();

function render() {
  const tiles = document.querySelectorAll(".tile");
  tiles.forEach(
    (tile) => {

      tile.innerHTML = gameBoard.getPosition(tile.getAttribute("data-row"), tile.getAttribute("data-col"))
    }
  );

};

// Announce the winner or draw
function announceResult(result) {
  const message = result === 'draw' ? 'It\'s a draw!' : `${result} wins!`;
  // Display the message in an alert or a div

  setTimeout(() => {
    alert(message);
  }, 100);
}




const tiles = document.querySelectorAll(".tile");
tiles.forEach((tile) => {
  const row = tile.getAttribute("data-row");
  const col = tile.getAttribute("data-col");
});

// Add this event listener to the "Restart" button to start a new game
const restart = document.querySelector(".restart");
restart.addEventListener("click", () => {
  gameController.startGame();
  render();

});
// Add an event listener to each tile
tiles.forEach((tile) => {
  tile.addEventListener("click", () => {
    // Get the row and column of the clicked tile
    const row = tile.getAttribute("data-row");
    const col = tile.getAttribute("data-col");

    // Make a move on the game board

    if (tile.innerHTML == "") {
      gameController.handleMove(row, col);
    }
    // Check if the game is over
    const result = gameController.isGameOver(gameBoard.getBoard());
    if (result) {
      // Announce the result of the game
      announceResult(result);


    }



  });
});


function _getbestMove(currentBoard) {
  let bestVal = +Infinity
  let bestMove = [-1, -1]

  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
        let temp = currentBoard[i][j]
        // console.log(temp)
        currentBoard[i][j] = 'O'
        let moveVal = _minimax(currentBoard, 9, true)
        // console.log("move val", moveVal, bestVal)
        currentBoard[i][j] = temp
        if (moveVal < bestVal) {
          bestMove = [i, j]
          bestVal = moveVal
        }
      }
    }
  }
  // console.log("best Val:", bestVal)

  return bestMove
}


function _minimax(currentBoard, depth, isMaximixingPlayer) {
  // console.log(currentBoard, depth, isMaximixingPlayer)
  let winSymbol = gameController.isGameOver(currentBoard)
  if (depth === 0 | winSymbol === "X" | winSymbol === "O" | winSymbol === "draw") {
    let gameOutcome = gameController.isGameOver(currentBoard)
    if (gameOutcome === 'X') {
      return 10
    } else if (gameOutcome === 'O') {
      return -10
    } else {
      return 0
    }
  }

  if (isMaximixingPlayer) {
    let maxEval = -Infinity
    for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
          let temp = currentBoard[i][j]
          currentBoard[i][j] = 'X'
          let val = _minimax(currentBoard, depth - 1, false)
          // console.log(val)
          currentBoard[i][j] = temp

          if (val > maxEval) {
            maxEval = val;
          }
        }
      }
    }
    return maxEval;




  } else {
    let minEval = +Infinity
    for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
          let temp = currentBoard[i][j]
          currentBoard[i][j] = 'O'
          let val = _minimax(currentBoard, depth - 1, true)
          currentBoard[i][j] = temp

          if (val < minEval) {
            minEval = val;
          }
        }
      }
    }
    return minEval


  }

}
const O_btn = document.querySelector("#O-btn");
const X_btn = document.querySelector("#X-btn");

X_btn.addEventListener("click", function() {
  gameController.changeMark(this.innerHTML);
  gameController.startGame();
  console.log("X button clicked");
});

O_btn.addEventListener("click", function() {
  gameController.changeMark(this.innerHTML);
  gameController.startGame();
  console.log("O button clicked");
});
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  font-family: 'Open Sans', "Helvetica";
}

.title {
  margin-top: 100px;
  flex: 1;
  display: flex;
  justify-content: center;
  border: 1px solid black;
  font-size: 40px;
}

.game-board-container {
  width: 50vh;
  height: 50vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.game-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(100px, 1fr));
  grid-template-rows: repeat(3, minmax(100px, 1fr));
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  grid-gap: 1px;
  /* This creates a 1px gap between cells */
}

.game-board div {
  width: 100%;
  height: 100%;
  outline: 1px solid black;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 100px;
}

.game-board div:hover {
  cursor: pointer;
}

.bottom-menu {
  margin-top: 100px;
  ;
  display: flex;
  width: 50vh;
  height: 50px;
  text-align: center;
}

.bottom-menu div {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  width: 100%;
  height: 100%;
  border: none;
  box-shadow: 1px 1px 1px grey;
  outline: 1px solid black;
}

button:hover {
  box-shadow: 3px 3px 2px grey;
  cursor: pointer
}

span {
  outline: 1px solid black;
  height: 100%;
  display: flex;
  align-items: center;
}

.chooseXO {
  height: 50px;
}

.closed {
  display: none !important;
}

#X-btn {
  background-color: green;
}

#O-btn {
  background-color: red;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js" defer></script>
</head>

<body>
  <div class="title">
    <h1>Tic-tac-toe</h1>
  </div>
  <div class="game-board-container">
    <div class="game-board">
      <div class="tile" data-row="0" data-col="0">X</div>
      <div class="tile" data-row="0" data-col="1">O</div>
      <div class="tile" data-row="0" data-col="2">X</div>
      <div class="tile" data-row="1" data-col="0">O</div>
      <div class="tile" data-row="1" data-col="1">X</div>
      <div class="tile" data-row="1" data-col="2">O </div>
      <div class="tile" data-row="2" data-col="0">x</div>
      <div class="tile" data-row="2" data-col="1">O</div>
      <div class="tile" data-row="2" data-col="2">X</div>
    </div>
  </div>
  <div class="bottom-menu">
    <div class="menu-left">
      <button class="restart">Restart</button>
    </div>
    <div class="menu-right">
      <button class=chooseXO-btn>Choose your letter</button>
      <div class="chooseXO closed">
        <button id="X-btn">X</button>
        <button id="O-btn">O</button>
      </div>
    </div>
  </div>
</body>

</html>

到目前为止,我尝试使用 console.log 调用来调试代码,它在两个按钮上都返回“X 调用变为 true”,并且按钮说 X 单击了,O也单击了。所以按钮可以工作,游戏开始,但是为玩家分配标记似乎没有按预期工作。我必须犯一些根本性的错误。谢谢你

javascript tic-tac-toe web-frontend
1个回答
0
投票

工作

const chooseXObtn = document.querySelector(".chooseXO-btn");
const chooseXO = document.querySelector(".chooseXO");

function displayXO() {
  chooseXO.classList.toggle("closed");
  console.log("display work")
}

chooseXObtn.addEventListener("click", displayXO);


const gameBoard = (() => {
  let winner;
  let getWinner = () => winner;
  let gameboard = [
    ["", "", ""],
    ["", "", ""],
    ["", "", ""]
  ];

  const getBoard = () => gameboard;
  const getPosition = (row, column) => gameboard[row][column];
  const setPosition = (row, column, el) => {
    gameboard[row][column] = el;
    render();
  }
  const resetBoard = () => {
    gameboard = [
      ["", "", ""],
      ["", "", ""],
      ["", "", ""]
    ];
  };
  const getEmptyFieldsId = () => {
    let fields = [];
    for (let row = 0; row < gameboard.length; row++) {
      for (let col = 0; col < gameboard[row].length; col++) {
        const field = gameboard[row][col];
        if (field == "") {
          fields.push([row, col]);
        }
      }
    }
    return fields;
  };
  const setFieldForAiLogic = (row, column, player) => {
    if (player == undefined) {
      board[row][column] = "";
      return;
    }
    board[row][column] = player.getMark();
  }

  return {
    getBoard,
    getWinner,
    getPosition,
    setPosition,
    resetBoard,
    getEmptyFieldsId
  }

})();

const Player = (name, mark) => {
  return {
    name,
    mark,
    getName(){
      return this.name;
    },
    getMark(){
      debugger;
      return this.mark;
    },
    setMark(mark){
      this.mark = mark;
    }
  }
}


const gameController = (() => {

    let humanPlayer = Player("Player1", "X");
    let aiPlayer = Player("AI", "O");
    let turn = true;
    let board;
    let winner = null;
    const setTurn = (falseortrue) => turn = falseortrue;
    const getWinner = () => winner;
    const whoseTurn = () => turn ? humanPlayer : aiPlayer;
    const switchTurn = () => turn = turn ? false : true;
    const startGame = () => {
      gameBoard.resetBoard();
      board = gameBoard.getBoard();
      render();
      winner = null;
      // Check who has the 'X' mark and let that player start
      if (humanPlayer.getMark() === 'X') {
        console.log("x called turn true");
        turn = true; // Human starts
      } else {
        console.log("o called turn = false");
        turn = false;
        switchTurn(); // AI starts
      }
      debugger;
      // If AI starts, make a move for AI
      if (!turn) {
        let arr = _getbestMove(gameBoard.getBoard());
        console.log(arr)
        gameBoard.setPosition(arr[0], arr[1], whoseTurn().getMark());
        switchTurn();
      }
      // If Human starts, wait for their move
      else {
        // Wait for human to make a move
      }
    }


    const handleMove = (moveRow, moveColumn) => {
      if (!isGameOver(gameBoard.getBoard()) && whoseTurn().getMark() === "X") {
        gameBoard.setPosition(moveRow, moveColumn, whoseTurn().getMark());
        switchTurn();
        // If it's now AI's turn and the game is not over, make a move for AI
        if (!isGameOver(gameBoard.getBoard()) && whoseTurn().getMark() === "O") {
          let arr = _getbestMove(gameBoard.getBoard());
          console.log(arr)
          gameBoard.setPosition(arr[0], arr[1], whoseTurn().getMark());
          switchTurn();
        }
      }
    }

    const changeMark = (mark) => {
      if (mark == "X") {
        humanPlayer.setMark('X');
        aiPlayer.setMark("O");
        turn = true;
      } else if (mark == "O") {
        humanPlayer.setMark("O");
        aiPlayer.setMark("X");
        turn = false;
      } else throw 'incorrect sign';
    }

    const isGameOver = (board) => {
      //check row and columns
      for (let i = 0; i < 3; i++) {
        if (board[i][0] !== "" && board[i][0] === board[i][1] && board[i][1] === board[i][2]) {
          winner = board[i][0];
          return winner;

        } else if (board[0][i] !== "" && board[0][i] === board[1][i] && board[1][i] === board[2][i]) {
          winner = board[0][i];
          return winner;

        }

      }

      //check diagonals

      if (board[0][0] !== "" && board[0][0] === board[1][1] && board[1][1] === board[2][2]) {
        winner = board[0][0];
        return winner;

      } else if (board[2][0] !== "" && board[2][0] === board[1][1] && board[1][1] === board[0][2]) {
        winner = board[2][0];
        return winner;
      }

      //if draw
      let isDraw = true;

      for (let i = 0; i < 3; i++) {
        for (let j = 0; j < 3; j++) {
          if (board[i][j] === "") {
            isDraw = false;
          }
        }
      }
      if (isDraw) {
        return "draw";
      }

      // game still continues
      return null;
    }

    return {
      whoseTurn,
      startGame,
      handleMove,
      isGameOver,
      getWinner,
      changeMark
    }
  }

)();

function render() {
  const tiles = document.querySelectorAll(".tile");
  tiles.forEach(
    (tile) => {

      tile.innerHTML = gameBoard.getPosition(tile.getAttribute("data-row"), tile.getAttribute("data-col"))
    }
  );

};

// Announce the winner or draw
function announceResult(result) {
  const message = result === 'draw' ? 'It\'s a draw!' : `${result} wins!`;
  // Display the message in an alert or a div

  setTimeout(() => {
    alert(message);
  }, 100);
}




const tiles = document.querySelectorAll(".tile");
tiles.forEach((tile) => {
  const row = tile.getAttribute("data-row");
  const col = tile.getAttribute("data-col");
});

// Add this event listener to the "Restart" button to start a new game
const restart = document.querySelector(".restart");
restart.addEventListener("click", () => {
  gameController.startGame();
  render();

});
// Add an event listener to each tile
tiles.forEach((tile) => {
  tile.addEventListener("click", () => {
    // Get the row and column of the clicked tile
    const row = tile.getAttribute("data-row");
    const col = tile.getAttribute("data-col");

    // Make a move on the game board

    if (tile.innerHTML == "") {
      gameController.handleMove(row, col);
    }
    // Check if the game is over
    const result = gameController.isGameOver(gameBoard.getBoard());
    if (result) {
      // Announce the result of the game
      announceResult(result);


    }



  });
});


function _getbestMove(currentBoard) {
  let bestVal = +Infinity
  let bestMove = [-1, -1]

  for (let i = 0; i < 3; i++) {
    for (let j = 0; j < 3; j++) {
      if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
        let temp = currentBoard[i][j]
        // console.log(temp)
        currentBoard[i][j] = 'O'
        let moveVal = _minimax(currentBoard, 9, true)
        // console.log("move val", moveVal, bestVal)
        currentBoard[i][j] = temp
        if (moveVal < bestVal) {
          bestMove = [i, j]
          bestVal = moveVal
        }
      }
    }
  }
  // console.log("best Val:", bestVal)

  return bestMove
}


function _minimax(currentBoard, depth, isMaximixingPlayer) {
  // console.log(currentBoard, depth, isMaximixingPlayer)
  let winSymbol = gameController.isGameOver(currentBoard)
  if (depth === 0 | winSymbol === "X" | winSymbol === "O" | winSymbol === "draw") {
    let gameOutcome = gameController.isGameOver(currentBoard)
    if (gameOutcome === 'X') {
      return 10
    } else if (gameOutcome === 'O') {
      return -10
    } else {
      return 0
    }
  }

  if (isMaximixingPlayer) {
    let maxEval = -Infinity
    for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
          let temp = currentBoard[i][j]
          currentBoard[i][j] = 'X'
          let val = _minimax(currentBoard, depth - 1, false)
          // console.log(val)
          currentBoard[i][j] = temp

          if (val > maxEval) {
            maxEval = val;
          }
        }
      }
    }
    return maxEval;




  } else {
    let minEval = +Infinity
    for (let i = 0; i < 3; i++) {
      for (let j = 0; j < 3; j++) {
        if (currentBoard[i][j] !== "X" & currentBoard[i][j] !== "O") {
          let temp = currentBoard[i][j]
          currentBoard[i][j] = 'O'
          let val = _minimax(currentBoard, depth - 1, true)
          currentBoard[i][j] = temp

          if (val < minEval) {
            minEval = val;
          }
        }
      }
    }
    return minEval


  }

}
const O_btn = document.querySelector("#O-btn");
const X_btn = document.querySelector("#X-btn");

X_btn.addEventListener("click", function() {
  gameController.changeMark(this.innerHTML);
  gameController.startGame();
  console.log("X button clicked");
});

O_btn.addEventListener("click", function() {
  gameController.changeMark(this.innerHTML);
  gameController.startGame();
  console.log("O button clicked");
});
html,
body,
div,
span,
applet,
object,
iframe,
h1,
h2,
h3,
h4,
h5,
h6,
p,
blockquote,
pre,
a,
abbr,
acronym,
address,
big,
cite,
code,
del,
dfn,
em,
img,
ins,
kbd,
q,
s,
samp,
small,
strike,
strong,
sub,
sup,
tt,
var,
b,
u,
i,
center,
dl,
dt,
dd,
ol,
ul,
li,
fieldset,
form,
label,
legend,
table,
caption,
tbody,
tfoot,
thead,
tr,
th,
td,
article,
aside,
canvas,
details,
embed,
figure,
figcaption,
footer,
header,
hgroup,
menu,
nav,
output,
ruby,
section,
summary,
time,
mark,
audio,
video {
  margin: 0;
  padding: 0;
  border: 0;
  font-size: 100%;
  font: inherit;
  vertical-align: baseline;
}

body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 15px;
  font-family: 'Open Sans', "Helvetica";
}

.title {
  margin-top: 100px;
  flex: 1;
  display: flex;
  justify-content: center;
  border: 1px solid black;
  font-size: 40px;
}

.game-board-container {
  width: 50vh;
  height: 50vh;
  display: flex;
  justify-content: center;
  align-items: center;
}

.game-board {
  display: grid;
  grid-template-columns: repeat(3, minmax(100px, 1fr));
  grid-template-rows: repeat(3, minmax(100px, 1fr));
  justify-content: center;
  align-items: center;
  width: 100%;
  height: 100%;
  grid-gap: 1px;
  /* This creates a 1px gap between cells */
}

.game-board div {
  width: 100%;
  height: 100%;
  outline: 1px solid black;
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 100px;
}

.game-board div:hover {
  cursor: pointer;
}

.bottom-menu {
  margin-top: 100px;
  ;
  display: flex;
  width: 50vh;
  height: 50px;
  text-align: center;
}

.bottom-menu div {
  flex: 1;
  display: flex;
  justify-content: center;
  align-items: center;
}

button {
  width: 100%;
  height: 100%;
  border: none;
  box-shadow: 1px 1px 1px grey;
  outline: 1px solid black;
}

button:hover {
  box-shadow: 3px 3px 2px grey;
  cursor: pointer
}

span {
  outline: 1px solid black;
  height: 100%;
  display: flex;
  align-items: center;
}

.chooseXO {
  height: 50px;
}

.closed {
  display: none !important;
}

#X-btn {
  background-color: green;
}

#O-btn {
  background-color: red;
}
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <link rel="stylesheet" href="style.css">
  <script src="script.js" defer></script>
</head>

<body>
  <div class="title">
    <h1>Tic-tac-toe</h1>
  </div>
  <div class="game-board-container">
    <div class="game-board">
      <div class="tile" data-row="0" data-col="0">X</div>
      <div class="tile" data-row="0" data-col="1">O</div>
      <div class="tile" data-row="0" data-col="2">X</div>
      <div class="tile" data-row="1" data-col="0">O</div>
      <div class="tile" data-row="1" data-col="1">X</div>
      <div class="tile" data-row="1" data-col="2">O </div>
      <div class="tile" data-row="2" data-col="0">x</div>
      <div class="tile" data-row="2" data-col="1">O</div>
      <div class="tile" data-row="2" data-col="2">X</div>
    </div>
  </div>
  <div class="bottom-menu">
    <div class="menu-left">
      <button class="restart">Restart</button>
    </div>
    <div class="menu-right">
      <button class=chooseXO-btn>Choose your letter</button>
      <div class="chooseXO closed">
        <button id="X-btn">X</button>
        <button id="O-btn">O</button>
      </div>
    </div>
  </div>
</body>

</html>

© www.soinside.com 2019 - 2024. All rights reserved.