Javascript 检查数组的更好方法
我正在做一个井字游戏,在如何简化一些检查方面遇到了困难。下面你会看到一个水平、垂直和对角线的检查,看一个玩家是否赢了 问题:在不重复这么多代码的情况下,我可以用什么来简化这个问题?我们非常感谢在正确方向上的任何指导 该数组如下所示:Javascript 检查数组的更好方法,javascript,arrays,sorting,Javascript,Arrays,Sorting,我正在做一个井字游戏,在如何简化一些检查方面遇到了困难。下面你会看到一个水平、垂直和对角线的检查,看一个玩家是否赢了 问题:在不重复这么多代码的情况下,我可以用什么来简化这个问题?我们非常感谢在正确方向上的任何指导 该数组如下所示: gridArray: [ ['', '', ''], ['', '', ''], ['', '', ''], ] 播放时,playerTurn变量只是从x变为o // Horizontal check state.gridArray.m
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!');
}
}
谢谢 您可以尝试使用数字值,如1和4,而不是使用字符串检查“X”或“O”的值,这样可以对每个轴的值求和。然后,如果其值为0,则该轴上没有移动,如果该值为3,则该轴的“X”移动获胜,如果其值为12,则该轴的“O”移动获胜
thx@4castle为了指出这一点,我做了更正,而不是用字符串来检查“X”或“O”的值。你可以尝试使用数字值,如1和4,以这种方式对每个轴的值求和。然后,如果其值为0,则该轴上没有移动,如果该值为3,则该轴的“X”移动获胜,如果其值为12,则该轴的“O”移动获胜
thx@4castle为了指出这一点,这确实是一个假阳性,我做了更正您可以使用稍微不同的数据结构,只有一维和数字内容。然后,您可以定义另一个变量,该变量列出该结构中表示赢的所有三元组索引。通过这种设置,检测胜利的功能几乎变成一行:
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));
}
注:网格中的数值为1表示“X”,2表示“O”。使用字符串display=['''X','O']
很容易将一个转换为另一个
可供替代的
如果你真的想得到高效的代码,你可以回到位操作,用两个整数来表示网格,一个用于“X”位置,另一个用于“O”位置。您将使用每个整数的9位。使用相同的原则,您可以定义构成win的所有位掩码,并使用这些掩码执行&
,以查看是否有匹配项
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);
}
您可以使用稍微不同的数据结构,只有一维和数字内容。然后,您可以定义另一个变量,该变量列出该结构中表示赢的所有三元组索引。通过这种设置,检测胜利的功能几乎变成一行:
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));
}
注:网格中的数值为1表示“X”,2表示“O”。使用字符串display=['''X','O']
很容易将一个转换为另一个
可供替代的
如果你真的想得到高效的代码,你可以回到位操作,用两个整数来表示网格,一个用于“X”位置,另一个用于“O”位置。您将使用每个整数的9位。使用相同的原则,您可以定义构成win的所有位掩码,并使用这些掩码执行&
,以查看是否有匹配项
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);
}
使用嵌套的
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;
}
函数whowen(网格){
var i,j,
rX,rO,
cX公司,
ddX,ddO,
杜,杜,;
ddX=ddO=duX=duO=0;
对于(i=0;i<3;++i){
rX=rO=cX=cO=0;
对于(j=0;j<3;++j){
如果(网格[i][j]=='x')++rX;
else if(网格[i][j]='o')++rO;
如果(网格[j][i]=='x')++cX;
else if(grid[j][i]=='o')++cO;
}
如果(网格[i][i]=='x')++ddX;
else if(网格[i][i]=='o')++ddO;
如果(网格[2-i][i]=='x')++duX;
else if(grid[2-i][i]=='o')++duO;
}
if(数学最大值(rX,cX,ddX,duX)==3)返回'x';
if(Math.max(rO,cO,ddO,duO)==3)返回'o';
返回null;
}
使用嵌套的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;
}
函数whowen(网格){
var i,j,
rX,rO,
cX公司,
ddX,ddO,
杜,杜,;
ddX=ddO=duX=duO=0;
对于(i=0;i<3;++i){
rX=rO=cX=cO=0;
对于(j=0;j<3;++j){
如果(网格[i][j]=='x')++rX;
else if(网格[i][j]='o')++rO;
如果(网格[j][i]=='x')++cX;
else if(grid[j][i]=='o')++cO;
}
如果(网格[i][i]=='x')++ddX;
else if(网格[i][i]=='o')++ddO;
如果(网格[2-i][i]=='x')++duX;
else if(grid[2-i][i]=='o')++duO;
}
if(数学最大值(rX,cX,ddX,duX)==3)返回'x';
if(Math.max(rO,cO,ddO,duO)==3)返回'o';
返回null;
}
位板和查找表
测试获胜位置最有效的方法之一是使用和查找表
位盘在国际象棋引擎中很常用,其中64位整数的每一位都描述了一个正方形的给定属性,例如“一块白色的棋子在这个正方形上”或“一个主教在这个正方形上”
对于Tic-Tac-Toe,我们只需要两个比特板来描述游戏:一个用于“X”侧,另一个用于“O”侧。每个位板由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)
让我们看看位置是如何编码的,这里是“X”侧:
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; });
}
当然,对于这样一个简单的游戏来说,这有点过头了,但同样的想法也适用于更复杂的游戏
此外,如果您想实现“人机对抗”版本,您的AI可以使用isWin[]
快速评估