开局双连问(什么是四连棋,规则又是什么?)
四连棋是双人对战的棋类游戏
。棋盘被垂直放置在桌面之上,只有棋盘底部的空缺被填满棋子才能继续向上扩展。
- 棋盘一般是6行7列的垂直框架,棋子自然下落到棋盘底部或者是已有棋子的上方;
- 两名玩家各自执不同的颜色的棋子,双方轮流落子;
- 四个颜色相同的棋子率先连成一条竖线、横线或者是斜线,那么执这个颜色棋子的玩家获胜;
- 当棋盘的棋子被填满的还是没有四自连成一条直线的时候,此时双方打平。
市面上的四联棋
市面的实体四连棋简约美观,收纳便捷。围绕着棋盘规则制造出样式多样的四连棋。
六一儿童节即将到来,的确,有了实物的四连棋,那么信息时代又怎么能够少了页面版的电子四连棋呢!!!
AI四连棋实现进化史
一台设备实现双人手动下棋
页面效果实现只是通过不同阶段用户执的棋子颜色不同实现的功能。
前端代码框架搭建代码很少,主要利用grid布局和for循环实现棋盘效果。
for (let i = 0; i < rows; i++) {
for (let j = 0; j < cols; j++) {
// 创建一个div元素作为棋盘格子
const cell = document.createElement('div');
// 为格子添加 cell 类名
cell.classList.add('cell');
// 可以给每个格子添加一些自定义属性,方便后续操作,比如记录位置
cell.dataset.row = i;
cell.dataset.col = j;
board.appendChild(cell);
}
由于四连棋棋盘实际上是垂直放置在桌面上的,页面考虑到这一点设置了一个类似于重力感应的功能。
点击任意一列中的任意一个白色圆圈,棋子都会掉落在棋盘的最底部或者是已有棋子的上方。
for (let row = rows - 1; row >= 0; row--) {
if (boardState[row][col] === 0) {
// 更新棋盘状态
boardState[row][col] = currentPlayer;
// 更新UI - 确保使用正确的选择器
const targetCell = document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`);
if (!targetCell) {
console.error('找不到目标单元格:', row, col);
return;
}
targetCell.style.backgroundColor = currentPlayer === 1 ? 'rgb(227, 179, 206)' : 'rgb(246, 229, 209)';
// 检查是否获胜
if (checkWin(row, col)) {
gameOver = true;
setTimeout(() => {
alert(`游戏结束,${currentPlayer === 1 ? '紫色' : '黄色'}的棋子获胜!`);
}, 500);
return;
}
// 切换玩家
currentPlayer = currentPlayer === 1 ? 2 : 1;
// 更新玩家显示
const playerDisplay = document.getElementById('currentPlayerDisplay');
if (currentPlayer === 1) {
playerDisplay.innerHTML = '<span>🪻🌸</span><span>紫色</span>';
} else {
playerDisplay.innerHTML = '<span>🌻🌸</span><span>黄色</span>';
}
break;
}
}
棋盘落子需要考虑到玩家交替,棋子颜色的更改、游戏胜利判断条件以及页面玩家提示等等,在想到棋盘设置重力感应的状况下这些因素都需要被考虑进去。
低级人机对战模式
这个模式利用AI在代码中设计了一个简易的算法。玩家和人机对战,玩家率先执棋,一秒钟之后程序执黄棋。率先连成一条线的棋子获胜。
程序算法是利用棋盘布局,七列棋子随机选择一列落子。并没有多余的围堵以及程序获胜之类的想法考虑在其中。
程序在点击开始按钮之后正式启动,那么程序落子的延迟也需要在按钮函数中创建。
setTimeout(() => {
if (!gameOver) {
aiMove();
if (checkWin(2)) {
gameOver = true;
setTimeout(() => {
alert("游戏结束,执黄色棋的AI获胜!");
}, 500);
}
currentPlayer = 1;
updatePlayerDisplay();
}
}, 1000);
多人实时对战
界面设计创建房间和加入房间两种效果,创建房间可以生成一个房间号以至于玩家2能够通过房间号进入相同的房间进行对战。
指导AI明确使用node.js搭建后端服务器,利用socket.io实现了不同设备之间可以实时对战的效果,并且通过js实现页面功能设计。
文字描述页面实现效果指导AI完成多人实时对战模式。
代码框架主要由index.html和server.js两个文件组成。
运用nodemon server.js
运行服务器,通过控制台输出的连接进入页面创建或加入房间,开展双人实时对战游戏。
高级人机对战
点击开始游戏按钮之后正式进入人机对战模式,这个程序的实现相较于低级人机对战那个模式而言,就是在算法方面考虑了多种因素。
- 在相同颜色的棋子连在一起
小于等于2
的状况下,这个时候程序落子的规律是随机的;
// 优先检查是否有能获胜的落子点
const winningMove = findWinningMove(2);
if (winningMove !== null) {
makeMove(winningMove, 2);
return;
}
- 在相同颜色的棋子连在一起
大于2
的状况下,程序落子就必须关注玩家落子的状态,及时围堵;
// 其次遍历用户所有连续不间断棋子的起始和结束位置,找出最优封堵位置
const blockingMove = findOptimalBlockingMove(1);
if (blockingMove !== null) {
makeMove(blockingMove, 2);
return;
}
// 若都没有,则执行原有的落子策略
let bestScore = -Infinity;
let bestCol = null;
for (let col = 0; col < cols; col++) {
if (boardState[0][col] === 0) {
const row = findDropRow(col);
// 模拟落子
boardState[row][col] = 2;
// 计算当前局面得分
const aiScore = evaluateBoard(2);
const userScore = evaluateBoard(1);
const score = aiScore - userScore * 2; // 更重视阻止用户获胜
// 撤销模拟落子
boardState[row][col] = 0;
if (score > bestScore) {
bestScore = score;
bestCol = col;
}
}
}
- 程序在兼顾围堵的同时
优先选择的是自己的胜率
,会结合自己的棋子计算在哪个地方落子可以实现多种路径的胜利。
将需要实现的效果通过文字描述指导AI完成代码的编写。
页面效果的实现仅仅只通过一个.html文件就达到了上述效果。
功能改进
AI实现四连棋的成果并没有达到无可挑剔的状态。从一台到多台设备、低级到高级的人机对战模式,程序很显然缺少很多的功能。
就譬如:
- 对局计时器;
- 对战得分积累;
- 也可以设置排位等级增强用户的体验性等等。
最主要的是,高级人机对战模式的算法并不是很全面,程序在随机落子的时候是否考虑到接下来的几步对自己有没有用处,在对局即将结束的时候如何引导玩家落子为程序落子进行铺垫。
🎈从青铜到王者,AI四连棋实现的进化史还将继续。🎉🎉🎉