【问题标题】:Applying logics to this simple Tic Tac Toe Game将逻辑应用于这个简单的井字游戏
【发布时间】:2021-08-15 01:07:12
【问题描述】:

我一直在尝试用 JavaScript 构建 井字游戏。我在编写获胜条件的逻辑时遇到了麻烦。该程序的其他部分运行良好。


下面是我写的代码:

// Wrong Code..?

const winning = () => {
  const winning = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  for (let i = 0; i <= winning.length; i++) {
    const condition = winning[i];
    let a = spaces[condition[0]];
    let b = spaces[condition[1]];
    let c = spaces[condition[2]];
    if (a === "" || b === "" || c === "") {
      continue;
    }
    if (a === b && b === c) {
      roundWon = true;
      break;
    }
  }
};

【问题讨论】:

  • 嗯,什么逻辑?
  • 解释一下程序的当前行为是什么(当你点击程序中的按钮X时,它会打印出Y),以及预期的是什么b> 行为(应该打印出 Z 代替)。最好使用堆栈 sn-p。
  • i &lt;= winning.length 是您的第一个错误。绝对应该是@​​987654323@
  • 首先,逻辑已经是复数了,所以不要用Logics这个词,其次,每个句子的第一个字母要大写,每个句子的末尾也要加句号.这些建议将有助于使您的问题和 cmets 更具可读性、更易于理解,并将提高您获得所需解决方案的机会。现在就实际问题而言:您没有解释问题是什么,没有包含任何调试信息,也没有解释您要做什么。在你向我重复之前,请知道
  • “我做不到”或“我想不通”,并不能很好地解释您的要求。您需要询问的不是程序是否正确编写,而是一个明确定义的问题的解决方案。您提到您无法使获胜逻辑起作用,但您没有解释您正在尝试编写的获胜逻辑是什么。当您尝试开发它时,您应该对它是什么有所了解。您也没有指定特定的问题,而是说:“嘿,我正在尝试编写此逻辑,但是,我不断收到此错误。

标签: javascript tic-tac-toe


【解决方案1】:

我猜想在您的handleClick 函数中,您尝试检查该位置的空格是否仍然为空,如果是,请将其设置为currentPlayer,即XO,但这不会不工作是因为你

  1. 使用被点击的目标的id属性,它不会返回索引,而是该元素的id,并且
  2. 当你用null 填充你的spaces 数组时,你在playerWon 函数中检查空字符串。并且
  3. 除此之外,还有一些事情可以做得更好。

首先在空格数组中添加一些值(undefined 在我看来是最好的选择,我们也将在这里使用let,这样我们就可以重新定义变量进行重置)。让您的 reset 函数成为实际的重置函数。:

let spaces = [
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined
]

要解决索引问题,以便您可以更改关联单元格索引处的空格数组的值,您可以在迭代所有单元格时向handleClick 函数传递一个索引参数并添加一个点击事件监听器到他们。

cells.forEach((cell, index) => {
  cell.addEventListener("click", () => handleClick(e, index));
});

您的handleClick 函数将如下所示:

function handleClick(e, i) {
  if (spaces[i] == undefined) {
    spaces[i] = currentPlayer;
    e.target.innerText = currentPlayer;

    if (playerWon()) {
      playText.innerText = `${currentPlayer} has won!`;
      restart();
      return;
    }
    currentPlayer = currentPlayer === OPlayer ? XPlayer : OPlayer;
  }
}

在restart函数中,不用遍历spaces数组中的所有值,只需重新定义即可:

spaces = [
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined, 
  undefined
]

您还必须从 playerWon 函数返回一些内容,而不是检查空字符串,您现在应该检查 undefined

function playerWon() {
  for (let i = 0; i < winning.length; i++) {
    const condition = winning[i];
    let a = spaces[condition[0]];
    let b = spaces[condition[1]];
    let c = spaces[condition[2]];
    if (a == undefined || b == undefined || c == undefined) {
      continue;
    }
    if (a === b && b === c) {
      return true;
    }
  }
  return false
}

这些是我第一眼看到的几个大问题,我想如果你还有一些问题,试着自己解决。我在下面做了一个示例tictactoe,所以如果您遇到困难,也许可以尝试查看示例以获取帮助(代码用cmets自行解释):

// container element where the rows and cells are going to be appended
const con = document.querySelector("#tictactoe")

// the current board
let cellsArr = [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined];

// current player
let currentPlayer = Math.floor(Math.random() * 10) % 2 == 0 ? "X" : "O";
let gameOver = false;

// conditions of winning, for both X and O
const winningConditions =
  [[0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6]]


// reset function
// sets gameOver to true so players can't press buttons anymore
// resets the board (cellsArr array)
// adds a winningAlert to the DOM
// disables all buttons on the board
// resets DOM after 4 seconds
const reset = (tie) => {
  gameOver = true;
  cellsArr = [undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined, undefined]
  const winningAlert = document.createElement("p");
  winningAlert.innerText = tie ? "Its a tie!" : `${currentPlayer} has won!`;
  con.appendChild(winningAlert);
  document.querySelectorAll("button").forEach(e => e.disabled = true)
  setTimeout(() => {
    gameOver = false;
    init();
  }, 4000)
}

// check win function
// resarr -> maps through all the arrays of the winningConditions array and swaps the
//          indexes with the value of the board e.g: [1, 2, 3] => ["X", undefined, "O"]
// res -> find a array in winningConditions that has only 1 kind of element, 
//        but not undefined (Set is a data structure that only allows unique elements, so   
//        if the size of it is == 1 the array that was made of that set has only unique elements)
// if an array was found than res != undefined. If it is undefined, nothing happends, game is still on,
// else if it is undefined than reset the game, it is not a tie
// else if no array was found but all cells are already played, reset game, it is a tie
const checkWin = () => {
  const resarr = winningConditions.map(e => e.map(e => cellsArr[e]));
  const res = resarr.find(e => (new Set(e)).size == 1 && e.indexOf(undefined) == -1)
  if (res != undefined) {
    reset(false);
  } else if (cellsArr.indexOf(undefined) == -1) {
    reset(true);
  }
}

// initilizes the game
// creates a row with buttons, each 3 iterations create a new row so we have 3x3 board
// add an EventListener to each cell: 
// if gameOver or cell was already played, do nothing
// else set cell to currentPlayer, disable cell, check if won and switch player
function init() {
  let row = document.createElement("div");
  row.className = "row"
  while (con.firstChild) con.firstChild.remove();
  for (let i = 1; i < 10; i++) {
    const cell = document.createElement("button");
    row.appendChild(cell);
    if (i % 3 == 0) {
      con.appendChild(row)
      row = document.createElement("div");
      row.className = "row"
    }

    cell.addEventListener("click", () => {
      if (gameOver) return;
      if (cellsArr[i - 1] != undefined) return;
      cellsArr[i - 1] = currentPlayer;
      cell.innerText = currentPlayer;
      cell.disabled = true;
      checkWin();
      currentPlayer = currentPlayer == "X" ? "O" : "X"
    })
  }
}

init();
button {
  width: 30px;
  height: 30px;
}

.row {
  display: flex;
  flex-direction: row;
  justify-content: center;
  align-items: center;
}


p {
  width: 100%;
  text-align: center
}
&lt;div id="tictactoe"&gt;&lt;/div&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多