JavaScript TicTacToe if… Winner detection

前端 未结 7 1623
借酒劲吻你
借酒劲吻你 2020-12-21 09:22

I just have a small problem.

The final assignment in my computer science class is to write a game of Tic-Tac-Toe in JavaScript. The game works by clicking on cells w

相关标签:
7条回答
  • 2020-12-21 09:40

    My version, but it lacks the tie game check:

    var table = [
    ['','',''],
    ['','',''],
    ['','','']
    ]
    
    function GameIsOver(player) {
    var result = true;
    for (var j = 0; j < 3; j++) {     //first diagonal
        result= result && (table[j][j] == player);
    }
        if (result) {
            return gameResult = {
                result: result,
                player: player
            };
        }
    result = true;
    for (var j = 0; j < 3; j++) {  //second diagonal
        result= result && (table[2-j][j] == player);
    }
        if (result) {
            return gameResult = {
                result: result,
                player: player
            };
        }
    for (var k = 0; k < 3; k++) {
        result = true;
        for (var j = 0; j < 3; j++) {      //lines 
            result = result && (table[k][j] == player);
        }
        if (result) {
            return gameResult = {
                result: result,
                player: player
            };
        }    
        result = true;
        for (var j = 0; j < 3; j++) {      //colums
            result = result && (table[j][k] == player);
        }
            if (result) {
                return gameResult = {
                    result: result,
                    player: player
                };
            } 
    }
    return false;
    

    }

    0 讨论(0)
  • 2020-12-21 09:46

    I see you said you have searched Stack Overflow for similar questions. I understand how being new to programming, it's not easy to read something in another language but the fundamental idea is there. Here is a link where this is already done: Algorithm for Determining Tic Tac Toe Game Over.

    That being said, there are basically 3 ways to win in the game, and you are headed in the right direction with your vars.

    The three ways to win are

    1. 3 matches across
    2. 3 matches down
    3. 3 matches diagonal.

    The easy parts are the rows and columns, simply for loop through each row/column and see if you get three matches, if you do, then you can declare a winner.

    Non-efficient Pseudo-code Example:

    if pic1, pic2, and pic3 are the same
    alert user X or O has won
    end the game.
    

    Repeat for row 2, and row 3.

    if pic1, pic4, and pic7 are the same
    alert user X or O has won
    end the game.
    

    Repeat for column 2 and 3.

    The diagonal can be done in a simple fashion as well, without using the two dimensional array in the example. There are basically only two diagonal win possibilities:

    1. var 1, 5, 9 match
    2. var 3, 5, 7 match.

    Anything else you can end the game in a draw. I would recommend using the counter as shown in the link example.

    Good luck! -- edit for clarity --

    0 讨论(0)
  • 2020-12-21 09:52

    I write from begining code where you can check my version of checking who win game. Dont downvote if my version of game is another than you. I just want to show you how you can write code without knowledge of any algorithm.

    You just need motivation. Don't give up next time so fast.

    jsFiddle

    My version for checking who win:

    var checkResult = function(){
        $("table tr").each(function(i, val){
            $(this).find('td').each(function(j, val2){
                arr[i][j] = parseInt($(this).attr("data-points"));
            });
        });
    
        for(var i = 0; i<3;i++){
            var rowSum = 0;
            for(var j = 0; j<3;j++){
                rowSum += arr[i][j];
            }
            if(rowSum === 3)
                alert("Circle WIN!");
            else if(rowSum === -3)
                alert("Cross WIN!");
        }
    
        for(var i = 0; i<3;i++){
            var colSum = 0;
            for(var j = 0; j<3;j++){
                colSum += arr[j][i];
            }
            if(colSum === 3)
                alert("Circle WIN!");
            else if(colSum === -3)
                alert("Cross WIN!");
        }
    
        if(arr[0][0] + arr[1][1] + arr[2][2] === 3)
            alert("Circle WIN!");
        else if(arr[0][0] + arr[1][1] + arr[2][2] === -3)
            alert("Cross WIN!");
    
        if(arr[2][0] + arr[1][1] + arr[0][2] === 3)
            alert("Circle WIN!");
        else if(arr[2][0] + arr[1][1] + arr[0][2] === -3)
            alert("Cross WIN!");
    };
    
    0 讨论(0)
  • 2020-12-21 09:57

    A few more optimizations.

    1. Add mechanism to identify which "lines" on a board can never be winning because they contain at least 1 of both players' pieces. These are cached to prevent future checks of that line and improve speed.
    2. Ignore expensive win check if there are not enough pieces for a win to be possible (while following the rules). For example, the soonest a player could win on a 3x3 board is when marking the 5th square.
    0 讨论(0)
  • 2020-12-21 10:02

    Depending on which way you prefer the board to be represented.

    I've coded a Tic-Tac-Toe game (in React), and chose a flat array, because I believe it is easier to work with (also in other aspects of the game)

    I've authored my win-detection code in a manner where all possible winning positions are pre-defined, and the Array representing the game board is converted into an array of two strings (one per player), so each of the strings has the cells indices of which this particular player had selected.

    /**
     * 
     * @param {Array} board - flat array representation of the board, 
     * from right to left, top to bottom, Ex.
     * [1,2,2,1,1,2,1,2,1] 
     */
    function checkWin(board){
      // all possible winning combinations (of cells filled by the same player)
      const winMap = [123, 456, 789, 147, 258, 369, 357, 159]
    
      // convert the board to array represening the filled cells, per player.
      // each array item is a string of only the cells (indices) filled by a player
      const moves = board.reduce((players, v, i) => {
        if(v) players[v-1] += i+1
        return players
      }, ['', ''])
    
    // console.log(JSON.stringify(moves))
    
      // find & return the winning combination
      const winningMove = winMap.find(comb =>
        moves.some(m => // there are only 2 sets of moves, one for each player
          // break down the current combination to array and check if every item exists
          // also in the current set of moves. quit on first match.
          comb.toString().split('').every(c => m.includes(c))
        )
      )
    
      return winningMove ?
        { // get the first number of the winning-move, 
          // substract 1 from it, and use as index to find which
          // player played that move from the board Array
          player: board[winningMove.toString()[0] - 1],
          move: winningMove
        } 
        : false
    }
    
    
    // sample tests:
    [
      [1,1,1,2,2,2],       // player 1 wins, horizontal, row 1
      [1,2,2,1,,,1],       // player 1 wins, vertical, col 1
      [2,1,1,1,2,1,2,1,2], // player 2 wins, diagonal to right
      [1,1,2,1,2,1,2,1,2], // player 2 wins, diagonal to left
      [1,2,1,1,2,1,2,1,2]  // no win
    ].forEach(board => console.log(
      checkWin(board)
    ))

    0 讨论(0)
  • 2020-12-21 10:04

    I can't in good faith give you the answer to this, but I can walk you through one way of thinking about this problem; by no means is it the best solution, but it could get you at least a start.

    To detect a winner, it must be true that one of the following holds:

    1. All three cells in any row are the same
    2. All three cells in any column are the same
    3. All three cells traversing the board diagonally are the same.

    Fortunately, you can loop over your table elements to make this check easily.

    The if statement you provided is flawed. You do not need to precede your variables with var after you have declared them already. Additionally, your use of && is wrong. What this will do is check to see if the left statement is true, which in this case is var pic1 == var pic2, then checks if the right statement is also true, which is simply var pic3. By itself, this is not a good statement, since it will be automatically cast to Javascript's best interpretation of a boolean, which in this case is true as long as pic3 is defined. Instead, you will need something like if(pic1 == pic2 && pic2 == pic3), but I would use something besides comparing the images, which is what you're doing. You could change the class of each cell to "X" or "O" depending on which piece goes there, which would be a little more elegant.

    Class names can be accessed via the .className call:

    <div id="foo" class="bar"></div>
    
    <script>
        document.getElementById("foo").className; //returns "bar"
    </script>
    

    Here is a more in-depth description of how to change an element's class.

    0 讨论(0)
提交回复
热议问题