从青铜到王者,AI四连棋实现进化史🐧

68 阅读6分钟

开局双连问(什么是四连棋,规则又是什么?)

【四子棋】双人休闲益智小游戏推荐(11)_3_聚会桌游神器_来自小红书网页版.jpg

四连棋是双人对战的棋类游戏。棋盘被垂直放置在桌面之上,只有棋盘底部的空缺被填满棋子才能继续向上扩展。

  • 棋盘一般是6行7列的垂直框架,棋子自然下落到棋盘底部或者是已有棋子的上方;
  • 两名玩家各自执不同的颜色的棋子,双方轮流落子;
  • 四个颜色相同的棋子率先连成一条竖线、横线或者是斜线,那么执这个颜色棋子的玩家获胜;
  • 当棋盘的棋子被填满的还是没有四自连成一条直线的时候,此时双方打平。

市面上的四联棋

🎲立体四子棋👨_👩_👧_👦亲子益智必备_2_益乐多_来自小红书网页版.jpg

厂家直销立体四子棋四连棋儿童益智力五子棋_5_山峰霞_来自小红书网页版.jpg

市面的实体四连棋简约美观,收纳便捷。围绕着棋盘规则制造出样式多样的四连棋。

六一儿童节即将到来,的确,有了实物的四连棋,那么信息时代又怎么能够少了页面版的电子四连棋呢!!!

AI四连棋实现进化史

一台设备实现双人手动下棋

双人手动下棋.gif

页面效果实现只是通过不同阶段用户执的棋子颜色不同实现的功能。

前端代码框架搭建代码很少,主要利用grid布局和for循环实现棋盘效果。

image.png

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;
                }
            }

棋盘落子需要考虑到玩家交替,棋子颜色的更改、游戏胜利判断条件以及页面玩家提示等等,在想到棋盘设置重力感应的状况下这些因素都需要被考虑进去。

低级人机对战模式

低级人机对战.gif

这个模式利用AI在代码中设计了一个简易的算法。玩家和人机对战,玩家率先执棋,一秒钟之后程序执黄棋。率先连成一条线的棋子获胜。

程序算法是利用棋盘布局,七列棋子随机选择一列落子。并没有多余的围堵以及程序获胜之类的想法考虑在其中。

image.png

程序在点击开始按钮之后正式启动,那么程序落子的延迟也需要在按钮函数中创建。

        setTimeout(() => {
            if (!gameOver) {
                aiMove();
                if (checkWin(2)) {
                    gameOver = true;
                    setTimeout(() => {
                        alert("游戏结束,执黄色棋的AI获胜!");
                    }, 500);
                }
                currentPlayer = 1;
                updatePlayerDisplay();
            }
        }, 1000);

多人实时对战

多人实时对战.gif

界面设计创建房间和加入房间两种效果,创建房间可以生成一个房间号以至于玩家2能够通过房间号进入相同的房间进行对战。

指导AI明确使用node.js搭建后端服务器,利用socket.io实现了不同设备之间可以实时对战的效果,并且通过js实现页面功能设计。

文字描述页面实现效果指导AI完成多人实时对战模式。

image.png

image.png

代码框架主要由index.html和server.js两个文件组成。

image.png

运用nodemon server.js运行服务器,通过控制台输出的连接进入页面创建或加入房间,开展双人实时对战游戏。

高级人机对战

高级人机对战.gif

点击开始游戏按钮之后正式进入人机对战模式,这个程序的实现相较于低级人机对战那个模式而言,就是在算法方面考虑了多种因素。

  • 在相同颜色的棋子连在一起小于等于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完成代码的编写。

image.png

页面效果的实现仅仅只通过一个.html文件就达到了上述效果。

功能改进

AI实现四连棋的成果并没有达到无可挑剔的状态。从一台到多台设备、低级到高级的人机对战模式,程序很显然缺少很多的功能。

就譬如:

  • 对局计时器;
  • 对战得分积累;
  • 也可以设置排位等级增强用户的体验性等等。

最主要的是,高级人机对战模式的算法并不是很全面,程序在随机落子的时候是否考虑到接下来的几步对自己有没有用处,在对局即将结束的时候如何引导玩家落子为程序落子进行铺垫。

🎈从青铜到王者,AI四连棋实现的进化史还将继续。🎉🎉🎉