我正在通过一个tic tac toe游戏,并且真的碰壁了如何简化一些检查。您可以在下方找到水平,垂直和对角线检查以确定玩家是否赢了。
问题:如果不重复这么多代码,我可以使用哪些来简化此操作?非常感谢任何正确方向的指导。
数组如下所示:
gridArray: [
['', '', ''],
['', '', ''],
['', '', ''],
]
播放时,playerTurn变量只是从x变为o。
// Horizontal check
state.gridArray.map((item, index) => {
if(
item[0] === playerTurn &&
item[1] === playerTurn &&
item[2] === playerTurn) {
console.log(playerTurn + ' has won!');
}
});
// Vertical check
if(
state.gridArray[0][0] === playerTurn &&
state.gridArray[1][0] === playerTurn &&
state.gridArray[2][0] === playerTurn
) {
console.log(playerTurn + ' has won!');
}
if(
state.gridArray[0][1] === playerTurn &&
state.gridArray[1][1] === playerTurn &&
state.gridArray[2][1] === playerTurn
) {
console.log(playerTurn + ' has won!');
}
if(
state.gridArray[0][2] === playerTurn &&
state.gridArray[1][2] === playerTurn &&
state.gridArray[2][2] === playerTurn
) {
console.log(playerTurn + ' has won!');
}
// Diagonal check
if(
state.gridArray[0][0] === playerTurn &&
state.gridArray[1][1] === playerTurn &&
state.gridArray[2][2] === playerTurn
) {
console.log(playerTurn + ' has won!');
}
if(
state.gridArray[0][2] === playerTurn &&
state.gridArray[1][1] === playerTurn &&
state.gridArray[2][0] === playerTurn
) {
console.log(playerTurn + ' has won!');
}
}
谢谢!
答案 0 :(得分:4)
您可以使用略有不同的数据结构,只有1维和数字内容。然后,您可以定义另一个变量,该变量列出该结构中表示胜利的所有三元组索引。有了这个设置,检测胜利的功能几乎成了一个单一的:
var gridArray = [
0, 0, 0,
0, 0, 0,
0, 0, 0,
];
var lines = [
[0,1,2],
[3,4,5],
[6,7,8],
[0,3,6],
[1,4,7],
[2,5,8],
[0,4,8],
[2,4,6]
];
function hasWon(gridArray, lines, playerTurn) {
return lines.some(line => line.every(cell => gridArray[cell] === playerTurn));
}
注意:网格中的数值对于'X'将变为1,对于'O'将变为2。使用字符串display = [' ', 'X', 'O']
可以很容易地将一个字符串转换为另一个字符串。
如果你真的想要获得有效的代码,你可以恢复位操作,并用两个整数表示网格,一个用于'X'位置,一个用于'O'位置。您将使用每个整数的9位。使用相同的原则,您可以定义构成胜利的所有位掩码,并使用&
来查看是否匹配。
var gridArray = [0b000000000, 0b000000000]; // X bits, O bits
var lines = [
0b111000000,
0b000111000,
0b000000111,
0b100100100,
0b010010010,
0b001001001,
0b100010001,
0b001010100
];
function hasWon(gridArray, lines, playerTurn) {
return lines.some(line => (line & gridArray[playerTurn]) == line);
}
答案 1 :(得分:2)
使用嵌套的for
,此功能可以在任何状态下查看游戏,并通过计算X和Os的数量来告诉您获胜者是否和谁
function whoWon(grid) {
var i, j,
rX, rO,
cX, cO,
ddX, ddO,
duX, duO;
ddX = ddO = duX = duO = 0;
for (i = 0; i < 3; ++i) {
rX = rO = cX = cO = 0;
for (j = 0; j < 3; ++j) {
if (grid[i][j] === 'x') ++rX;
else if (grid[i][j] === 'o') ++rO;
if (grid[j][i] === 'x') ++cX;
else if (grid[j][i] === 'o') ++cO;
}
if (grid[i][i] === 'x') ++ddX;
else if (grid[i][i] === 'o') ++ddO;
if (grid[2 - i][i] === 'x') ++duX;
else if (grid[2 - i][i] === 'o') ++duO;
}
if (Math.max(rX, cX, ddX, duX) === 3) return 'x';
if (Math.max(rO, cO, ddO, duO) === 3) return 'o';
return null;
}
答案 2 :(得分:0)
而不是使用字符串来检查&#39; X&#39;的值。或者&#39; O&#39;您可以尝试使用数值,如1和4,这样可以对每个轴的值求和。然后,如果它的值为0,那么该轴上没有移动,如果该值为3,则该轴具有“X&#39;”的获胜移动。如果它的值是12,那么它就是“O&#39”的胜利之举。
thx @ 4castle指出,我做了修正确实是误报答案 3 :(得分:0)
测试获胜位置的最有效方法之一是使用bitboards和查找表。
Bitboard在Chess引擎中很常用,其中64位整数的每个位都描述了一个正方形的给定属性,例如&#39;白色方块就在这个方块上39; 或&#39;主教在这个广场上。
对于Tic-Tac-Toe,我们只需要两个位板来描述游戏:一个用于&#39; X&#39;方和一方用于&#39; O&#39;侧。每个位板由9位组成:
8 7 6 // where 8 is the most significant bit
5 4 3 // and 0 is the least significant bit
2 1 0 // (we could do it the other way around just as well)
让我们看一下如何对一个位置进行编码,这里针对&#39; X&#39;侧:
X . X 1 0 1
. X . = 0 1 0 = 101010011 in binary = 0x153 in hexadecimal
. X X 0 1 1
现在,让我们编码所有获胜的配置:
X X X . . . . . . X . . . X . . . X X . . . . X
. . . X X X . . . X . . . X . . . X . X . . X .
. . . . . . X X X X . . . X . . . X . . X X . .
0x1C0 0x038 0x007 0x124 0x092 0x049 0x111 0x054
给定一方只有2 ^ 9 = 512个可能的位置(包括一些实际上无法到达的位置)。因此,构建一个包含所有512个位置的查找表是完全可行的,这将告诉我们它是否是一个胜利:
var winMask = [ 0x1C0, 0x038, 0x007, 0x124, 0x092, 0x049, 0x111, 0x054 ],
isWin = [];
for(var n = 0; n < 512; n++) {
isWin[n] = winMask.some(function(msk) { return (n & msk) == msk; });
}
现在,我们可以做类似的事情:
if(isWin[xBoard]) {
console.log('X has won!');
}
当然,对于这样一款简单的游戏来说,这有点过分,但同样的想法也适用于更复杂的游戏。
此外,如果您想要实施“人类与计算机”这样的话。版本,您的AI可以使用isWin[]
在搜索树的叶节点上快速评估游戏的结果。
以下是使用我们刚刚描述的技术对整个游戏的简单实现。
在这里,您可以看到使用位板轻松实现的其他两项操作:
!((board[0] | board[1]) & msk)
(board[0] | board[1]) == 0x1ff
var winMask = [ 0x1C0, 0x038, 0x007, 0x124, 0x092, 0x049, 0x111, 0x054 ],
isWin = [],
board, player;
for(var n = 0; n < 512; n++) {
isWin[n] = winMask.some(function(msk) { return (n & msk) == msk; });
}
$('button').click(function() {
var msk = 0x100 >> $('button').index(this);
if(!((board[0] | board[1]) & msk)) {
$(this).html('XO'[player]);
board[player] |= msk;
if(isWin[board[player]]) {
alert('XO'[player] + ' has won!');
newGame();
}
else if((board[0] | board[1]) == 0x1ff) {
alert('This is a draw!');
newGame();
}
else {
player ^= 1;
}
}
});
newGame();
function newGame() {
board = [ 0, 0 ];
player = 0;
$('button').html('.');
}
&#13;
button { width:32px; }
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div><button></button><button></button><button></button></div>
<div><button></button><button></button><button></button></div>
<div><button></button><button></button><button></button></div>
&#13;