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

PHP井字棋游戏问题:点击格子无法放置X的解决方案

修复PHP井字棋点击不显示X的问题

你的代码存在两个核心问题:

  • 请求方式不匹配:前端点击格子用GET传递参数,但后端只处理POST请求,导致用户的操作没被处理。
  • 状态未持久化:HTTP是无状态协议,每次页面刷新都会重新初始化空棋盘,之前的操作记录会丢失。

以下是修改后的完整代码,附关键修改说明:

<!DOCTYPE html>
<html>
<head>
    <title>Tic Tac Toe</title>
    <style>
        /* Styling for the game board */
        table {
            border-collapse: collapse;
            margin: auto;
            font-size: 25px;
            font-weight: bold;
        }
        td {
            width: 50px;
            height: 50px;
            border: 1px solid black;
            text-align: center;
            vertical-align: middle;
            cursor: pointer;
        }
        td:hover {
            background-color: #ccc;
        }
        form {
            margin: 0;
            padding: 0;
        }
        button {
            font-size: inherit;
            font-weight: inherit;
        }
    </style>
</head>
<body>
    <?php
        // 开启Session,用于保存棋盘状态
        session_start();

        // 初始化棋盘:优先从Session读取,不存在则创建空棋盘
        if (!isset($_SESSION['board'])) {
            $_SESSION['board'] = array(
                array("", "", ""),
                array("", "", ""),
                array("", "", "")
            );
        }
        $board = $_SESSION['board'];

        // 检查玩家是否获胜
        function checkWin($board, $player) {
            // 横向检查
            for ($i = 0; $i < 3; $i++) {
                if ($board[$i][0] == $player && $board[$i][1] == $player && $board[$i][2] == $player) {
                    return true;
                }
            }

            // 纵向检查
            for ($i = 0; $i < 3; $i++) {
                if ($board[0][$i] == $player && $board[1][$i] == $player && $board[2][$i] == $player) {
                    return true;
                }
            }

            // 对角线检查
            if ($board[0][0] == $player && $board[1][1] == $player && $board[2][2] == $player) {
                return true;
            }
            if ($board[0][2] == $player && $board[1][1] == $player && $board[2][0] == $player) {
                return true;
            }

            return false;
        }

        // 检查是否平局
        function checkTie($board) {
            for ($i = 0; $i < 3; $i++) {
                for ($j = 0; $j < 3; $j++) {
                    if ($board[$i][$j] == "") {
                        return false;
                    }
                }
            }
            return true;
        }

        // 处理玩家操作:兼容GET和POST请求
        if (($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['row'], $_POST['col'])) || 
            (isset($_GET['row'], $_GET['col']))) {
            // 获取落子位置
            $row = isset($_POST['row']) ? $_POST['row'] : $_GET['row'];
            $col = isset($_POST['col']) ? $_POST['col'] : $_GET['col'];

            // 仅允许空格子落子
            if ($board[$row][$col] == "") {
                // 玩家落子
                $board[$row][$col] = "X";

                // 检查玩家获胜
                if (checkWin($board, "X")) {
                    echo "<h1>你赢了!</h1>";
                    unset($_SESSION['board']);
                    exit();
                }

                // 检查平局
                if (checkTie($board)) {
                    echo "<h1>平局!</h1>";
                    unset($_SESSION['board']);
                    exit();
                }

                // 电脑随机落子
                do {
                    $comp_row = rand(0, 2);
                    $comp_col = rand(0, 2);
                } while ($board[$comp_row][$comp_col] != "");
                $board[$comp_row][$comp_col] = "O";

                // 检查电脑获胜
                if (checkWin($board, "O")) {
                    echo "<h1>你输了!</h1>";
                    unset($_SESSION['board']);
                    exit();
                }

                // 检查平局
                if (checkTie($board)) {
                    echo "<h1>平局!</h1>";
                    unset($_SESSION['board']);
                    exit();
                }

                // 更新Session中的棋盘状态
                $_SESSION['board'] = $board;
            }
        }
    ?>

    <h1>井字棋游戏</h1>

    <table>
        <?php
            // 渲染棋盘
            for ($i = 0; $i < 3; $i++) {
                echo "<tr>";
                for ($j = 0; $j < 3; $j++) {
                    // 使用POST表单提交落子请求
                    echo "<td>";
                    echo "<form method='post' style='width:100%;height:100%;'>";
                    echo "<input type='hidden' name='row' value='$i'>";
                    echo "<input type='hidden' name='col' value='$j'>";
                    echo "<button type='submit' style='width:100%;height:100%;border:none;background:none;cursor:pointer;'>";
                    echo $board[$i][$j];
                    echo "</button>";
                    echo "</form>";
                    echo "</td>";
                }
                echo "</tr>";
            }
        ?>
    </table>

</body>
</html>

关键修改点说明:

  • Session状态持久化:通过session_start()开启会话,将棋盘状态存储在$_SESSION['board']中,确保页面刷新后不会丢失落子记录。
  • 请求方式兼容:修改后端逻辑,同时处理GET和POST请求,保证玩家的点击操作能被正确接收。
  • 前端提交优化:将每个格子的点击改为POST表单提交,既符合HTTP语义,又避免URL暴露参数,同时保证点击区域覆盖整个格子。
  • 落子合法性检查:增加空格子判断,防止重复落子。
  • 游戏结束重置:胜负或平局后清除Session中的棋盘状态,方便启动新游戏。

内容的提问来源于stack exchange,提问作者Christian Placido

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 08:48:11