本文目录导读:

我来为您介绍如何使用PHP实现一个下棋AI,这里以五子棋为例,提供几种不同难度的实现方案:
基础实现(简单AI)
<?php
class TicTacToeAI {
private $board;
private $player = 'X';
private $ai = 'O';
public function __construct($board) {
$this->board = $board;
}
// 简单AI:随机下棋
public function randomMove() {
$emptyCells = [];
foreach ($this->board as $row => $cols) {
foreach ($cols as $col => $value) {
if ($value === '') {
$emptyCells[] = [$row, $col];
}
}
}
if (empty($emptyCells)) {
return null; // 棋盘已满
}
return $emptyCells[rand(0, count($emptyCells) - 1)];
}
// 中等AI:优先中心位置
public function smartRandomMove() {
// 优先中心
if ($this->board[1][1] === '') {
return [1, 1];
}
// 其次四角
$corners = [[0,0], [0,2], [2,0], [2,2]];
foreach ($corners as $corner) {
if ($this->board[$corner[0]][$corner[1]] === '') {
return $corner;
}
}
return $this->randomMove();
}
}
?>
中级AI(评估函数法)
<?php
class GomokuAI {
private $board;
private $size = 15;
private $player = 1; // 玩家棋子
private $ai = 2; // AI棋子
public function __construct($size = 15) {
$this->size = $size;
$this->board = array_fill(0, $size, array_fill(0, $size, 0));
}
// 评估函数 - 计算某位置的得分
private function evaluatePosition($row, $col, $player) {
$score = 0;
$directions = [[0,1], [1,0], [1,1], [1,-1]];
foreach ($directions as $dir) {
$score += $this->evaluateDirection($row, $col, $dir[0], $dir[1], $player);
}
return $score;
}
// 评估特定方向
private function evaluateDirection($row, $col, $dr, $dc, $player) {
$count = 1;
$blocked = 0;
$empty = 0;
// 正向检查
for ($i = 1; $i < 5; $i++) {
$nr = $row + $dr * $i;
$nc = $col + $dc * $i;
if ($nr < 0 || $nr >= $this->size || $nc < 0 || $nc >= $this->size) {
$blocked++;
break;
}
if ($this->board[$nr][$nc] === $player) {
$count++;
} elseif ($this->board[$nr][$nc] === 0) {
$empty++;
break;
} else {
$blocked++;
break;
}
}
// 反向检查
for ($i = 1; $i < 5; $i++) {
$nr = $row - $dr * $i;
$nc = $col - $dc * $i;
if ($nr < 0 || $nr >= $this->size || $nc < 0 || $nc >= $this->size) {
$blocked++;
break;
}
if ($this->board[$nr][$nc] === $player) {
$count++;
} elseif ($this->board[$nr][$nc] === 0) {
$empty++;
break;
} else {
$blocked++;
break;
}
}
// 根据连子数和阻塞情况计算得分
if ($count >= 5) return 100000;
if ($count === 4) {
return $empty > 0 ? ($blocked === 0 ? 10000 : 1000) : 0;
}
if ($count === 3) {
return $empty > 0 ? ($blocked === 0 ? 1000 : 100) : 0;
}
if ($count === 2) {
return $empty > 0 ? ($blocked === 0 ? 100 : 10) : 0;
}
return $count * 10;
}
// 找到最佳位置
public function findBestMove() {
$bestScore = -INF;
$bestMove = null;
for ($row = 0; $row < $this->size; $row++) {
for ($col = 0; $col < $this->size; $col++) {
if ($this->board[$row][$col] !== 0) continue;
// 跳过太远的位置(优化性能)
if (!$this->hasNeighbor($row, $col)) continue;
// 计算进攻和防守得分
$attackScore = $this->evaluatePosition($row, $col, $this->ai);
$defenseScore = $this->evaluatePosition($row, $col, $this->player);
// 综合得分(防守优先略低)
$totalScore = $attackScore + $defenseScore * 0.8;
if ($totalScore > $bestScore) {
$bestScore = $totalScore;
$bestMove = [$row, $col];
}
}
}
return $bestMove;
}
// 检查是否有相邻棋子(用于优化)
private function hasNeighbor($row, $col) {
for ($i = max(0, $row-2); $i <= min($this->size-1, $row+2); $i++) {
for ($j = max(0, $col-2); $j <= min($this->size-1, $col+2); $j++) {
if ($this->board[$i][$j] !== 0) {
return true;
}
}
}
return false;
}
}
?>
高级AI(Minimax + Alpha-Beta剪枝)
<?php
class AdvancedChessAI {
private $board;
private $size = 15;
// Minimax算法(简化版,适用于小棋盘)
public function minimax($depth, $isMaximizing) {
// 检查终端状态
$winner = $this->checkWinner();
if ($winner !== null) {
return $winner === 1 ? -100000 + $depth : 100000 - $depth;
}
if ($depth === 0) {
return $this->evaluateBoard();
}
if ($isMaximizing) {
$maxEval = -INF;
foreach ($this->getPossibleMoves() as $move) {
$this->makeMove($move[0], $move[1], 2);
$eval = $this->minimax($depth - 1, false);
$this->undoMove($move[0], $move[1]);
$maxEval = max($maxEval, $eval);
}
return $maxEval;
} else {
$minEval = INF;
foreach ($this->getPossibleMoves() as $move) {
$this->makeMove($move[0], $move[1], 1);
$eval = $this->minimax($depth - 1, true);
$this->undoMove($move[0], $move[1]);
$minEval = min($minEval, $eval);
}
return $minEval;
}
}
// Alpha-Beta剪枝优化
public function alphaBeta($depth, $alpha, $beta, $isMaximizing) {
$winner = $this->checkWinner();
if ($winner !== null) {
return $winner === 1 ? -100000 + $depth : 100000 - $depth;
}
if ($depth === 0) {
return $this->evaluateBoard();
}
if ($isMaximizing) {
$maxEval = -INF;
foreach ($this->getPossibleMoves() as $move) {
$this->makeMove($move[0], $move[1], 2);
$eval = $this->alphaBeta($depth - 1, $alpha, $beta, false);
$this->undoMove($move[0], $move[1]);
$maxEval = max($maxEval, $eval);
$alpha = max($alpha, $eval);
if ($beta <= $alpha) break; // 剪枝
}
return $maxEval;
} else {
$minEval = INF;
foreach ($this->getPossibleMoves() as $move) {
$this->makeMove($move[0], $move[1], 1);
$eval = $this->alphaBeta($depth - 1, $alpha, $beta, true);
$this->undoMove($move[0], $move[1]);
$minEval = min($minEval, $eval);
$beta = min($beta, $eval);
if ($beta <= $alpha) break; // 剪枝
}
return $minEval;
}
}
// 棋盘评估(简化版)
private function evaluateBoard() {
$score = 0;
// 统计棋子数量
foreach ($this->board as $row) {
foreach ($row as $cell) {
if ($cell === 1) $score -= 10;
if ($cell === 2) $score += 10;
}
}
return $score;
}
}
?>
完整应用示例
<?php
// 使用示例
session_start();
class GomokuGame {
private $ai;
private $gameId;
public function __construct() {
$this->gameId = $_SESSION['game_id'] ?? uniqid();
$this->initGame();
}
private function initGame() {
if (!isset($_SESSION['board'])) {
$_SESSION['board'] = array_fill(0, 15, array_fill(0, 15, 0));
$_SESSION['current_turn'] = 1; // 1=玩家, 2=AI
}
}
public function playerMove($row, $col) {
$board = $_SESSION['board'];
// 检查位置是否有效
if ($row < 0 || $row >= 15 || $col < 0 || $col >= 15) {
return ['error' => '无效位置'];
}
if ($board[$row][$col] !== 0) {
return ['error' => '该位置已有棋子'];
}
// 玩家下棋
$board[$row][$col] = 1;
$_SESSION['board'] = $board;
// 检查玩家是否获胜
if ($this->checkWin($board, $row, $col, 1)) {
return ['status' => 'win', 'player' => 'human'];
}
// AI下棋
$this->ai = new GomokuAI();
$this->ai->board = $board;
$aiMove = $this->ai->findBestMove();
if ($aiMove) {
$board[$aiMove[0]][$aiMove[1]] = 2;
$_SESSION['board'] = $board;
if ($this->checkWin($board, $aiMove[0], $aiMove[1], 2)) {
return ['status' => 'win', 'player' => 'ai'];
}
}
return ['status' => 'continue', 'board' => $board];
}
private function checkWin($board, $row, $col, $player) {
$directions = [[0,1], [1,0], [1,1], [1,-1]];
foreach ($directions as $dir) {
$count = 1;
// 正向
for ($i = 1; $i < 5; $i++) {
$nr = $row + $dir[0] * $i;
$nc = $col + $dir[1] * $i;
if ($nr < 0 || $nr >= 15 || $nc < 0 || $nc >= 15) break;
if ($board[$nr][$nc] === $player) $count++;
else break;
}
// 反向
for ($i = 1; $i < 5; $i++) {
$nr = $row - $dir[0] * $i;
$nc = $col - $dir[1] * $i;
if ($nr < 0 || $nr >= 15 || $nc < 0 || $nc >= 15) break;
if ($board[$nr][$nc] === $player) $count++;
else break;
}
if ($count >= 5) return true;
}
return false;
}
}
// API端点
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$game = new GomokuGame();
$data = json_decode(file_get_contents('php://input'), true);
if (isset($data['row']) && isset($data['col'])) {
$result = $game->playerMove($data['row'], $data['col']);
echo json_encode($result);
}
}
?>
HTML前端示例
<!DOCTYPE html>
<html>
<head>PHP 五子棋AI</title>
<style>
.board {
display: grid;
grid-template-columns: repeat(15, 30px);
gap: 1px;
background: #d4a574;
padding: 10px;
}
.cell {
width: 30px;
height: 30px;
background: #f0d9b5;
border: 1px solid #999;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
}
.cell.black::after {
content: '';
width: 20px;
height: 20px;
background: black;
border-radius: 50%;
}
.cell.white::after {
content: '';
width: 20px;
height: 20px;
background: white;
border-radius: 50%;
border: 1px solid #999;
}
</style>
</head>
<body>
<div id="gameBoard" class="board"></div>
<div id="status"></div>
<script>
let board = [];
function initBoard() {
const gameBoard = document.getElementById('gameBoard');
gameBoard.innerHTML = '';
for (let row = 0; row < 15; row++) {
for (let col = 0; col < 15; col++) {
const cell = document.createElement('div');
cell.className = 'cell';
cell.dataset.row = row;
cell.dataset.col = col;
cell.addEventListener('click', () => makeMove(row, col));
gameBoard.appendChild(cell);
}
}
}
async function makeMove(row, col) {
const response = await fetch('api.php', {
method: 'POST',
headers: {'Content-Type': 'application/json'},
body: JSON.stringify({row, col})
});
const result = await response.json();
updateBoard(result.board || board);
if (result.status === 'win') {
document.getElementById('status').textContent =
result.player === 'human' ? '你赢了!' : 'AI赢了!';
}
}
function updateBoard(newBoard) {
board = newBoard;
const cells = document.querySelectorAll('.cell');
cells.forEach((cell, index) => {
const row = Math.floor(index / 15);
const col = index % 15;
cell.className = 'cell';
if (newBoard[row][col] === 1) cell.classList.add('black');
if (newBoard[row][col] === 2) cell.classList.add('white');
});
}
initBoard();
</script>
</body>
</html>
优化建议
-
性能优化:
- 使用缓存的评估结果
- 限制搜索深度(通常3-5层)
- 只搜索有棋子的周边区域
-
AI难度调整:
- 随机错误率
- 不同的搜索深度
- 评估函数的权重调整
-
其他功能:
- 悔棋功能
- 保存/加载游戏
- 多种AI难度选择
-
技术改进:
- 使用MCTS(蒙特卡洛树搜索)
- 机器学习评估
- 神经网络(需要PHP-ML等库)
这个实现适合教学和中小型游戏项目,对于大型项目,可以考虑使用更多高级算法,或者将AI逻辑放在后端服务中以提高性能。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播