【问题标题】:Check for a row of 4 diagonally, vertically, and horizontally using javascript?使用javascript检查对角线、垂直和水平方向的一行4?
【发布时间】:2020-11-09 16:10:31
【问题描述】:

我正在制作一种扩展的井字游戏,它是 5x5 网格而不是 3x3 网格,并且需要 4 个连接而不是 3 个连接才能获胜,但我不知道如何在不检查每个网格的情况下检查获胜者可能的组合,我想知道是否有人能指出我正确的方向。我的代码在这里:

<style>
.tictac div {
padding: 10px;
border: 1px solid black;
height:30px;
width: 30px;
float: left;


}
.tictac{
clear: both;
}

</style>

<script>
var currentMove = 'x'
function addMove(box){

box.innerText = currentMove;
 if (currentMove === 'x'){currentMove = 'o'
}
else{currentMove = 'x'}
}

</script>
<div id = 'tictactoe'>
<div class = 'tictac'>
<div onclick = 'addMove(this)'></div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>


</div>

<div class = 'tictac'>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>


</div>

<div class = 'tictac'>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>


</div>
<div>

<div class = 'tictac'>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
</div>
<div>

<div class = 'tictac'>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
<div  onclick = 'addMove(this)'></div>
<div onclick = 'addMove(this)'> </div>
</div>

【问题讨论】:

  • 我猜你认为你必须单独拼出每个组合,这当然不是真的。为此,您需要一堆 for 循环。您的代码现在最大的问题是比赛场地数据没有存储在二维数组中。这一原则被称为“内容和呈现分离”,对于从正确的方向解决此类问题至关重要。用户单击应该更改您的内部数据结构,然后您根据它更新 DOM。这样你就可以简单地遍历你的数组来找到获胜条件。

标签: javascript html algorithm dom


【解决方案1】:

我假设您将游戏状态存储在 2D 数组中(除了 HTML 文档的管理):该数组将有 5 行,每行将是 5 个单个字符的数组。如果相应的方格已经玩过,它将有玩家的名字(“X”或“O”)。如果它是空的,它可能是一个空格“”。

当然有几种方法可以检查获胜位置。一种方法是将板数组转换为字符串,其中每行对应 5 个字符,并且这些行由特殊字符(如 #)分隔。因此,总字符串长度为 25 + 4 = 29。然后,您可以创建一个正则表达式,如果某处确实存在四行,则该正则表达式将找到匹配项。检测水平四连的正则表达式很简单:

([XO])\1{3}

这意味着:匹配一个 X 或一个 O,然后再匹配三个相同的。

垂直胜利可以匹配:

([XO])(.....\1){3}

这意味着:匹配一个 X 或一个 O,然后相同的字符应该恰好出现在字符串中的 6 个位置(也包括 # 分隔符),以及 12 和 18。

“反斜杠”对角线几乎相同:两次连续命中之间的距离只是多了一个:

([XO])(......\1){3}

另一条对角线的距离较短,我们需要额外的预防措施:

([XO])(?=.{0,4}#)....\1){3}

这意味着:匹配一个 X 或一个 O,然后同一个字符应该正好出现在字符串中的 5 个字符后面,并且应该验证在这两个字符之间有一个 # 字符,因此 @987654325 @ 展望。这应该像其他正则表达式一样重复,所以得到“4 in a row”。

这是一个实现:

let game = document.getElementById("tictactoe");
let board, currentPlayer;

function newGame() {
    game.innerHTML = ("<div>" + "<div></div>".repeat(5) + "</div>").repeat(5);
    board = Array.from({length: 5}, () => Array(5).fill("."));
    currentPlayer = "X";
}

function isWin() {
    let str = board.map(line => line.join("")).join("#");
    let regex = /([XO])(\1{3}|(.....\1){3}|(......\1){3}|((?=.{0,4}#)....\1){3})/;
    return regex.test(str);
}

game.addEventListener("click", function (e) {
    let node = e.target;
    let rowNode = node.parentNode;
    let row = Array.from(rowNode.children).indexOf(node);
    let col = Array.from(game.children).indexOf(rowNode);
    if (board[row][col] !== ".") return; // invalid move;
    node.textContent = board[row][col] = currentPlayer;
    currentPlayer = "OX"["XO".indexOf(currentPlayer)];
    if (isWin()) {
        alert("It's a win!");
        newGame();
    }
});

newGame();
#tictactoe>div {
    clear: both;
}
#tictactoe>div>div {
    padding: 10px;
    border: 1px solid black;
    height: 20px;
    width: 20px;
    display: table-cell;
    text-align: center;
    vertical-align: middle;
}
&lt;div id="tictactoe"&gt;&lt;/div&gt;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多