关于javascript的Tic tac toe游戏bug

时间:2014-02-09 20:19:30

标签: javascript jquery tic-tac-toe

我在使用 html / css / javascript (使用jquery)编码的tictactoe游戏时遇到错误。

大多数时候游戏运作正常但在某些情况下(似乎它不依赖于棋盘上棋子的位置或动作的顺序,我还没有设法找出它的情况)因为它很随意而中断了它会给出错误的赢家数字(有时甚至会在任何人赢得时显示胜利警告)并且它会改变预期的部分(当玩家2正在玩时它将玩家1件放入其中)。

每当此错误发生时,它会显示获胜者的警报(总是错误的获胜者),并且当游戏重置时,最后点击的位置不会重置。

我已经检查过函数 WhoWins(board)是否正常工作。

JAVASCRIPT:

const NO_WINNER = 0;
const PL1 = 1;
const PL2 = 2;
const FREE = 0;
const PIECEPL1 = 'X';
const PIECEPL2 = 'O';

$(document).ready(function() {
    TicTacToe();
});

// **** ACTION ****
function TicTacToe() {
    console.log("Game start");
    // Initialization of variables
    var moves = 0;
    var board = [[FREE, FREE, FREE],[FREE, FREE, FREE],[FREE, FREE, FREE]];
    var winner = NO_WINNER;
    $( ".square" ).html( "" ); // Reset of board
    $( "#pnum" ).html( PL1 ); // Player 1 starts
    StartMove(moves, board);
}

// **** ACTION ****
// PRE: moves is integer, board is integer 3x3 matrix.
// POST: The game has been updated.
function StartMove(moves, board) {
    console.log("Move " + moves);
    // We wait for a click on some square
    $( ".square" ).each(function() {
        $( this ).on("click", function() {
            var id = $( this ).attr( "id" );
            // [id[1]][id[2]] is the position of the clicked square in the board
            var i = id[1];
            var j = id[2];
            if (board[i][j] == FREE) { // We update the board only if the clicked position isn't already marked
                if (moves%2 == 0) { // Player 1 is playing
                    $( '#' + id ).html(PIECEPL1);
                    board[i][j] = PL1;
                }
                else { // Player 2 is playing
                    $( '#' + id ).html(PIECEPL2);
                    board[i][j] = PL2;
                }
                ++moves;
                winner = WhoWins(board);
                // We check the situation of the game
                if (moves == 9 && winner == NO_WINNER) {
                    alert( "Draw!" );
                    TicTacToe(); // We start a new game
                }
                else if (winner == NO_WINNER) {
                    $( "#pnum" ).html(moves%2 + 1); // We write the number of next move's player (We add one not because it's the next move but because the players are numbered 1,2 and not 0,1)
                    StartMove(moves, board); // We start the next move
                }
                else {
                    alert( "The winner is Player " + winner );
                    TicTacToe(); // We start a new game 
                }
            }
        });
    });
}

// **** FUNCTION ****
// PRE: board is integer 3x3 matrix.
// POST: Returns integer 0 if there is no winner, integer 1 if player 1 wins or integer 2 if player 2 wins
function WhoWins(board) {
    // We check for row equality
    if (board[0][0] != FREE && board[0][0] == board[0][1] && board[0][0] == board[0][2]) return board[0][0];
    if (board[1][0] != FREE && board[1][0] == board[1][1] && board[1][0] == board[1][2]) return board[1][0];
    if (board[2][0] != FREE && board[2][0] == board[2][1] && board[2][0] == board[2][2]) return board[2][0];
    // We check for columns equality
    if (board[0][0] != FREE && board[0][0] == board[1][0] && board[0][0] == board[2][0]) return board[0][0];        
    if (board[0][1] != FREE && board[0][1] == board[1][1] && board[0][1] == board[2][1]) return board[0][1];
    if (board[0][2] != FREE && board[0][2] == board[1][2] && board[0][2] == board[2][2]) return board[0][2];
    // We check for diagonal equality
    if (board[0][0] != FREE && board[0][0] == board[1][1] && board[0][0] == board[2][2]) return board[0][0];
    if (board[0][2] != FREE && board[0][2] == board[1][1] && board[0][2] == board[2][0]) return board[0][2];
    return NO_WINNER;
}

HTML:

<!DOCTYPE html>
<html>
    <head>
        <script type = "text/javascript" src = "jquery-2.1.0.min.js"> </script>
        <script type = "text/javascript" src = "tictactoe.js"> </script>
        <link rel = "stylesheet" type = "text/css" href = "tictactoe.css">
        <title> Tic-tac-toe </title>
    </head>
    <body>
        <header></header>
        <div id = "board">
            <div class = "square" id = "p00"></div> <!-- It's important for the id to not change, as it identifies the position of the square in the board -->
            <div class = "square" id = "p01"></div>
            <div class = "square" id = "p02"></div>
            <div class = "square" id = "p10"></div>
            <div class = "square" id = "p11"></div>
            <div class = "square" id = "p12"></div>
            <div class = "square" id = "p20"></div>
            <div class = "square" id = "p21"></div>
            <div class = "square" id = "p22"></div>
        </div>
        <p>Player&nbsp; <span id = "pnum"></span></p>
    </body>
</html>

CSS:

body { background-color: black }

#board {
    width: 914px;
    height: 914px;
    display: inline-block;
}

.square {
    border: dotted white 3px;
    width: 300px;
    height: 300px;
    display: inline-block;
    vertical-align: top;
    margin-right: -4px; 
    border-radius: 20%;
    text-align: center;
    line-height: 310px;
    font-family: Arial;
    font-size: 2000%;
    color: white;
}

p {
    color: white;
    font-size: 80px;
    display: inline-block;
    position: absolute;
    margin-left: 30px;
    top: -60px;
    font-family: Arial;
}

1 个答案:

答案 0 :(得分:0)

每次调用StartMove()函数时,都会应用新的click事件监听器。因此,对于每个新游戏,附加的点击事件将附加到元素。您不需要这样,因此在重新应用之前删除(取消绑定)点击事件。

I.E取而代之:

$( this ).on("click", function() {...

用这个:

$( this ).unbind("click").on("click", function() {...

因为你是新人,我也让你成为jsFiddle,以便下次发帖时你更熟悉它; - )