JavaScript TicTacToe if ...获胜者检测

时间:2013-05-15 17:05:30

标签: javascript

我只是遇到一个小问题。

我计算机科学课的最后一项任务是用JavaScript编写一个Tic-Tac-Toe游戏。游戏通过单击表格中的单元格并使用函数()将img源(一个空白图像直到被点击)切换为X或O来工作。它刚刚完成,但有一件事我无法获得

显然,这场比赛是由两名球员进行的。我需要的最后一件事就是让它(一个函数)检测玩家何时获胜并在发生这种情况时杀死脚本。我只是想不出来。我知道它涉及if语句,我尝试了几种不同的代码,但是我编写的所有代码都打破了游戏。

我确实之前已经问过这个问题了,我已经尝试点击右侧“类似问题”框中的几个链接,但所有这些链接都是我没有学过的语言(例如作为C#)。

这是我的剧本:

<script type="text/javascript" charset="ISO-8859-1">
function placeMove(value)
{
    if (document.getElementById(value).src.indexOf("FC")!=-1) //"FC" because of the FC contained in the file name. I intended for it to stand for "free cell", for easy indentification.
    {
        var turn = document.getElementById("playerturn").innerHTML;
        if (turn == "X")
        {
            document.getElementById(value).src="../Images/TicTacToeX.jpg";
            document.getElementById("playerturn").innerHTML="O";
        }
        if (turn == "O")
        {
            document.getElementById(value).src="../Images/TicTacToeO.jpg";
            document.getElementById("playerturn").innerHTML="X";
        }
    }
    else
    {
        window.alert("Tile is in use. Please select another tile.");
    }
}
function detectWin()
{

}
</script>

这是游戏发生的表格,如果它有帮助:

<table class="gametable" id="gametable" border="1">
<tr>
    <td><img onclick="placeMove('r1c1')" id="r1c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r1c2')" id="r1c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r1c3')" id="r1c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr> 
<tr>
    <td><img onclick="placeMove('r2c1')" id="r2c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r2c2')" id="r2c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r2c3')" id="r2c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
<tr>
    <td><img onclick="placeMove('r3c1')" id="r3c1" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r3c2')" id="r3c2" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
    <td><img onclick="placeMove('r3c3')" id="r3c3" class="blank" alt="blank space" src="../Images/TicTacToeFC.jpg"></img></td>
</tr>
</table>

明天将分配作业,我需要的只是最后一点代码。

非常感谢任何帮助。这是我上学期的最后一次作业。

谢谢,

凯尔

编辑:经过一些建议,这是我一直在尝试的。输入此代码将不允许玩游戏。如果只是缺少分号,请原谅我。它涉及将每个单元格中的img源设置为变量,并检查这些变量是否匹配。

我创建了9个变量,每个单元格对应一个/ X或O图像:

var pic1 = document.getElementById("r1c1").src;
var pic2 = document.getElementById("r1c2").src;
var pic3 = document.getElementById("r1c3").src;
var pic4 = document.getElementById("r2c1").src;
var pic5 = document.getElementById("r2c2").src;
var pic6 = document.getElementById("r2c3").src;
var pic7 = document.getElementById("r3c1").src;
var pic8 = document.getElementById("r3c2").src;
var pic9 = document.getElementById("r3c3").src;

这是在第一个脚本的最后:

function detectWin()
{
if (var pic1 == var pic2 && var pic3)
{
window.alert("Game won. Please reset the game.");
}
}

这显然只能检测到第一行的胜利。如果我可以让它工作,我会知道其余代码必须是什么。不过,我仍然不知道如何杀死剧本。

编辑删除一些不必要的评论和语法错误。

7 个答案:

答案 0 :(得分:3)

我从开头的代码中写道,你可以查看我的查看谁赢得游戏的版本。如果我的游戏版本不是你,请不要贬低。我只是想告诉你如何在不知道任何算法的情况下编写代码。

你只需要动力。不要下次这么快就放弃。

jsFiddle

我的版本用于检查谁赢了:

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!");
};

答案 1 :(得分:1)

我看到你说你搜索了Stack Overflow的类似问题。我理解如何对编程不熟悉,用另一种语言阅读内容并不容易,但基本思想就在那里。以下是已完成此操作的链接:Algorithm for Determining Tic Tac Toe Game Over

话虽如此,在游戏中基本上有3种方法可以赢得胜利,并且你正朝着正确的方向前进。

获胜的三种方式是

  1. 3场比赛
  2. 3匹配
  3. 3匹配对角线。
  4. 简单的部分是行和列,只是循环遍历每一行/列,看看你是否得到三个匹配,如果你这样做,那么你可以声明一个胜利者。

    非效率伪代码示例:

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

    对第2行和第3行重复。

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

    重复第2栏和第3栏。

    对角线也可以以简单的方式完成,而不使用示例中的二维数组。基本上只有两种对角胜利的可能性:

    1. var 1,5,9匹配
    2. var 3,5,7匹配。
    3. 你可以在平局中结束比赛。我建议使用链接示例中显示的计数器。

      祝你好运! - 为清晰起见而编辑 -

答案 2 :(得分:1)

我不能真诚地给你答案,但我可以引导你思考这个问题;绝不是最好的解决方案,但它至少可以让你开始。

要检测获胜者,必须确保以下一个

  1. 任何一行中的所有三个单元格都相同
  2. 任何列中的所有三个单元格都相同
  3. 对角线穿过电路板的所有三个电池都是相同的。
  4. 幸运的是,您可以循环使用表格元素,以便轻松进行检查。

    您提供的if声明存在缺陷。在您已经声明变量后,您不需要在变量之前加上var。此外,您使用&&是错误的。这将做的是检查左语句是否为真,在这种情况下是var pic1 == var pic2,然后检查右语句是否也为真,这只是var pic3。就其本身而言,这不是一个好的陈述,因为它将自动转换为Javascript对布尔值的最佳解释,在这种情况下,只要定义了pic3,就会true 。相反,你需要像if(pic1 == pic2 && pic2 == pic3)这样的东西,但我会使用除了比较图像之外的东西,这就是你正在做的事情。您可以将每个单元格的类别更改为“X”或“O”,具体取决于哪个单元格更加优雅。

    可以通过.className电话访问班级名称:

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

    Here是对如何更改元素类的更深入的描述。

答案 3 :(得分:1)

假设&#39;正方形&#39;是一个方形大小的数组,其中0表示未填充 ,1表示玩家1(x),-1表示其他玩家(O)。

e.g。

let squares = Array(3).fill(Array(3).fill(0))

将是盯着董事会。

以下适用于电路板尺寸1,2,3,4 ...对于尺寸为n的电路板,n个连续的x或o需要在行列或对角线中。

如果没有人赢了,则返回0,对于玩家1则返回1,为另一个玩家返回-1。

首先定义两个辅助函数以使代码更具可读性。

&#13;
&#13;
const add = (a, b) =>
a + b

function sum(array)  
{  
   return array.reduce(add);
}


function calculateWinner(squares) {
  // check for horizontal wins along rows and diagonals
  let winner = calculateWinnerInner(squares);
  if (winner !== 0) return winner;
  // check for possible vertical wins as well
  const stranspose = squares.map((col, i) => squares.map(row => row[i]));
  return calculateWinnerInner(stranspose);
}

 
function calculateWinnerInner(squares) {

  for (let r = 0; r < squares.length; r++) {
    if (squares[r].length === sum(squares[r])) {
      return 1;
    }
    if (squares[r].length === - sum(squares[r])) {
      return -1;
    }
  }
  const diagonal = squares.map((row, r) => squares[r][r]);

  if (squares[0].length === sum(diagonal)) {
    return 1;
  }
  if (squares[0].length === -sum(diagonal)) {
    return -1;
  }
  
 const len=squares.length;
 const crossdiagonal = squares.map((row, r) => squares[r][len-r-1]);

 if (squares[0].length === sum(crossdiagonal)) {
  return 1;
 }
 if (squares[0].length === -sum(crossdiagonal)) {
  return -1;
 }

  return 0;

}
&#13;
&#13;
&#13;

答案 4 :(得分:0)

进行一些优化。

  1. 添加机制以识别棋盘上哪些“线”永远无法获胜,因为它们至少包含两个玩家的棋子。这些都是缓存的,以防止将来检查该行并提高速度。
  2. 忽略昂贵的胜利检查,如果没有足够的棋子可以获胜(遵守规则)。例如,最快的一个玩家可以在3x3的牌面上获胜,就是在标记第5个方格时。

答案 5 :(得分:0)

我的版本,但它没有领带游戏检查:

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;

}

答案 6 :(得分:0)

取决于您希望以哪种方式代表董事会。

我已经编写了一个Tic-Tac-Toe游戏(在 React 中),并选择了一个 flat array ,因为我认为它更易于使用(也在游戏的其他方面)

我以预定义所有可能的获胜位置的方式编写了 win-detection 代码,并将表示游戏板的Array转换为两个字符串组成的数组(每个玩家一个),因此每个字符串都有该特定玩家选择的单元格索引。

/**
 * 
 * @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)
))