You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在自定义行列数的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 using intBoard for the game state.
  • The unused tor variable 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:

  1. Top-left to bottom-right (main diagonal): All cells on this diagonal share the same row - column value as the clicked cell.
  2. Top-right to bottom-left (anti-diagonal): All cells on this diagonal share the same row + column value 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 checkWin function: Eliminates duplicate code by handling all win checks for both players in one place.
  • Diagonal checks:
    • For the main diagonal, we calculate the row - column difference of the clicked cell, then verify all cells along that diagonal belong to the current player.
    • For the anti-diagonal, we use the row + column sum of the clicked cell to find and verify all cells on that diagonal.
  • 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 var with let/const for better variable scoping.

内容的提问来源于stack exchange,提问作者Roni ev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.29 02:52:44