4

我只是有一个小问题。

我的计算机科学课的最后一项任务是用 JavaScript 编写一个井字游戏。游戏通过单击表格中的单元格并使用 function() 将 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.");
}
}

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

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

4

7 回答 7

5

我从一开始写代码,您可以在其中检查我的检查谁赢得比赛的版本。如果我的游戏版本与您不同,请不要投反对票。我只是想向您展示如何在不了解任何算法的情况下编写代码。

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

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!");
};
于 2013-05-15T19:07:12.350 回答
1

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

要检测获胜者,必须满足以下条件之一

  1. 任何一行中的所有三个单元格都相同
  2. 任何列中的所有三个单元格都相同
  3. 对角线穿过电路板的所有三个单元格都是相同的。

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

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

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

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

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

是关于如何更改元素的类的更深入的描述。

于 2013-05-15T17:41:36.230 回答
1

我看到你说你已经在 Stack Overflow 上搜索过类似的问题。我了解编程新手,用另一种语言阅读内容并不容易,但基本思想就在那里。这是一个已经完成的链接:确定井字游戏结束的算法

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

三种取胜方式是

  1. 3场比赛
  2. 3场比赛落后
  3. 3 匹配对角线。

简单的部分是行和列,只需 for 循环遍历每一行/列,看看你是否得到三个匹配,如果你得到了,那么你可以宣布获胜者。

非高效伪代码示例:

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 匹配。

任何其他你可以以平局结束比赛的事情。我建议使用链接示例中所示的计数器。

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

于 2013-05-15T17:33:09.183 回答
1

取决于您更喜欢代表董事会的方式。

我编写了一个井字游戏(在React中),并选择了一个flat 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)
))

于 2020-10-28T10:05:01.260 回答
1

我的版本,但它缺少平局游戏检查:

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;
}
于 2018-02-14T10:09:38.180 回答
1

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

例如

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

将是盯着板。

以下适用于板尺寸1,2,3,4...,对于尺寸的板nn连续x的或o需要在一行一列对角线上。

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

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

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

于 2018-06-13T21:45:25.263 回答
0

还有一些优化。

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