什么是四连棋?四连棋的规则是怎样的?
四子棋是一种棋类智力游戏,共有6行7列,棋盘是垂直摆放的,每位玩家有21个圆形棋子,两个玩家的棋子颜色是不一样的。 游戏规则为两位玩家轮流下棋,玩家必须从最底下的一格开始下棋,在棋盘中,谁能使自己的四个棋子在横,竖或对角线连成一条直线,即可获胜,否则就输了;如果棋盘已经填满,且双方都没有实现四个棋子连在一起时,则为平局。
如何指导AI实现四连棋
AI时代已经到来,如何指导AI,怎样把AI变成我们的学习工具,也是一门必修课,下面 来看看我是怎么指导AI的吧!
- 先在脑海中思考一下你想要干什么
- 说出你的需求和想要实现的功能,尽可能说的详细点儿
- 将思考的结果和AI给出的答案进行对比,如果有不满意的地方,可以再次进行提问
页面代码
一、双人手动下棋
同一台电脑双方轮流点一下鼠标,自动判断胜负
指导AI:现在我要使用HTML+CSS+JS构建四连棋页面,要求使用Grid布局,界面画风为Q版。棋盘为6行7列,要求对战双方轮流下棋,双方棋子为不同颜色,当有一方在棋盘上形成4个棋子(横、竖或者对角线)连在一起时,获得胜利. 玩家可以选择先下或者后下,双方可使用鼠标点击轮流下棋,移动时应该有棋子占位的预显示功能,每次下棋时,必须叠在已有的棋子上,或者是最下面一层
页面效果
代码部分
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>六一四连棋大作战</title>
</head>
<body>
<h1>六一快乐!四连棋大作战</h1>
<div id="controls">
<button id="start-yellow">我先下(黄)</button>
<button id="start-red">对方先下(红)</button>
<button id="reset">重新开始游戏</button>
</div>
<div id="message"></div>
<div id="game-container">
<div id="board"></div>
</div>
</body>
</html>
逻辑代码
落子逻辑代码:确保棋子只能落在已有棋子上方或最底部,否则视为无效落子
<script>
//落子逻辑
const ROWS = 6;
const COLS = 7;
let board = Array.from({ length: ROWS }, () => Array(COLS).fill(null));
function handleCellClick(e) {
if (gameOver || currentPlayer === null) return;
const col = parseInt(e.target.dataset.col);
const row = findNextEmptyRow(col);
if (row === -1 || (row < ROWS - 1 && board[row + 1][col] === null)) {
return; // 无效落子
}
placePiece(row, col);
checkWin(row, col);
switchPlayer();
}
</script>
二、低级人机对战
AI随机选一列配合下棋,自动判断胜负 指导AI:现在我要写人机对战模式,就是AI随机选一列配合下棋,自动判断胜负
页面效果
现在这一页面是在第一个页面的基础上进行修改的,增加了AI对战的效果,但是AI看起来非常傻,当我三个棋子都连在一起了,它都没有堵我,哈哈哈哈哈,后面还有高级人机模式,尽情期待
逻辑代码
下面为大家展示一下AI下棋的逻辑:随机选择一列,然后执行落子
// AI 下棋
function aiMove() {
// 检查AI是否能直接获胜
const winningCol = findWinningMove(AI_PLAYER);
if (winningCol !== -1) return makeMove(winningCol);
const blockingCol = findThreeInARow();
if (blockingCol !== -1) return makeMove(blockingCol);
// 随机选择有效列
const validCols = Array.from({length: COLS}, (_, i) => i)
.filter(col => findNextEmptyRow(col) !== -1);
if (validCols.length) makeMove(validCols[Math.floor(Math.random() * validCols.length)]);
}
// 查找获胜的落子位置
function findWinningMove(player) {
for (let col = 0; col < COLS; col++) {
const row = findNextEmptyRow(col);
if (row !== -1) {
board[row][col] = player;
const isWin = checkWin(row, col);
board[row][col] = null;
if (isWin) return col;
}
}
return -1;
}
// 执行落子
function makeMove(col) {
const row = findNextEmptyRow(col);
placePiece(row, col);
if (!checkWin(row, col)) switchPlayer();
}
// 查找下一个空行
function findNextEmptyRow(col) {
for (let row = ROWS - 1; row >= 0; row--) {
if (board[row][col] === null) return row;
}
return -1;
}
// 放置棋子
function placePiece(row, col) {
board[row][col] = currentPlayer;
document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`).classList.add(currentPlayer);
}
三、多人实时对战
指导AI:
- 写一个多人实时对战.html (一人一个手机实时对战,使用Socket.io进行实时通信),需要写前后端,用户需要连接同一WiFi,功能和界面可以稍作修改
- 可以在页面上提示用户,你是什么颜色的棋,以免混淆,比如说轮到这一方下棋了,就在页面上提示用户,你是哪一方,轮到你下棋啦,另外一个用户下棋时,可以提示等待另一玩家下棋,大概是这样子
- 游戏结束后,赢的那一方提示"恭喜你,赢了!",失败提示"很遗憾,你输了!" 平局提示"游戏结束 - 平局!"
- 玩家点了再来一局,可以向对方发送一个请求,这边用户同意了,他们双方可以再玩一局,如果用户拒绝了,则进行提示
页面效果
当两个用户连接同一WiFi,访问网址时,只需要填入相同游戏ID房间号,即可进入同一游戏,这样就完成了实时对战效果
后端运行效果
代码部分
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<h1>多人实时四连棋</h1>
<div id="controls">
<input type="text" id="game-id-input" placeholder="输入游戏ID">
<button id="join-btn">加入游戏</button>
</div>
<div id="game-id"></div>
<div id="game-info" style="display: none;">
<div id="yellow-player" class="player-info">
<span id="yellow-player-name">黄方</span>
</div>
<div id="red-player" class="player-info">
<span id="red-player-name">红方</span>
</div>
</div>
<div id="turn-message">等待加入游戏...</div>
<div id="board"></div>
<button id="rematch-btn">再来一局</button>
<div id="rematch-dialog" class="rematch-dialog">
<p id="rematch-message">对手请求再来一局,是否接受?</p>
<div class="rematch-buttons">
<button id="accept-rematch" class="rematch-accept">接受</button>
<button id="reject-rematch" class="rematch-reject">拒绝</button>
</div>
</div>
</body>
</html>
逻辑代码
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js"></script>
<script>
const socket = io();
let myColor = null;
let currentGame = null;
let currentGameId = null;
// 加入游戏
joinBtn.addEventListener('click', () => {
const gameId = gameIdInput.value.trim();
if (!gameId) return alert('请输入游戏ID');
currentGameId = gameId;
socket.emit('join', gameId);
gameIdElement.textContent = `游戏ID: ${gameId}`;
createBoard();
});
// 再来一局
rematchBtn.addEventListener('click', () => {
socket.emit('requestRematch', currentGameId);
rematchBtn.disabled = true;
rematchBtn.textContent = '等待对方响应...';
});
// 处理重赛请求
socket.on('rematchRequested', () => {
rematchMessage.textContent = '对手请求再来一局,是否接受?';
rematchDialog.style.display = 'block';
});
socket.on('rematchPending', () => {
rematchBtn.disabled = true;
rematchBtn.textContent = '等待对方响应...';
});
socket.on('rematchAccepted', () => {
rematchDialog.style.display = 'none';
rematchBtn.disabled = false;
rematchBtn.textContent = '再来一局';
rematchBtn.style.display = 'none';
turnMessageElement.textContent = '游戏重新开始!';
});
socket.on('rematchRejected', () => {
rematchDialog.style.display = 'none';
rematchBtn.disabled = false;
rematchBtn.textContent = '再来一局';
turnMessageElement.textContent = '对手拒绝了重赛请求';
});
// Socket事件处理
socket.on('color', (color) => {
myColor = color;
gameInfoElement.style.display = 'flex';
</script>
后端代码,需要下载模块npm install express socket.io,然后再运行
const express = require('express');
const http = require('http');
const socketIo = require('socket.io');
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
const PORT = 3000;
// Socket.io连接处理
io.on('connection', (socket) => {
console.log('新用户连接:', socket.id);
socket.on('join', (gameId) => {
if (!games[gameId]) {
games[gameId] = {
players: [],
board: Array(6).fill().map(() => Array(7).fill(null)),
currentPlayer: 'yellow',
gameOver: false,
rematchRequested: false
};
}
if (games[gameId].players.length >= 2) {
socket.emit('full');
return;
}
const color = games[gameId].players.length === 0 ? 'yellow' : 'red';
games[gameId].players.push({ id: socket.id, color });
socket.join(gameId);
socket.emit('color', color);
io.to(gameId).emit('update', games[gameId]);
console.log(`${socket.id} (${color})加入了游戏${gameId}`);
});
socket.on('move', (col) => {
const gameId = Array.from(socket.rooms)[1];
const game = games[gameId];
if (!game || game.gameOver) return;
const player = game.players.find(p => p.id === socket.id);
if (!player || player.color !== game.currentPlayer) return;
const row = findEmptyRow(game.board, col);
if (row === -1) return;
game.board[row][col] = player.color;
if (checkWin(game.board, row, col, player.color)) {
game.gameOver = true;
game.winner = player.color;
} else if (isBoardFull(game.board)) {
game.gameOver = true;
game.winner = 'draw';
} else {
game.currentPlayer = player.color === 'yellow' ? 'red' : 'yellow';
}
io.to(gameId).emit('update', game);
});
socket.on('requestRematch', (gameId) => {
const game = games[gameId];
if (!game || !game.gameOver) return;
// 标记重赛请求
game.rematchRequested = true;
// 通知对方玩家
const opponent = game.players.find(p => p.id !== socket.id);
if (opponent) {
io.to(opponent.id).emit('rematchRequested');
}
// 通知请求方
socket.emit('rematchPending');
});
socket.on('respondRematch', ({ gameId, accept }) => {
const game = games[gameId];
if (!game || !game.rematchRequested) return;
if (accept) {
// 重置游戏状态
games[gameId] = {
players: game.players,
board: Array(6).fill().map(() => Array(7).fill(null)),
currentPlayer: 'yellow',
gameOver: false,
rematchRequested: false
};
io.to(gameId).emit('rematchAccepted');
io.to(gameId).emit('update', games[gameId]);
} else {
// 拒绝重赛
game.rematchRequested = false;
const requester = game.players.find(p => p.id !== socket.id);
if (requester) {
io.to(requester.id).emit('rematchRejected');
}
}
});
socket.on('disconnect', () => {
console.log('用户断开:', socket.id);
});
});
// 静态文件服务
app.use(express.static('public'));
server.listen(PORT, () => {
console.log(`服务器运行在 http://localhost:${PORT}`);
});
四、高级人机对战
指导AI:现在我要写高级人机对战,使用算法或训练AI经过思考下棋,达到必胜或者平手的水平
AI的回复为:使用极小化极大算法(Minimax)和α-β剪枝来提升AI的决策能力,这种算法可以让AI思考几步棋之后的情况,选择最优的下法
页面效果
代码部分和逻辑代码*
下面是AI回复的答案,我测试之后,直接震惊了,觉得这种算法很厉害,迫不及待地想和大家分享一下,大家可以研究研究。这个算法添加了难度选择,可以设置AI思考的深度(3步、5步或7步),思考深度越大,AI越强,但计算时间也越长,同时也实现了复杂的评估函数,考虑了多种因素:
- 优先选择中心列(中心列更有价值)
- 发现潜在的四连机会
- 阻止对手形成四连
- 优先形成自己的三连和双连 自己试玩之后,发现这个AI实力相当强大,自己挑战了多次,几乎没有赢过,很少能达成平局或者胜利,非常具有挑战性,可以通过调整难度选择来获得更适合你的挑战级别。以下是完整代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>六一四连棋大作战 - 高级AI版</title>
<style>
body {
font-family: 'Comic Sans MS', cursive;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
margin: 0;
background-color: #f5e6ff;
}
#game-container {
display: flex;
flex-direction: column;
align-items: center;
}
#board {
display: grid;
grid-template-columns: repeat(7, 80px);
grid-template-rows: repeat(6, 80px);
gap: 5px;
background-color: #73a6ff;
padding: 10px;
border-radius: 15px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.3);
}
.cell {
width: 80px;
height: 80px;
background-color: white;
border-radius: 50%;
box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.2);
cursor: pointer;
}
.yellow { background-color: #ffd700; box-shadow: 0 0 10px #ffd700; }
.red { background-color: #ff4500; box-shadow: 0 0 10px #ff4500; }
.hover-yellow { background-color: #ffd700; opacity: 0.5; }
.hover-red { background-color: #ff4500; opacity: 0.5; }
#controls {
margin-top: 20px;
display: flex;
gap: 10px;
}
button {
padding: 10px 20px;
border: none;
border-radius: 5px;
background-color: #9966cc;
color: white;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover { background-color: #8a56b7; }
#message {
margin-top: 20px;
font-size: 24px;
font-weight: bold;
color: #333;
}
#difficulty {
margin-top: 10px;
padding: 8px;
border-radius: 5px;
border: 1px solid #9966cc;
}
</style>
</head>
<body>
<h1>六一快乐!四连棋大作战 - 高级AI版</h1>
<div id="controls">
<button id="start-yellow">我先下(黄)</button>
<button id="start-red">AI 先下(红)</button>
<button id="reset">重新开始游戏</button>
</div>
<select id="difficulty">
<option value="3">简单 (思考3步)</option>
<option value="5" selected>中等 (思考5步)</option>
<option value="7">困难 (思考7步)</option>
</select>
<div id="message"></div>
<div id="game-container">
<div id="board"></div>
</div>
<script>
const ROWS = 6, COLS = 7;
let board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
let currentPlayer = null, gameOver = false;
const AI_PLAYER = 'red', HUMAN_PLAYER = 'yellow';
const boardElement = document.getElementById('board');
const messageElement = document.getElementById('message');
const [startYellowButton, startRedButton, resetButton] = ['start-yellow', 'start-red', 'reset'].map(id => document.getElementById(id));
const difficultySelect = document.getElementById('difficulty');
// 创建棋盘
function createBoard() {
boardElement.innerHTML = '';
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('click', handleCellClick);
cell.addEventListener('mouseenter', showPreview);
cell.addEventListener('mouseleave', removePreview);
boardElement.appendChild(cell);
}
}
}
// 处理单元格点击
function handleCellClick(e) {
if (gameOver || currentPlayer !== HUMAN_PLAYER) return;
const col = +e.target.dataset.col;
const row = findNextEmptyRow(col);
if (row !== -1 && (row === ROWS - 1 || board[row + 1][col] !== null)) {
placePiece(row, col);
if (!checkWin(row, col)) {
switchPlayer();
setTimeout(aiMove, 500);
}
}
}
// AI 下棋 - 使用Minimax算法
function aiMove() {
const difficulty = parseInt(difficultySelect.value);
const [bestMove, _] = minimax(board, difficulty, -Infinity, Infinity, true);
if (bestMove !== null && bestMove !== undefined) {
makeMove(bestMove);
}
}
// Minimax算法实现,带有α-β剪枝
function minimax(board, depth, alpha, beta, maximizingPlayer) {
// 检查游戏是否结束或达到最大深度
const gameResult = evaluateBoard(board);
if (depth === 0 || gameResult !== null) {
return [null, gameResult !== null ? gameResult : evaluatePosition(board)];
}
const validCols = getValidColumns(board);
if (maximizingPlayer) {
let value = -Infinity;
let bestCol = validCols[0];
for (const col of validCols) {
const row = findNextEmptyRowInBoard(board, col);
const newBoard = copyBoard(board);
newBoard[row][col] = AI_PLAYER;
const newScore = minimax(newBoard, depth - 1, alpha, beta, false)[1];
if (newScore > value) {
value = newScore;
bestCol = col;
}
alpha = Math.max(alpha, value);
if (alpha >= beta) break;
}
return [bestCol, value];
} else {
let value = Infinity;
let bestCol = validCols[0];
for (const col of validCols) {
const row = findNextEmptyRowInBoard(board, col);
const newBoard = copyBoard(board);
newBoard[row][col] = HUMAN_PLAYER;
const newScore = minimax(newBoard, depth - 1, alpha, beta, true)[1];
if (newScore < value) {
value = newScore;
bestCol = col;
}
beta = Math.min(beta, value);
if (alpha >= beta) break;
}
return [bestCol, value];
}
}
// 评估棋盘状态
function evaluateBoard(board) {
// 检查AI是否获胜
if (checkWinInBoard(board, AI_PLAYER)) return Infinity;
// 检查玩家是否获胜
if (checkWinInBoard(board, HUMAN_PLAYER)) return -Infinity;
// 检查平局
if (isBoardFull(board)) return 0;
// 游戏未结束
return null;
}
// 评估棋盘位置分数
function evaluatePosition(board) {
let score = 0;
// 中心列优先
const centerCol = Math.floor(COLS / 2);
for (let row = 0; row < ROWS; row++) {
if (board[row][centerCol] === AI_PLAYER) score += 3;
}
// 评估所有可能的四连位置
score += evaluateLines(board, AI_PLAYER);
score -= evaluateLines(board, HUMAN_PLAYER);
return score;
}
// 评估所有可能的四连位置
function evaluateLines(board, player) {
let score = 0;
// 水平方向
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS - 3; col++) {
score += evaluateWindow(board, row, col, 0, 1, player);
}
}
// 垂直方向
for (let row = 0; row < ROWS - 3; row++) {
for (let col = 0; col < COLS; col++) {
score += evaluateWindow(board, row, col, 1, 0, player);
}
}
// 正对角线
for (let row = 0; row < ROWS - 3; row++) {
for (let col = 0; col < COLS - 3; col++) {
score += evaluateWindow(board, row, col, 1, 1, player);
}
}
// 反对角线
for (let row = 3; row < ROWS; row++) {
for (let col = 0; col < COLS - 3; col++) {
score += evaluateWindow(board, row, col, -1, 1, player);
}
}
return score;
}
// 评估一个四连窗口
function evaluateWindow(board, row, col, dr, dc, player) {
let score = 0;
let opponent = player === AI_PLAYER ? HUMAN_PLAYER : AI_PLAYER;
let playerCount = 0;
let emptyCount = 0;
let opponentCount = 0;
for (let i = 0; i < 4; i++) {
const r = row + i * dr;
const c = col + i * dc;
if (board[r][c] === player) playerCount++;
else if (board[r][c] === null) emptyCount++;
else opponentCount++;
}
// 根据窗口中的棋子数量评分
if (playerCount === 4) score += 100;
else if (playerCount === 3 && emptyCount === 1) score += 5;
else if (playerCount === 2 && emptyCount === 2) score += 2;
if (opponentCount === 3 && emptyCount === 1) score -= 4;
return score;
}
// 获取所有有效列
function getValidColumns(board) {
const validCols = [];
for (let col = 0; col < COLS; col++) {
if (findNextEmptyRowInBoard(board, col) !== -1) {
validCols.push(col);
}
}
return validCols;
}
// 复制棋盘
function opyBoard(board) {
return board.map(row => [...row]);
}
// 在指定棋盘上查找下一个空行
function findNextEmptyRowInBoard(board, col) {
for (let row = ROWS - 1; row >= 0; row--) {
if (board[row][col] === null) return row;
}
return -1;
}
// 在指定棋盘上检查是否获胜
function checkWinInBoard(board, player) {
// 检查水平方向
for (let row = 0; row < ROWS; row++) {
for (let col = 0; col < COLS - 3; col++) {
if (board[row][col] === player &&
board[row][col+1] === player &&
board[row][col+2] === player &&
board[row][col+3] === player) {
return true;
}
}
}
// 检查垂直方向
for (let row = 0; row < ROWS - 3; row++) {
for (let col = 0; col < COLS; col++) {
if (board[row][col] === player &&
board[row+1][col] === player &&
board[row+2][col] === player &&
board[row+3][col] === player) {
return true;
}
}
}
// 检查正对角线
for (let row = 0; row < ROWS - 3; row++) {
for (let col = 0; col < COLS - 3; col++) {
if (board[row][col] === player &&
board[row+1][col+1] === player &&
board[row+2][col+2] === player &&
board[row+3][col+3] === player) {
return true;
}
}
}
// 检查反对角线
for (let row = 3; row < ROWS; row++) {
for (let col = 0; col < COLS - 3; col++) {
if (board[row][col] === player &&
board[row-1][col+1] === player &&
board[row-2][col+2] === player &&
board[row-3][col+3] === player) {
return true;
}
}
}
return false;
}
// 执行落子
function makeMove(col) {
const row = findNextEmptyRow(col);
placePiece(row, col);
if (!checkWin(row, col)) switchPlayer();
}
// 查找下一个空行
function findNextEmptyRow(col) {
for (let row = ROWS - 1; row >= 0; row--) {
if (board[row][col] === null) return row;
}
return -1;
}
// 放置棋子
function placePiece(row, col) {
board[row][col] = currentPlayer;
document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`).classList.add(currentPlayer);
}
// 检查是否获胜
function checkWin(row, col) {
const directions = [[1,0],[0,1],[1,1],[1,-1]];
for (const [dr, dc] of directions) {
let count = 1;
for (let i = 1; i < 4; i++) {
const r = row + i * dr, c = col + i * dc;
if (r >= 0 && r < ROWS && c >= 0 && c < COLS && board[r][c] === currentPlayer) count++;
else break;
}
for (let i = 1; i < 4; i++) {
const r = row - i * dr, c = col - i * dc;
if (r >= 0 && r < ROWS && c >= 0 && c < COLS && board[r][c] === currentPlayer) count++;
else break;
}
if (count >= 4) {
gameOver = true;
messageElement.textContent = `${currentPlayer === HUMAN_PLAYER ? '你' : 'AI'} 获胜!`;
return true;
}
}
if (board.every(row => row.every(cell => cell !== null))) {
gameOver = true;
messageElement.textContent = '平局!';
return true;
}
return false;
}
// 检查棋盘是否已满
function isBoardFull(board) {
return board.every(row => row.every(cell => cell !== null));
}
// 切换玩家
function switchPlayer() {
if (gameOver) return;
currentPlayer = currentPlayer === HUMAN_PLAYER ? AI_PLAYER : HUMAN_PLAYER;
messageElement.textContent = `${currentPlayer === HUMAN_PLAYER ? '你' : 'AI'} 回合`;
}
// 显示棋子占位预显示
function showPreview(e) {
if (gameOver || currentPlayer !== HUMAN_PLAYER) return;
const col = +e.target.dataset.col;
const row = findNextEmptyRow(col);
if (row !== -1) {
document.querySelector(`.cell[data-row="${row}"][data-col="${col}"]`)
.classList.add(`hover-${currentPlayer}`);
}
}
// 移除棋子占位预显示
function removePreview() {
document.querySelectorAll('.cell').forEach(cell => {
cell.classList.remove('hover-yellow', 'hover-red');
});
}
// 重置游戏
function resetGame() {
board = Array(ROWS).fill().map(() => Array(COLS).fill(null));
document.querySelectorAll('.cell').forEach(cell => {
cell.className = 'cell';
});
currentPlayer = null;
gameOver = false;
messageElement.textContent = '';
startYellowButton.disabled = false;
startRedButton.disabled = false;
}
// 事件监听
startYellowButton.addEventListener('click', () => {
currentPlayer = HUMAN_PLAYER;
messageElement.textContent = '你 回合';
startYellowButton.disabled = true;
startRedButton.disabled = true;
});
startRedButton.addEventListener('click', () => {
currentPlayer = AI_PLAYER;
messageElement.textContent = 'AI 回合';
startYellowButton.disabled = true;
startRedButton.disabled = true;
setTimeout(aiMove, 500);
});
resetButton.addEventListener('click', resetGame);
createBoard();
</script>
</body>
</html>
总结
谢谢大家看了这么久的文章,当然代码依然还有一些功能没有实现,我也会继续改进并进行学习,总之,这一次指导AI做游戏收获满满,谢谢大家!