如何在自定义行列数的JavaScript+HTML井字棋游戏中实现对角线获胜检测?
Fixing Diagonal Win Detection for Custom Tic Tac Toe
Hey there! Great job getting the row and column win checks working for your customizable Tic Tac Toe game. Let's add the diagonal win detection, plus clean up a few small bugs in your existing code.
First, Let's Fix Minor Issues in Your Original Code
- You had
var Array;which is invalid (Array is a built-in JavaScript constructor) – we can remove this since you're usingintBoardfor the game state. - The unused
torvariable can be deleted to keep code clean. - Your table cells had an extra space in the ID (
id='" + idNum.toString() + " ') – this broke the row/column calculation when a cell was clicked, so we'll remove that space. - You repeated win check logic for Player X and O – we'll refactor that into a reusable function to keep code DRY (Don't Repeat Yourself).
Adding Diagonal Win Detection Logic
Diagonal wins come in two types:
- Top-left to bottom-right (main diagonal): All cells on this diagonal share the same
row - columnvalue as the clicked cell. - Top-right to bottom-left (anti-diagonal): All cells on this diagonal share the same
row + columnvalue as the clicked cell.
We'll create a helper function checkWin(row, col, player) that handles all win checks (rows, columns, both diagonals) in one place.
Modified Full Code
// Initialize game variables let rows; let cols; let intBoard; let showfirst = 0; function XO() { rows = +prompt("Enter rows : "); cols = +prompt("Enter cols : "); // Create 2D array for game state (0 = empty, 1 = X, 2 = O) intBoard = new Array(rows); for (let r = 0; r < rows; r++) { intBoard[r] = new Array(cols).fill(0); } let idNum = 0; let strToShow = "<table border='1'>"; for (let r = 0; r < rows; r++) { strToShow += "<tr>"; for (let c = 0; c < cols; c++) { // Fixed: Removed extra space in cell ID strToShow += `<td id='${idNum}' onclick='TdClicked(this)' width='80px' height='80px'> <img src='background.jpg' width='80px' height='80px' /> </td>`; idNum++; } strToShow += "</tr>"; } strToShow += "</table>"; document.write(strToShow); } function TdClicked(tdClickedThis) { const idClicked = tdClickedThis.id; const rowClicked = Math.floor(idClicked / cols); const colClicked = idClicked % cols; // Prevent overwriting already occupied cells if (intBoard[rowClicked][colClicked] !== 0) return; if (showfirst === 0) { // Player X's turn tdClickedThis.innerHTML = "<img width='80px' height='80px' src='wolf.jpg'/>"; showfirst++; intBoard[rowClicked][colClicked] = 1; if (checkWin(rowClicked, colClicked, 1)) { alert("PLAYER X WIN!!"); // Optional: Uncomment below to reset game after win // XO(); } } else { // Player O's turn tdClickedThis.innerHTML = "<img width='80px' height='80px' src='fox.png'/>"; showfirst--; intBoard[rowClicked][colClicked] = 2; if (checkWin(rowClicked, colClicked, 2)) { alert("PLAYER O WIN!!"); // Optional: Uncomment below to reset game after win // XO(); } } } // Helper function to check all win conditions function checkWin(row, col, player) { // Check row win let rowWin = true; for (let c = 0; c < cols; c++) { if (intBoard[row][c] !== player) { rowWin = false; break; } } if (rowWin) return true; // Check column win let colWin = true; for (let r = 0; r < rows; r++) { if (intBoard[r][col] !== player) { colWin = false; break; } } if (colWin) return true; // Check top-left to bottom-right diagonal let mainDiagWin = true; const mainDiagDiff = row - col; for (let r = 0; r < rows; r++) { const c = r - mainDiagDiff; // Skip if column is out of bounds if (c < 0 || c >= cols || intBoard[r][c] !== player) { mainDiagWin = false; break; } } if (mainDiagWin) return true; // Check top-right to bottom-left diagonal let antiDiagWin = true; const antiDiagSum = row + col; for (let r = 0; r < rows; r++) { const c = antiDiagSum - r; // Skip if column is out of bounds if (c < 0 || c >= cols || intBoard[r][c] !== player) { antiDiagWin = false; break; } } if (antiDiagWin) return true; // No win detected return false; }
Key Changes Explained
- Reusable
checkWinfunction: Eliminates duplicate code by handling all win checks for both players in one place. - Diagonal checks:
- For the main diagonal, we calculate the
row - columndifference of the clicked cell, then verify all cells along that diagonal belong to the current player. - For the anti-diagonal, we use the
row + columnsum of the clicked cell to find and verify all cells on that diagonal.
- For the main diagonal, we calculate the
- Occupied cell protection: Added a check to stop players from overwriting already filled cells.
- Cleaner syntax: Used template literals for easier HTML string construction, and replaced
varwithlet/constfor better variable scoping.
内容的提问来源于stack exchange,提问作者Roni ev
相关产品推荐
相关产品推荐

