JavaScript TicTacToe if... 获胜者检测

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16571035/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 05:10:17  来源:igfitidea点击:

JavaScript TicTacToe if... Winner detection

javascript

提问by Jazzy663

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 within a table and using a function() to switch the img source (a blank image until clicked on) to an X or an O. It's just about done, but there's one thing I can't get.

我的计算机科学课的最后一个任务是用 JavaScript 编写一个井字游戏。该游戏的工作原理是点击表格中的单元格并使用 function() 将 img 源(点击之前的空白图像)切换为 X 或 O。它即将完成,但有一件事情我无法理解.

The game is played, obviously, by two players. The last thing I need is to get it (a function) to detect when a player wins and kill the script when this happens. I just can't figure this out. I know it involves if statements, and I've attempted several different codes, but everything I code just breaks the game.

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

I do see that this question has been asked before, and I've tried clicking on several links in the 'similar questions' box to the right, but all of them are in languages I haven't learned anything about (such as C#).

我确实看到以前有人问过这个问题,我已经尝试点击右侧“类似问题”框中的几个链接,但所有这些都是我没有学到任何东西的语言(例如 C#) .

Here is my script:

这是我的脚本:

<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>

This is the table that the game takes place in, if it helps:

如果有帮助的话,这是进行游戏的表:

<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>

The assignment is due tomorrow, and all I need is this last little bit of code.

作业明天到期,我需要的只是这最后一点代码。

Any help is greatly appreciated. This is my last assignment of the semester.

任何帮助是极大的赞赏。这是我本学期的最后一个作业。

Thanks,

谢谢,

Kyle

凯尔

EDIT: After some suggestions, here is what I've been trying. Entering this code will not allow the game to be played. If it's just a matter of missing semicolons, please forgive me. It involves setting the img source in each cell to a variable, and checking to see if those variables match.

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

There are 9 variables I created, one for each cell/X or O image:

我创建了 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;

This is at the very end of the first script:

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

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

This obviously only detects a win for the first row. If I can get this to work, I'll know what the rest of the code will have to be. I still don't know how to kill the script, though.

这显然只检测到第一行的胜利。如果我能让它工作,我就会知道剩下的代码是什么。不过,我仍然不知道如何杀死脚本。

Edited to remove some unnecessary remarks and grammatical errors.

编辑删除了一些不必要的注释和语法错误。

回答by WooCaSh

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

js小提琴

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

回答by Jordan NG

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.

我看到你说你已经在 Stack Overflow 上搜索过类似的问题。我了解刚接触编程,阅读另一种语言的内容并不容易,但基本思想就在那里。这是一个已经完成的链接: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.

话虽如此,基本上有 3 种方法可以在游戏中获胜,而您的 vars 正朝着正确的方向前进。

The three ways to win are

获胜的三种方式是

  1. 3 matches across
  2. 3 matches down
  3. 3 matches diagonal.
  1. 3场比赛
  2. 3场比赛下来
  3. 3 匹配对角线。

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.

重复第 2 行和第 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.

重复第 2 列和第 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.
  1. var 1, 5, 9 匹配
  2. var 3、5、7 匹配。

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 --

祝你好运!-- 为清楚起见进行编辑 --

回答by Bucket

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 oneof 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.
  1. 任何一行中的所有三个单元格都相同
  2. 任何列中的所有三个单元格都相同
  3. 沿对角线穿过棋盘的所有三个单元格都是相同的。

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

幸运的是,您可以遍历表格元素以轻松进行此检查。

The ifstatement you provided is flawed. You do not need to precede your variables with varafter 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 trueas 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.

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

Class names can be accessed via the .classNamecall:

可以通过.className调用访问类名:

<div id="foo" class="bar"></div>

<script>
    document.getElementById("foo").className; //returns "bar"
</script>

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

这里更深入地描述了如何更改元素的类。

回答by Alex Stancu

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;

}

}

回答by Gregor

Assume 'squares' is a Array of Arrays of square size with 0 for not filled , 1 for player 1 (x) and -1 for the other player (O).

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

e.g.

例如

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

让正方形= Array(3).fill(Array(3).fill(0))

would be the staring board.

将是凝视板。

The following works for board size 1,2,3,4... where for a board of size n, n consecutive x's or o's need to be in a row column or diagonal.

以下适用于大小为 1,2,3,4... 的棋盘,其中对于大小为 n 的棋盘,n 个连续的 x 或 o 需要在行列或对角线上。

It returns 0 if nobody won yet and 1 for player 1 and -1 for the other player.

如果没有人获胜,则返回 0,玩家 1 返回 1,其他玩家返回 -1。

First defining two helper functions to make the code more readable.

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

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;

}

回答by Νικ?λαο? Μανωλακο?

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