javascript中的connect4算法
在connect 4中检查一行中的4的最佳方法是什么 我不会复制数组的代码,但它基本上是一个长度为42的数组。每个数组元素都保留绘图的X、Y位置和颜色javascript中的connect4算法,javascript,algorithm,pseudocode,Javascript,Algorithm,Pseudocode,在connect 4中检查一行中的4的最佳方法是什么 我不会复制数组的代码,但它基本上是一个长度为42的数组。每个数组元素都保留绘图的X、Y位置和颜色 var board_array = [{x:60, y:55, c:"Red"}, // ... and so on 看起来是这样的: 最初我采取了这种方法。这里是所有可能的不同方式,一个人可以赢得比赛。这并不是所有可能的4连胜位置,而是一个人可以垂直、水平和垂直获胜的所有不同方式——你仍然需要使用某种嵌套for循环进行检查 // Winni
var board_array = [{x:60, y:55, c:"Red"}, // ... and so on
看起来是这样的:
最初我采取了这种方法。这里是所有可能的不同方式,一个人可以赢得比赛。这并不是所有可能的4连胜位置,而是一个人可以垂直、水平和垂直获胜的所有不同方式——你仍然需要使用某种嵌套for循环进行检查
// Winning vertically
wins[0] = new Array(0, 7, 14, 21, 28, 35);
wins[1] = new Array(1, 8, 15, 22, 29, 36);
wins[2] = new Array(2, 9, 16, 23, 30, 37);
wins[3] = new Array(3, 10, 17, 24, 31, 38);
wins[4] = new Array(4, 11, 18, 25, 32, 39);
wins[5] = new Array(5, 12, 19, 26, 33, 40);
wins[6] = new Array(6, 13, 20, 27, 34, 41);
// Winning horizontally
wins[7] = new Array(0, 1, 2, 3, 4, 5, 6);
wins[8] = new Array(7, 8, 9, 10, 11, 12, 13);
wins[9] = new Array(14, 15, 16, 17, 18, 19, 20);
wins[10] = new Array(21, 22, 23, 24, 25, 26, 27);
wins[11] = new Array(28, 29, 30, 31, 32, 33, 34);
wins[12] = new Array(35, 36, 37, 38, 39, 40, 41);
// Winning diagonally, left to right
wins[13] = new Array(14, 22, 30, 38);
wins[14] = new Array(7, 15, 23, 31, 39);
wins[15] = new Array(0, 8, 16, 24, 32, 40);
wins[16] = new Array(1, 9, 17, 25, 33, 41);
wins[17] = new Array(2, 10, 18, 26, 34);
wins[18] = new Array(3, 11, 19, 27);
//Winning diagonally, right to left
wins[19] = new Array(20, 26, 32, 38);
wins[20] = new Array(13, 19, 25, 31, 37);
wins[21] = new Array(6, 12, 18, 24, 30, 36);
wins[22] = new Array(5, 11, 17, 23, 29, 35);
wins[23] = new Array(4, 10, 16, 22, 28);
wins[24] = new Array(3, 9, 15, 21);
如果您认为board_阵列是这样的:
//0 1 2 3 4 5 6
//7 8 9 10 11 12 13
//14 15 16 17 18 19 20
//21 22 23 24 25 26 27
//28 29 30 31 32 33 34
//35 36 37 38 39 40 41
我使用了一个3层for循环和一个计数器来检查wins阵列和board_阵列,但没有用。我只是想知道是否有更简单的方法。有很多方法可以做到这一点。如果您想摆脱循环,可以使用动态规划算法,每次添加硬币时计算结果 为此,每个字段必须保存4个值:水平值、垂直值、对角左值和对角右值
class Field {
int horiz;
int vert;
int diagLeft;
int diagRight;
}
开始时,所有字段都初始化为0(字段的所有值)。
如果向字段中添加硬币,则可以计算如下值:
fields[i][j].horiz = fields[i][j+1].horiz + fields[i][j-1].horiz + 1;
fields[i][j].vert = fields[i+1][j].vert + fields[i-1][j].vert + 1;
fields[i][j].diagLeft = fields[i+1][j+1].diagLeft + fields[i-1][j-1].diagLeft +1;
fields[i][j].diagRight = fields[i-1][j-1].diagRight + fields[i+1][j+1]
如果四个计算值中的一个大于等于4,则为赢家
要处理两个玩家,您可以为每个玩家创建一个字段数组,也可以使用正值和负值
如果您不想一直检查边界(i和j),可以在字段中添加边界(这样您就可以在左侧和右侧增加一列,在顶部和底部增加一行)“在connect 4中检查一行中的4的最佳方法是什么?”
我不会说这是“最好的方式”,但这是一种方式
大多数情况下忽略UI gubbins,该过程(在某种程度上)只是在每次在动态创建的条带搜索模式(可能包含四个连接)中删除计数器时读取网格
每一行、每一列以及前后倾斜的对角线条都是一个字符串,由沿其每一点的颜色值连接而成。用一个简单的正则表达式测试这些条带,看看是否连续提到了相同的四种计数器颜色(红色或黄色) 虽然它非常循环,但对象非常短,
check4Winner()
(读取网格)中的第一个嵌套循环整理了完成检查所需的所有数据,同时检查行以获得连接。下面的循环循环仅在未找到赢家的情况下检查柱状和对角条 一个未包含的优化(老实说,几乎不值得额外的代码)可能是删除12条对角线(每个角有三条),因为它们太短,不需要检查 如果需要导出或导入游戏数据,可以轻松使用字符串数组的临时对象(即
console.log
ged用于演示)
用户界面gubbins虽然对于寻找赢家的算法并不十分重要,但在设计时考虑了算法,因此DOM的状态是读取数据的来源。我特意关闭了代码段中的
控制台
输出,但是您可以在浏览器的控制台中看到通过读取DOM(以这种特定方式)生成的数据
var player=“red”;
常量玩家={“红色”:“黄色”,“黄色”:“红色”},
输出=document.querySelector(“输出”),
tbody=document.querySelector(“tbody”),
rows=tbody.querySelectorAll(“tr”),
准备就绪=(n)=>{
返回数组(n),填充(“”);
},
连接4=(带)=>{
常量rslt=/(?:(红色){4}|(黄色){4}/.exec(条带);
如果(!!rslt){
output.classList.add(rslt[1]| | rslt[2]);
返回true;
}
返回false;
},
check4Winner=()=>{
var条带={
h:[],
五:预备雷(七),,
f:prepArray(12),
b:准备就绪(12)
},
条带,颜色,获胜者,目录;
rows.forEach((row,ri)=>{
strip=“”;
row.querySelectorAll(“td”).forEach((单元格,ci)=>{
color=cell.getAttribute(“类”)| |“”;
strips.b[ci-ri+rows.length-1]+=颜色;
条带.f[ci+ri]+=颜色;
条带.v[ci]+=颜色;
条纹+=颜色;
} );
条。h.推(条);
赢家=赢家| |连接4(带);
} );
console.log(strips);//游戏数据对象
用于(条状目录){
if(!winner&&strips.hasOwnProperty(dir)){
条带[dir].forEach((s)=>{
获胜者=获胜者| |连接4个;
} );
}
}
},
dropCounter=(ci)=>{
var电池;
rows.forEach((row)=>{
if(!(pc=row.childNodes[ci]).getAttribute(“类”)){
cell=pc;
}
} );
如果(单元){
cell.classList.add(player=players[player]);
check4Winner();
}
};
output.addEventListener(“单击”,()=>{
output.removeAttribute(“类”);
t body.queryselectoral(“td”).forEach((c)=>{
c、 删除属性(“类别”);
} );
},假);
tbody.addEventListener(“单击”,(evt)=>{
const trg=evt.target;
如果(!output.getAttribute(“class”)和&trg.tagName.toLowerCase()=“td”){
滴落计数器(trg.cellIndex);
}
},假)代码>
表格,
输出{
盒影:5vh.5vh.2vh.5vh rgba(0,0,0,5);
}
桌子{
宽度:90vh;
边界塌陷:塌陷;
边框:2vh纯蓝色;
}
运输署{
宽度:计算(90vh/7);
背景:皇家蓝;
游标:默认值;
用户选择:无;
}
td:之前{
内容:“;
显示:块;
宽度:计算(90vh/7);
高度:计算(90vh/7);
边界半径:50%;
盒影:插图5vh.5VH2VH.5VHRGBA(0,0,0,5);
背景:白色;
}
运输署署长:之前,{
背景:红色;
}
黄道光:之前,{
背景:黄色;
}
输出{
P
"100000,212121,212000,121211,212100,000000,200000"