井字棋检查器

Tic Tac Toe Checker

我是一个自学成才的程序员,我得到了一个 TicTacToe 项目,但我卡在了以下部分。 我做了一个相对有效的 TicTacToe(灵感来自 youtube),然后我想做一个响应式 TicTacToe 矩阵,它根据第一个游戏的输入改变控制台中 X 和 O 中的数字(0-9)。但现在我一直在努力寻找一种方法来检查矩阵的获胜者哦,我正试图从最后一个 X 或 O

开始“检查”

希望看到代码更容易理解。 非常感谢您的帮助!

const statusDiv = document.querySelector('.status');
const resetDiv = document.querySelector('.reset');
const cellDivs = document.querySelectorAll('.game-cell');


// game constants
const xSymbol = '×';
const oSymbol = '○';

// game variables
let gameIsLive = true;
let xIsNext = true;
var currentPlayer = 0;



//Random generated
function getInputValue() {
  document.getElementById("formInput").style.display = "none";
  document.getElementById("container").style.display = "inline";
  let player1Input = document.getElementById("player1Input").value;
  let player2Input = document.getElementById("player2Input").value;


  currentPlayer = 1;

  var random = Math.random() * 100;
  if (random <= 60) {
    currentPlayer = 1;
    statusDiv.innerHTML = player1Input + " turn";
    statusDiv.style.color = "blue";

  }
  else {
    currentPlayer = 2;
    statusDiv.innerHTML = player2Input + " turn";
    statusDiv.style.color = "red";



  }
}
//  statusDiv.style.filter= "green";


//functions
const letterToSymbol = (letter) => letter === 'x' ? xSymbol : oSymbol;

const handleWin = (letter) => {
  gameIsLive = false;
  if (currentPlayer === 1) {
    statusDiv.innerHTML = player1Input.value + " has won!";
    statusDiv.style.color = "blue";

  } else {
    statusDiv.innerHTML = player2Input.value + " has won!";
    statusDiv.style.color = "red";
  }
};

const checkGameStatus = () => {
  const topLeft = cellDivs[0].classList[1];
  const topMiddle = cellDivs[1].classList[1];
  const topRight = cellDivs[2].classList[1];
  const middleLeft = cellDivs[3].classList[1];
  const middleMiddle = cellDivs[4].classList[1];
  const middleRight = cellDivs[5].classList[1];
  const bottomLeft = cellDivs[6].classList[1];
  const bottomMiddle = cellDivs[7].classList[1];
  const bottomRight = cellDivs[8].classList[1];




  // check winner
  if (topLeft && topLeft === topMiddle && topLeft === topRight) {
    handleWin(topLeft);
    cellDivs[0].classList.add('won');
    cellDivs[1].classList.add('won');
    cellDivs[2].classList.add('won');
  } else if (middleLeft && middleLeft === middleMiddle && middleLeft === middleRight) {
    handleWin(middleLeft);
    cellDivs[3].classList.add('won');
    cellDivs[4].classList.add('won');
    cellDivs[5].classList.add('won');
  } else if (bottomLeft && bottomLeft === bottomMiddle && bottomLeft === bottomRight) {
    handleWin(bottomLeft);
    cellDivs[6].classList.add('won');
    cellDivs[7].classList.add('won');
    cellDivs[8].classList.add('won');
  } else if (topLeft && topLeft === middleLeft && topLeft === bottomLeft) {
    handleWin(topLeft);
    cellDivs[0].classList.add('won');
    cellDivs[3].classList.add('won');
    cellDivs[6].classList.add('won');
  } else if (topMiddle && topMiddle === middleMiddle && topMiddle === bottomMiddle) {
    handleWin(topMiddle);
    cellDivs[1].classList.add('won');
    cellDivs[4].classList.add('won');
    cellDivs[7].classList.add('won');
  } else if (topRight && topRight === middleRight && topRight === bottomRight) {
    handleWin(topRight);
    cellDivs[2].classList.add('won');
    cellDivs[5].classList.add('won');
    cellDivs[8].classList.add('won');
  } else if (topLeft && topLeft === middleMiddle && topLeft === bottomRight) {
    handleWin(topLeft);
    cellDivs[0].classList.add('won');
    cellDivs[4].classList.add('won');
    cellDivs[8].classList.add('won');
  } else if (topRight && topRight === middleMiddle && topRight === bottomLeft) {
    handleWin(topRight);
    cellDivs[2].classList.add('won');
    cellDivs[4].classList.add('won');
    cellDivs[6].classList.add('won');
  } else if (topLeft && topMiddle && topRight && middleLeft && middleMiddle && middleRight && bottomLeft && bottomMiddle && bottomRight) {
    gameIsLive = false;
    statusDiv.innerHTML = 'Game is tied!';
  } else {

    xIsNext = !xIsNext;

    if (currentPlayer === 2) {
      statusDiv.innerHTML = player1Input.value + ` turn`;
      statusDiv.style.color = "blue";
      currentPlayer = 1;


    } else {
      currentPlayer = 2;
      statusDiv.style.color = "red";
      statusDiv.innerHTML = player2Input.value + ` turn`;


    }
  }
};


// event Handlers
const handleReset = () => {
  document.getElementById("formInput").style.display = "inline";
  document.getElementById("container").style.display = "none";

  xIsNext = true;
  statusDiv.innerHTML = `Press Start Game`;
  for (const cellDiv of cellDivs) {

    cellDiv.classList.remove('x');
    cellDiv.classList.remove('o');
    cellDiv.classList.remove('won');
    document.location.reload()

  }
  gameIsLive = true;
};

const handleCellClick = (e) => {

  const classList = e.target.classList;

  if (!gameIsLive || classList[1] === 'x' || classList[1] === 'o') {
    return;

  }

  if (currentPlayer === 1) {
    classList.add('playerOneColour');
  } else {
    classList.add('playerTwoColour');
  }

  if (xIsNext) {

    classList.add("x");

  } else {

    classList.add('o');

  }


  checkGameStatus();
};



// event listeners
resetDiv.addEventListener('click', handleReset);

for (const cellDiv of cellDivs) {

  cellDiv.addEventListener('click', handleCellClick);
  cellDiv.addEventListener('click', handleCellSelection);
}




















//Matrix Builder
var counter = 0;
var matrix = [];
for (var i = 0; i < 3; i++) {
  matrix[i] = [];

  for (var j = 0; j < 3; j++) {
    matrix[i][j] = [];
    matrix[i][j] = counter;
    ++counter;

  }

}


// 0,1,2,3,4,5,6,7,8
// 0,1,2,0,1,2,0,1,2
var playerCounter = 1;
var currentPlayer = 1;
function handleCellSelection(e) {
  playerCounter++;

  let htmlElement = e.target;
  let cellType = htmlElement.getAttribute("data-cell");
  let reuseNTI = numberToIndexes(cellType);
  let matrixIndex = indexInMatrix(reuseNTI[0], reuseNTI[1]);
  let isWinnerFunction = isPlayerWinner(matrix);



  function indexInMatrix(index1, index2) {
    if (currentPlayer === 2) {
      return matrix[index1].splice([index2], 1, "X")
      currentPlayer = 1;
    } else {
      return matrix[index1].splice([index2], 1, "O");
      currentPlayer = 2;

    }

  }


  function isPlayerWinner(matrix, currentPlayer) {
    if (playerCounter < 6) {
      return;
    } else {
      var xSign = "X";
      var oSign = "O";
      let rowX = 0;
      let rowO = 0;

      //TO DO CHECK COLUMN
      for (var i = 0; i < matrix[0].length; i++) {
        if (xSign === matrix[i][reuseNTI[0]]) {
          rowX++


        } else if (oSign === matrix[i][reuseNTI[0]]) {
          rowO++
          console.log(rowO)

        }



        // console.log(matrix[i, 0].lastIndexOf("X")) ;  //000↓,111↓,222↓
        // console.log(matrix[i, 0].lastIndexOf("O"));

      }
      //TO DO CHECK ROW
      for (var i = 0; i < matrix[0].length; i++) {
        if (xSign === matrix[reuseNTI[0][i]]) {

        } else if (oSign === matrix[reuseNTI[0]][i]) {

        }



        // console.log(matrix[0, i].lastIndexOf("X")) ; //row is 000->,111->,222->
        // console.log(matrix[0, i].lastIndexOf("O"));
      }
      //TO DO CHECK PRIMARY DIAGONAL
      for (var i = 0; i < matrix[0].length; i++) {
        if (xSign === matrix[i][i]) {

        } else if (oSign === matrix[i][i]) {

        }


        // matrix[i][i];
        // console.log(matrix[i, i].lastIndexOf("X"));   //012->,012->,012->
        // console.log(matrix[i, i].lastIndexOf("O"));
      }
      //TO DO CHECK SECONDARY DIAGONAL
      for (var i = 0; i < matrix[0].length; i++) {
        if (xSign === matrix[i][matrix.length - 1 - i]) {

        } else if (oSign === matrix[i][matrix.length - 1 - i]) {

        }


        // matrix[i][matrix.length - 1 - i];
        // console.log(matrix[i, matrix.length - 1 - i].lastIndexOf("X"));
        // console.log(matrix[i, [matrix.length - 1 - i]].lastIndexOf("O"));
      }

    }
  }
  isPlayerWinner(matrix);


  console.log(matrix);
}



function numberToIndexes(number) {
  let row = Math.floor(number / 3);
  let column = number % 3;
  return [row, column];
}







var cellSize = 100;
var cellSpace = 10;

var matrixRows = matrix.length;
var matrixColumns = matrix[0].length;

for (var i = 0; i < matrixRows; i++) {

  for (var j = 0; j < matrixColumns; j++) {

    var cell = document.createElement("div");

    cell.setAttribute("class", "cell");
    matrixStage.appendChild(cell);

    cell.style.top = i * (cellSize + cellSpace) + "px";
    cell.style.left = j * (cellSize + cellSpace) + "px";
  }
}

function newMatrixGrid() {
  var grid3x3 = document.getElementById("matrixMaker").value;
  if (grid3x3 == "3") {
    var matrixStage = document.querySelector("#matrixStage").style.display = "block";
  } else {
    matrixStage = document.querySelector("#matrixStage").style.display = "none";
  }
}
#player1{
  color: blue;

}
#player2{
  color: red;

}


* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  color: #545454;
  display: grid;
  font-family: sans-serif;
  justify-content: center;
}

.container {
  background: #ffffff;
  margin: 50px;
  padding: 50px;
  border-radius: 25px;
}

.title {
  text-align: center;
}

.title span {
  color: #F2EBD3;
}

.status-action {
  color:blue;
  display: flex;
  margin-top: 25px;
  font-size: 25px;
  justify-content: space-around;
  height: 30px;
}

.status span {
  
  color: red;
}

.reset {
  color: black;
  cursor: pointer;
}

.reset:hover {
  color: #10976c;
}

.game-grid {
  background: #000000;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-gap: 15px;
  margin-top: 50px;
}

.game-cell {
  background:white;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  height: 200px;
  width: 200px;
}


.playerOneColour{ 
   filter: invert(9%) sepia(100%) saturate(7261%) hue-rotate(247deg) brightness(91%) contrast(146%);
}

.playerTwoColour{

  filter: invert(14%) sepia(95%) saturate(6042%) hue-rotate(358deg) brightness(109%) contrast(117%);
} 
.x {
    
    color: transparent;
    cursor: default;
  }
  

.o {
  
  color: transparent;
  cursor: default;
}

.x::after {

  background-image: url(../Resources/X.png);
  background-size:contain;
  background-repeat: no-repeat;
  margin-top: 80px;
  content: '×';
  

}

.o::after {

  background-image: url(../Resources/O.png);
  background-size:contain;
  background-repeat: no-repeat;
  margin-top: 100px;
  content: '○';
  
  
}

.won::after {
  filter: invert(100%) sepia() saturate(10000%) hue-rotate(0deg); 
}

@media only screen and (min-width: 1024px) {
  .game-grid {
    margin-top: 25px;
    grid-gap: 10px;
  }

  .game-cell {
    height: 150px;
    width: 150px;
  }

  .x::after {
    font-size: 150px;
  }

  .o::after {
    font-size: 175px;
  }
}

@media only screen and (max-width: 540px) {
  .container {
    margin: 25px;
    padding: 25px;
  }

  .game-cell {
    height: 100px;
    width: 100px;
  }

  .x::after {
    font-size: 100px;
  }

  .o::after {
    font-size: 125px;
  }
}
  


#matrixStage{
 
  position:relative;
 
}
.cell
{
    position: absolute;
    width: 100px;
    height: 100px;
    border: 1px solid black;
    background-color: white;
}
<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Play XO</title>
    <link rel="StyleSheet" href="Styles/index.css">
</head>

<body>


    <form id="formInput">
        <h1>Play X O </h1><br>
        <label for="player1" id="player1">Player 1:</label><br>
        <input type="text" id="player1Input"><br>
        <label for="player1" id="player2">Player 2:</label><br>
        <input type="text" id="player2Input"><br><br>
        <button type="button" onclick="getInputValue();"> Start Game</button>




    </form>
    <br>

    </form>

    <div class="container" style="display:none" id="container">
        <h1 class="title">Play X O </h1>
        <div class="status-action">
            <div class="status">Player 1 turn</div>
            <div class="reset">Reset</div>
        </div>
        <div class="game-grid">
            <div class="game-cell" data-cell="0"></div>
            <div class="game-cell" data-cell="1"></div>
            <div class="game-cell" data-cell="2"></div>
            <div class="game-cell" data-cell="3"></div>
            <div class="game-cell" data-cell="4"></div>
            <div class="game-cell" data-cell="5"></div>
            <div class="game-cell" data-cell="6"></div>
            <div class="game-cell" data-cell="7"></div>
            <div class="game-cell" data-cell="8"></div>
        </div>
    </div>

    <select name="matrix-size" id="matrixMaker" onchange="newMatrixGrid()">
        <option value="3">3X3</option>
        <option value="4">4X4</option>
        <option value="5">5X5</option>

    </select>


    </br></br></br>
    <div id="matrixStage"></div>





    <script src="Scripts/index.js"></script>


</body>

</html>

我认为您可以通过忽略是否正在寻找 Xs 或 Os 来简化 isPlayerWinner 函数。您必须假设最后使用的标记不是上一轮的赢家,否则游戏已经结束。

因此,如果您有矩阵 = [[0,1,2],[3,4,5],[6,7,8]] 并且数字将逐渐替换为 x 或 o,请检查是否组合中的所有项目都相等

function isPlayerWinner(){
    for(let i=0; i<3; i++){
        const row = matrix[i][0] === matrix[i][1] && matrix[i][1] === matrix[i][2];
        const column = matrix[0][i] === matrix[1][i] && matrix[1][i] === matrix[2][i];
        if(column || row){
            return true
        }
    }
    if(matrix[0][0] === matrix[1][1] && matrix[1][1] === matrix[2][2]){
        return true;
    }
    if(matrix[0][2] === matrix[1][1] && matrix[1][1] === matrix[2][0]){
        return true;
    }
    return false
}