首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >JavaScript中的Gomoku板

JavaScript中的Gomoku板
EN

Code Review用户
提问于 2020-02-04 03:41:25
回答 3查看 630关注 0票数 4

编辑:结果如下:http://gomokuu.glitch.me/

这是我的gomoku密码。我是用JavaScript和HTML做的。我认为checkWinner函数可以改进或缩短。此外,职能是否应该重新组织?

以下是代码:

Javascript:

代码语言:javascript
复制
var turn = 0;
var width = 15;
var height = 15;
var gameOver = false;
var board = Array(width * height);

function announceWinner(winner) {
  console.log("a");
  if (winner == 0) {
    window.alert("X wins");
  }
  if (winner == 1) {
    window.alert("O wins");
  }
  if (winner == 2) {
    window.alert("Board filled");
  }
}

function checkWinner() {
  var filled = true;
  for (var i = 0; i < board.length; i++) {
    if (board[i] == undefined) filled = false;
    if (board[i] !== undefined) {
      if (
        (board[i] == board[i + 1] &&
          board[i + 1] == board[i + 2] &&
          board[i + 2] == board[i + 3] &&
          board[i + 3] == board[i + 4]) ||
        (board[i] == board[i + width] &&
          board[i + width] == board[i + 2 * width] &&
          board[i + 2 * width] == board[i + 3 * width] &&
          board[i + 3 * width] == board[i + 4 * width]) ||
        (board[i] == board[i + 1 + width] &&
          board[i + 1 + width] == board[i + 2 + 2 * width] &&
          board[i + 2 + 2 * width] == board[i + 3 + 3 * width] &&
          board[i + 3 + 3 * width] == board[i + 4 + 4 * width]) ||
        (board[i] == board[i - 1 + width] &&
          board[i - 1 + width] == board[i - 2 + 2 * width] &&
          board[i - 2 + 2 * width] == board[i - 3 + 3 * width] &&
          board[i - 3 + 3 * width] == board[i - 4 + 4 * width])
      ) {
        gameOver = true;
        announceWinner(board[i]);
      }
    }
  }
  if (filled) {
    announceWinner(2);
  }
}

function tileClick(row, tile) {
  var clicked = document.getElementById("board").children[row].children[tile];
  if (clicked.innerHTML || gameOver) return;
  board[tile + row * width] = turn;
  if (turn) {
    clicked.innerHTML = "o";
    clicked.style.color = "red";
    turn = 0;
  } else {
    clicked.innerHTML = "x";
    clicked.style.color = "blue";
    turn = 1;
  }
  checkWinner();
}

//generate board and listen to click event
var domBoard = document.createElement("table");
domBoard.id = "board";
for (let i = 0; i < height; i++) {
  var row = document.createElement("tr");
  for (let j = 0; j < width; j++) {
    var tile = document.createElement("td");
    tile.onclick = function() {
      tileClick(i, j);
    };
    row.appendChild(tile);
  }
  domBoard.appendChild(row);
}
document.body.appendChild(domBoard);

HTML:

代码语言:javascript
复制
<!DOCTYPE html>
<html>
  <head>
    <title>gomoku</title>
    <link rel="stylesheet" href="style.css" />
  </head>
  <body>
    <script src="script.js"></script>
  </body>
</html>
EN

回答 3

Code Review用户

发布于 2020-02-05 03:25:46

我没有时间给您一个完整的评论,所以我将添加一些关于checkWinner的评论:

  • 如果从它中删除全局状态的突变,它会读得更好。使其成为返回truefalse的纯函数。
  • 您可以考虑使用2D数组作为数据结构。这是没有必要的,但它更自然地映射到视觉板,并可能清理一些您的逻辑。

至于复制,您可以通过引入一个助手函数来捕获每个块中重复的抽象逻辑,从而删除其中的许多内容。这也将澄清检查胜利者的高层次逻辑:

代码语言:javascript
复制
function checkWinner() {
  for (var i = 0; i < board.length; i++) {
    var rightWin = winAt(i, 1)
    var downWin = winAt(i, width)
    if (rightWin || downWin) return true
  }
  return false
}

function winAt(i, step) {
  if ( board[i] === undefined ) return false
  for ( var j = 1; j < 5; j++) {
    var nextIndex = i + (j * step)
    if ( board[i] !== board[nextIndex] ) return false
  }
  return true
}

编辑:对

问题的回答

Green Ball,对于您提到的使用2D数组的问题,有一些方法可以解决:您可以使用额外的未定义行填充,或者可以抽象一个隐藏丑陋边界检查的cell(i, j),并将其保存在一个地方。事实上,最后一点是关键,而不是使用一维或二维数组。

在当前的实现中,行周围的算术逻辑被强制输出到客户端:任何想要获得i, j对的代码都必须自己进行计算。目前发生在checkWinnertileClickboard[tile + row * width]中。它还隐式地发生在构造html的双循环中。

不管包含board的底层结构是什么,您都希望客户端代码能够作为头等公民使用“行”和“列”的概念,因为这是我们人类对此的看法。这将使代码更加自然。

票数 2
EN

Code Review用户

发布于 2020-02-04 14:07:47

在您的announceWinner()函数中,可以将多个if语句缩短为具有三元算子的单行语句,如下所示:

代码语言:javascript
复制
function announceWinner(winner) {
  console.log("a");
  window.alert(winner == 0 ? "X wins" : winner == 1 ? "O wins" : winner == 2 ? "Board filled");
}

或者,如果您确信winner始终是012,那么您可以省略以下最后一个条件:

代码语言:javascript
复制
function announceWinner(winner) {
  console.log("a");
  window.alert(winner == 0 ? "X wins" : winner == 1 ? "O wins" : "Board filled");
}

checkWinner()函数中,可以将多个board数组索引推送到单个数组,然后使用每个()方法简化if语句中的多个条件,如下所示:

代码语言:javascript
复制
    function checkWinner() {
      var filled = true;
      for (var i = 0; i < board.length; i++) {
        if (board[i] == undefined) filled = false;
        
        if (board[i] !== undefined) {
          let arr1 = [board[i+1], board[i+2], board[i+3], board[i+4]];
          let arr2 = [board[i+width], board[i+2*width], board[i+3*width], board[i+4*width]];
          let arr3 = [board[i+1+width], board[i+2+2*width], board[i+3+3*width], board[i+4+4*width]];
          let arr4 = [board[i-1+width], board[i-2+2*width], board[i-3+3*width], board[i-4+4*width]];
          
          if (
            (arr1.every(e=> e == board[i])) ||
            (arr2.every(e=> e == board[i])) ||
            (arr3.every(e=> e == board[i])) ||
            (arr4.every(e=> e == board[i]))
          ) {
            gameOver = true;
            announceWinner(board[i]);
          }
        }
      }
      if (filled) {
        announceWinner(2);
      }
    }
票数 1
EN

Code Review用户

发布于 2020-02-05 08:07:54

边缘箱里有个窃听器。如果最后一步,也就是董事会的最后一步,也创造了一个获胜的行列,就会有两个公告。要解决这个问题,您必须在获胜者声明之后使用return

除此之外,代码非常容易阅读和理解。检查胜利者是相当缓慢的,如果您需要更快的代码,这就是您可以获得性能的地方。但在那之前,我建议保持原样。它很短,很简洁,很优雅。

如果希望减少代码的冗余,可以在checkWinner中定义一个助手函数:

代码语言:javascript
复制
function checkWinner() {
    function fiveSame(start, step) {
        function same(i) {
            return board[start + i * step] === board[start];
        }
        return same(1) && same(2) && same(3) && same(4);
    }

    for (const i in board) {
        if (fiveSame(i, 1) || fiveSame(i, width - 1) || fiveSame(i, width) || fiveSame(i, width + 1)) {
            ...
        }
    ...
}
票数 1
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/236619

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档