《我用AI实现四子棋》

505 阅读5分钟

一、什么是四连棋?规则又是怎样的?

1、什么是四子棋

四子棋是一种益智的棋类游戏。两方在6*7的格子内依次落子,落子规则为每一列必须从最底下的一格依次往上开始。

2、四子棋规则

棋子分为两种颜色,假设A玩家先落子,B玩家紧随其后,每一次落子都会掉到最底下,不能悬空。从各个方向,率先连成四子的玩家获胜。

二、AI如何实现想要的效果

1、双人对战+与低级AI对战

提示词: 为庆祝六一,由你为中小学构建《四连棋》对战网页游戏,使用HTML+CSS+JS构建四连棋页面, 页面使用Grid布局,界面Q版,棋盘6行 7列, 要求对战双方轮流下棋,各是一种具有区分度的颜色, 当有一方在棋盘上形成4个棋子连在一起时,获得胜利. 玩家选择先下或者后下 双方使用鼠标点击轮流下棋,移动时应该有旗子占位的预显示功能 提示获胜方不刷新棋盘,每次下棋时,必须叠在已有的棋子上,或者是最下一层。并且加上一个AI对战,可以和AI下棋。
页面实现代码(html):

<div class="game-container">
        <h1>四连棋</h1>
        <div class="status" id="status">玩家1回合 (红色)</div>
        <div class="board" id="board"></div>
        <button id="restart">重新开始</button>
    </div>
    <script src="LV1.js"></script>

逻辑实现代码(JS): 如果游戏未进行则返回,如果游戏正在进行就显示“AI思考中...",并调用makeAIMove,makeAIMove即返回的是AI所能下的列和行

function updateStatus() {
        if (!gameActive) return;
        
        if (isAIEnabled && currentPlayer === 2) {
            status.textContent = 'AI思考中...';
            setTimeout(makeAIMove, 500); // 延迟AI下棋,增加思考感
        } else {
            status.textContent = `玩家${currentPlayer}回合 (${currentPlayer === 1 ? '红色' : '黄色'})`;
        }
    }

如果说当前是AI回合就返回,否则启用双方对战的点击事件

board.addEventListener('click', (e) => {
        if (!gameActive || (isAIEnabled && currentPlayer === 2)) return;
        
        const cell = e.target.closest('.cell');
        if (!cell) return;
        
        const col = parseInt(cell.dataset.col);
        const row = getAvailableRow(col);
        
        if (row !== -1) {
            placePiece(row, col);
            checkGameStatus(row, col);
        }
    });

2、多人实时对战

提示词:
在上面代码的基础上,实现双人对战,可以通过手机或者电脑登录网址,必须输入正确的房间号才能进行对战,且每个房间只能进入两个人,如果有一方赢了就给他加一分。采用三局两胜的游戏规则,如果有一方的玩家不服气,还想玩可以通过重新开始实现新的棋盘,必须满足房间有两个人才能开始游戏,用到socket.io。
页面效果:

动画2.gif 逻辑实现:

正确下载npm install express socket.io,如果正确下载了会出现js代码
socket.io:

  • 功能:实现实时双向通信
  • 此处用途:处理游戏房间管理、玩家移动、胜负判断等实时交互
const express = require('express');
const http = require('http');
const { Server } = require('socket.io');
const path = require('path');

const app = express();
const server = http.createServer(app);

const io = new Server(server, {
  serveClient: true,
  cors: {
    origin: "*"
  }
});

app.use(express.static(path.join(__dirname, 'public')));

如果下载了socket.io,html里一定要引用它,因为它可以通过你的路径得到你写的js文件,才能调用里面的事件效果。

 <script src="/socket.io/socket.io.js"></script>

通过if,else条件判断,实现页面提示效果,用updateBoardUI函数和updateScoreDisplay函数存储最新的信息,以确保另一方能实时看到。定义currentPlayer(谁行动),matchWinner(是否结束)等逻辑进行判断。

socket.on('gameState', (data) => {
                gameBoard = data.board;
                currentPlayer = data.currentPlayer;
                scores = data.scores || { 1: 0, 2: 0 };
                currentRound = data.currentRound || 1;
                matchWinner = data.matchWinner || null;
                
                roundDisplay.textContent = currentRound;
                updateBoardUI();
                updateScoreDisplay();
                
                if (data.winner) {
                    gameActive = false;
                    if (data.winner === playerColor) {
                        status.textContent = `恭喜,你赢了第${currentRound}局!`;
                    } else {
                        status.textContent = `对手赢了第${currentRound}局!`;
                    }
                    
                    if (matchWinner) {
                        if (matchWinner === playerColor) {
                            status.textContent = '恭喜,你赢得了整个比赛!';
                        } else {
                            status.textContent = '对手赢得了整个比赛!';
                        }
                        restartBtn.textContent = '重新开始比赛';
                    } else {
                        restartBtn.textContent = '开始下一局';
                    }
                    
                    if (data.winningCells) {
                        highlightWinningCells(data.winningCells);
                    }
                    restartBtn.disabled = false;
                } else if (data.draw) {
                    gameActive = false;
                    status.textContent = `第${currentRound}局平局!`;
                    restartBtn.textContent = '开始下一局';
                    restartBtn.disabled = false;
                } else {
                    if (currentPlayer === playerColor) {
                        status.textContent = `第${currentRound}局 - 轮到你行动`;
                    } else {
                        status.textContent = `第${currentRound}局 - 等待对手行动...`;
                    }
                    restartBtn.disabled = true;
                }
            });

3、高级人机对战

提示词: 在低级AI对战的基础上,进一步更新代码,如果用户有两个子连在一起并且旁边为空的时候,AI就要去堵玩家的子,从多个角度判断玩家的棋子是否为三个子,如果玩家的棋子是三个,且这一轮轮到AI落子,AI的棋子只差一步就四子了,那么AI先完成自己的四子。否则当玩家的四子概率比AI成四子的概率更高的话(玩家只差一步就要四子),AI优先考虑堵玩家的棋子。
页面代码(html):

 <h1>✨ 四连棋 ✨</h1>
    <p class="subtitle">专家人机对战 - 挑战最强AI</p>
    
    <div class="game-container">
        <div class="player-selection">
            <div class="player-option player1 selected" id="player-first">我先下 (粉红色)</div>
            <div class="player-option player2" id="ai-first">AI先下 (天蓝色)</div>
        </div>
        
        <div class="board" id="board"></div>
        
        <div class="status" id="status">请选择谁先下棋</div>
        
        <div class="ai-thinking" id="ai-thinking">
            AI思考中<span class="thinking-dots"></span>
        </div>
        
        <div class="controls">
            <button class="btn" id="reset-btn">重新开始</button>
        </div>
    </div>

逻辑实现:
检查最底行的两个连在一起的棋子是否空,如果有就把它堵住

function checkBottomRowTwoInRow() {
                const bottomRow = ROWS - 1;
                
                for (let col = 0; col <= COLS - 2; col++) {
                    // 检查两连且两边有空位的情况
                    if (board[bottomRow][col] === 1 && 
                        board[bottomRow][col + 1] === 1) {
                        
                        // 检查左边是否有空位
                        if (col > 0 && board[bottomRow][col - 1] === 0) {
                            const emptyRow = findEmptyRow(col - 1);
                            if (emptyRow === bottomRow) {
                                return { row: emptyRow, col: col - 1 };
                            }
                        }
                        
                        // 检查右边是否有空位
                        if (col + 2 < COLS && board[bottomRow][col + 2] === 0) {
                            const emptyRow = findEmptyRow(col + 2);
                            if (emptyRow === bottomRow) {
                                return { row: emptyRow, col: col + 2 };
                            }
                        }
                    }
                }
                
                return null;
            }

filter是js的一个内置方法,创建一个新的数组,提供所需的元素。根据各种情况考虑玩家对于AI胜利的威胁程度,让AI做出反应。

function evaluateThreat(window) {
                const playerCount = window.filter(cell => cell === 1).length;
                const aiCount = window.filter(cell => cell === 2).length;
                const emptyCount = window.filter(cell => cell === 0).length;
                
                // 如果窗口中有AI的棋子,这不是威胁
                if (aiCount > 0) return null;
                
                // 玩家有三连且有一个空位
                if (playerCount === 3 && emptyCount === 1) {
                    return { threatLevel: 3 }; // 最高级别威胁,必须阻止
                }
                
                // 玩家有两连且有两个空位(潜在威胁)
                if (playerCount === 2 && emptyCount === 2) {
                    return { threatLevel: 2.5 }; // 中级威胁,应该考虑阻止
                }
                
                return null;
            }

三、遇到的问题

有时候可能是我们的表达方式不当,不能让AI理解我们的意思,这个时候我们应该更加清楚的表明我们的想法和思路,逐字逐句的去引导它,直到完成我们想要的效果。

四、如何购买?

四子棋是一个非常有趣的小游戏,可以帮助我们活跃思维,集中注意力,提升和亲朋好友的感情。如果你也觉得有趣的话,可以通过淘宝、京东等APP搜索“四连棋”,能找到多种款式和材质的四连棋,进行购买哦!