PHP 怎么PHP AI对战

wen PHP项目 3

本文目录导读:

PHP 怎么PHP AI对战

  1. 基础版:简单规则AI
  2. 进阶版:概率模型AI
  3. 完整示例:五子棋AI对战
  4. 使用示例
  5. 前端HTML
  6. 优化建议

我来给你详细介绍如何用PHP实现一个AI对战系统,这里我提供几种不同层次的实现方案:

基础版:简单规则AI

<?php
class SimpleAI {
    private $difficulty;
    public function __construct($difficulty = 'easy') {
        $this->difficulty = $difficulty;
    }
    public function makeMove($board) {
        // 简单AI:随机选择一个空位
        $emptyCells = [];
        foreach ($board as $row => $cols) {
            foreach ($cols as $col => $value) {
                if ($value === 0) {
                    $emptyCells[] = [$row, $col];
                }
            }
        }
        if (empty($emptyCells)) {
            return null; // 棋盘已满
        }
        // 按难度选择移动
        switch ($this->difficulty) {
            case 'easy':
                return $this->randomMove($emptyCells);
            case 'medium':
                return $this->mediumMove($board, $emptyCells);
            case 'hard':
                return $this->hardMove($board, $emptyCells);
            default:
                return $this->randomMove($emptyCells);
        }
    }
    private function randomMove($emptyCells) {
        $index = array_rand($emptyCells);
        return $emptyCells[$index];
    }
    private function mediumMove($board, $emptyCells) {
        // 中等AI:尝试获胜或阻挡对手
        // 简单的策略:如果有必胜,选择必胜
        foreach ($emptyCells as $cell) {
            $board[$cell[0]][$cell[1]] = 1; // 假设AI是1
            if ($this->isWinner($board, 1)) {
                $board[$cell[0]][$cell[1]] = 0;
                return $cell;
            }
            $board[$cell[0]][$cell[1]] = 0;
        }
        // 防守策略:阻挡对手
        foreach ($emptyCells as $cell) {
            $board[$cell[0]][$cell[1]] = 2; // 对手是2
            if ($this->isWinner($board, 2)) {
                $board[$cell[0]][$cell[1]] = 0;
                return $cell;
            }
            $board[$cell[0]][$cell[1]] = 0;
        }
        return $this->randomMove($emptyCells);
    }
    private function hardMove($board, $emptyCells) {
        // 高级AI:使用Minimax算法
        $bestScore = -INF;
        $bestMove = null;
        foreach ($emptyCells as $cell) {
            $board[$cell[0]][$cell[1]] = 1;
            $score = $this->minimax($board, 0, false);
            $board[$cell[0]][$cell[1]] = 0;
            if ($score > $bestScore) {
                $bestScore = $score;
                $bestMove = $cell;
            }
        }
        return $bestMove ?? $this->randomMove($emptyCells);
    }
    private function minimax($board, $depth, $isMaximizing) {
        // 检查胜负
        if ($this->isWinner($board, 1)) return 10 - $depth;
        if ($this->isWinner($board, 2)) return $depth - 10;
        if ($this->isBoardFull($board)) return 0;
        if ($isMaximizing) {
            $bestScore = -INF;
            foreach ($board as $row => $cols) {
                foreach ($cols as $col => $value) {
                    if ($value === 0) {
                        $board[$row][$col] = 1;
                        $score = $this->minimax($board, $depth + 1, false);
                        $board[$row][$col] = 0;
                        $bestScore = max($score, $bestScore);
                    }
                }
            }
            return $bestScore;
        } else {
            $bestScore = INF;
            foreach ($board as $row => $cols) {
                foreach ($cols as $col => $value) {
                    if ($value === 0) {
                        $board[$row][$col] = 2;
                        $score = $this->minimax($board, $depth + 1, true);
                        $board[$row][$col] = 0;
                        $bestScore = min($score, $bestScore);
                    }
                }
            }
            return $bestScore;
        }
    }
    private function isWinner($board, $player) {
        // 检查胜利条件(以井字棋为例)
        $winLines = [
            [[0,0],[0,1],[0,2]], [[1,0],[1,1],[1,2]], [[2,0],[2,1],[2,2]], // 行
            [[0,0],[1,0],[2,0]], [[0,1],[1,1],[2,1]], [[0,2],[1,2],[2,2]], // 列
            [[0,0],[1,1],[2,2]], [[0,2],[1,1],[2,0]]  // 对角
        ];
        foreach ($winLines as $line) {
            $win = true;
            foreach ($line as $cell) {
                if ($board[$cell[0]][$cell[1]] !== $player) {
                    $win = false;
                    break;
                }
            }
            if ($win) return true;
        }
        return false;
    }
    private function isBoardFull($board) {
        foreach ($board as $row) {
            foreach ($row as $cell) {
                if ($cell === 0) return false;
            }
        }
        return true;
    }
}

进阶版:概率模型AI

<?php
class ProbabilisticAI {
    private $probabilityMatrix;
    private $history;
    public function __construct() {
        $this->probabilityMatrix = [];
        $this->history = [];
    }
    public function makeMove($gameState) {
        // 学习历史,预测对手行为
        $action = $this->getAction($gameState);
        $this->updateHistory($gameState, $action);
        return $action;
    }
    private function getAction($gameState) {
        $actionValues = [];
        $possibleActions = $this->getPossibleActions($gameState);
        foreach ($possibleActions as $action) {
            // 计算Q值(期望回报)
            $qValue = 0;
            if (isset($this->probabilityMatrix[md5(serialize($gameState))])) {
                $qValue = $this->probabilityMatrix[md5(serialize($gameState))][md5(serialize($action))] ?? 0;
            }
            $actionValues[$action] = $qValue;
        }
        // 使用epsilon贪心策略
        $epsilon = 0.1;
        if (rand(0, 100) / 100 < $epsilon) {
            // 探索:随机选择
            return $possibleActions[array_rand($possibleActions)];
        } else {
            // 利用:选择Q值最高的动作
            arsort($actionValues);
            return array_key_first($actionValues);
        }
    }
    private function updateHistory($state, $action) {
        $key = md5(serialize($state)) . '-' . md5(serialize($action));
        $this->history[] = [
            'state' => $state,
            'action' => $action,
            'timestamp' => time()
        ];
    }
}

完整示例:五子棋AI对战

<?php
class GomokuAI {
    private $board;
    private $size;
    private $player = 1; // AI的棋子
    private $opponent = 2; // 对手的棋子
    public function __construct($size = 15) {
        $this->size = $size;
        $this->board = array_fill(0, $size, array_fill(0, $size, 0));
    }
    public function getBestMove() {
        // 使用极大极小搜索 + Alpha-Beta剪枝
        $bestScore = -PHP_INT_MAX;
        $bestMove = null;
        for ($i = 0; $i < $this->size; $i++) {
            for ($j = 0; $j < $this->size; $j++) {
                if ($this->board[$i][$j] === 0) {
                    $this->board[$i][$j] = $this->player;
                    $score = $this->alphaBeta(4, -PHP_INT_MAX, PHP_INT_MAX, false);
                    $this->board[$i][$j] = 0;
                    if ($score > $bestScore) {
                        $bestScore = $score;
                        $bestMove = [$i, $j];
                    }
                }
            }
        }
        return $bestMove;
    }
    private function alphaBeta($depth, $alpha, $beta, $isMaximizing) {
        // 检查胜负
        if ($this->checkWinner($this->player)) return 100000;
        if ($this->checkWinner($this->opponent)) return -100000;
        if ($depth === 0) return $this->evaluateBoard();
        if ($isMaximizing) {
            $maxScore = -PHP_INT_MAX;
            $moves = $this->getHeuristicMoves();
            foreach ($moves as $move) {
                $this->board[$move[0]][$move[1]] = $this->player;
                $score = $this->alphaBeta($depth - 1, $alpha, $beta, false);
                $this->board[$move[0]][$move[1]] = 0;
                $maxScore = max($maxScore, $score);
                $alpha = max($alpha, $score);
                if ($beta <= $alpha) break;
            }
            return $maxScore;
        } else {
            $minScore = PHP_INT_MAX;
            $moves = $this->getHeuristicMoves();
            foreach ($moves as $move) {
                $this->board[$move[0]][$move[1]] = $this->opponent;
                $score = $this->alphaBeta($depth - 1, $alpha, $beta, true);
                $this->board[$move[0]][$move[1]] = 0;
                $minScore = min($minScore, $score);
                $beta = min($beta, $score);
                if ($beta <= $alpha) break;
            }
            return $minScore;
        }
    }
    private function evaluateBoard() {
        $score = 0;
        // 评估所有方向上的局势
        $directions = [[0,1],[1,0],[1,1],[1,-1]];
        foreach ($directions as $dir) {
            $score += $this->evaluateDirection($dir[0], $dir[1], $this->player);
            $score -= $this->evaluateDirection($dir[0], $dir[1], $this->opponent);
        }
        return $score;
    }
    private function evaluateDirection($dx, $dy, $player) {
        $score = 0;
        for ($i = 0; $i < $this->size; $i++) {
            for ($j = 0; $j < $this->size; $j++) {
                if ($this->board[$i][$j] === $player) {
                    $count = 1;
                    $blocked = [false, false];
                    // 向前检查
                    for ($k = 1; $k < 5; $k++) {
                        $nx = $i + $dx * $k;
                        $ny = $j + $dy * $k;
                        if ($nx < 0 || $nx >= $this->size || $ny < 0 || $ny >= $this->size) {
                            $blocked[0] = true;
                            break;
                        }
                        if ($this->board[$nx][$ny] === $player) {
                            $count++;
                        } else if ($this->board[$nx][$ny] === 0) {
                            break;
                        } else {
                            $blocked[0] = true;
                            break;
                        }
                    }
                    // 向后检查
                    for ($k = 1; $k < 5; $k++) {
                        $nx = $i - $dx * $k;
                        $ny = $j - $dy * $k;
                        if ($nx < 0 || $nx >= $this->size || $ny < 0 || $ny >= $this->size) {
                            $blocked[1] = true;
                            break;
                        }
                        if ($this->board[$nx][$ny] === $player) {
                            $count++;
                        } else if ($this->board[$nx][$ny] === 0) {
                            break;
                        } else {
                            $blocked[1] = true;
                            break;
                        }
                    }
                    // 根据棋子数和阻塞情况打分
                    if ($count >= 5 && !$blocked[0] && !$blocked[1]) {
                        $score += 10000;
                    } else if ($count === 4 && !($blocked[0] && $blocked[1])) {
                        $score += 1000;
                    } else if ($count === 3 && !($blocked[0] && $blocked[1])) {
                        $score += 100;
                    } else if ($count === 2 && !($blocked[0] && $blocked[1])) {
                        $score += 10;
                    } else if ($count === 1 && !($blocked[0] && $blocked[1])) {
                        $score += 1;
                    }
                }
            }
        }
        return $score;
    }
    private function getHeuristicMoves() {
        $moves = [];
        // 只考虑周围有棋子的位置
        for ($i = 0; $i < $this->size; $i++) {
            for ($j = 0; $j < $this->size; $j++) {
                if ($this->board[$i][$j] !== 0 && $this->hasNeighbor($i, $j)) {
                    $moves[] = [$i, $j];
                }
            }
        }
        return $moves;
    }
    private function hasNeighbor($x, $y) {
        for ($i = -1; $i <= 1; $i++) {
            for ($j = -1; $j <= 1; $j++) {
                if ($i === 0 && $j === 0) continue;
                $nx = $x + $i;
                $ny = $y + $j;
                if ($nx >= 0 && $nx < $this->size && $ny >= 0 && $ny < $this->size) {
                    if ($this->board[$nx][$ny] !== 0) {
                        return true;
                    }
                }
            }
        }
        return false;
    }
    private function checkWinner($player) {
        $directions = [[0,1],[1,0],[1,1],[1,-1]];
        for ($i = 0; $i < $this->size; $i++) {
            for ($j = 0; $j < $this->size; $j++) {
                if ($this->board[$i][$j] === $player) {
                    foreach ($directions as $dir) {
                        $count = 1;
                        for ($k = 1; $k < 5; $k++) {
                            $nx = $i + $dir[0] * $k;
                            $ny = $j + $dir[1] * $k;
                            if ($nx < 0 || $nx >= $this->size || $ny < 0 || $ny >= $this->size) {
                                break;
                            }
                            if ($this->board[$nx][$ny] === $player) {
                                $count++;
                            } else {
                                break;
                            }
                        }
                        if ($count >= 5) return true;
                    }
                }
            }
        }
        return false;
    }
}

使用示例

<?php
// 简单对战示例
session_start();
// 游戏状态管理
function initGame() {
    $_SESSION['board'] = array_fill(0, 3, array_fill(0, 3, 0));
    $_SESSION['currentPlayer'] = 1; // 1 = 人类, 2 = AI
    $_SESSION['gameOver'] = false;
}
function playGame() {
    if (!isset($_SESSION['board'])) {
        initGame();
    }
    $ai = new SimpleAI('hard');
    // 人类走棋
    if (isset($_POST['move']) && $_SESSION['currentPlayer'] === 1) {
        $move = json_decode($_POST['move'], true);
        $_SESSION['board'][$move['row']][$move['col']] = 1;
        // 检查胜负
        if (checkWin($_SESSION['board'], 1)) {
            $_SESSION['gameOver'] = true;
            echo json_encode(['result' => 'win', 'board' => $_SESSION['board']]);
            return;
        }
        $_SESSION['currentPlayer'] = 2;
    }
    // AI走棋
    if ($_SESSION['currentPlayer'] === 2 && !$_SESSION['gameOver']) {
        // 添加延迟模拟"思考"
        sleep(1);
        $move = $ai->makeMove($_SESSION['board']);
        if ($move !== null) {
            $_SESSION['board'][$move[0]][$move[1]] = 2;
            // 检查AI是否获胜
            if (checkWin($_SESSION['board'], 2)) {
                $_SESSION['gameOver'] = true;
                echo json_encode(['result' => 'lose', 'board' => $_SESSION['board'], 'aiMove' => $move]);
                return;
            }
            $_SESSION['currentPlayer'] = 1;
            echo json_encode(['result' => 'continue', 'board' => $_SESSION['board'], 'aiMove' => $move]);
        } else {
            echo json_encode(['result' => 'draw', 'board' => $_SESSION['board']]);
        }
    }
}
function checkWin($board, $player) {
    // 检查胜利逻辑
    // ... 实现检查逻辑
}
// 前端AJAX处理
if (isset($_POST['action'])) {
    if ($_POST['action'] === 'move') {
        playGame();
    } else if ($_POST['action'] === 'reset') {
        session_destroy();
        initGame();
        echo json_encode(['success' => true, 'board' => $_SESSION['board']]);
    }
}

前端HTML

<!DOCTYPE html>
<html>
<head>PHP AI对战</title>
    <style>
        .board {
            display: grid;
            grid-template-columns: repeat(3, 100px);
            gap: 5px;
            margin: 20px;
        }
        .cell {
            width: 100px;
            height: 100px;
            border: 1px solid #000;
            font-size: 40px;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="board" id="board"></div>
    <button onclick="resetGame()">重新开始</button>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <script>
        let currentBoard = Array(3).fill(null).map(() => Array(3).fill(0));
        function renderBoard() {
            let boardHtml = '';
            for (let i = 0; i < 3; i++) {
                for (let j = 0; j < 3; j++) {
                    let symbol = '';
                    if (currentBoard[i][j] === 1) symbol = 'X';
                    if (currentBoard[i][j] === 2) symbol = 'O';
                    boardHtml += `<div class="cell" onclick="makeMove(${i}, ${j})">${symbol}</div>`;
                }
            }
            $('#board').html(boardHtml);
        }
        function makeMove(row, col) {
            if (currentBoard[row][col] !== 0) return;
            // 人类走棋
            currentBoard[row][col] = 1;
            renderBoard();
            // AI走棋
            $.ajax({
                url: 'game.php',
                method: 'POST',
                data: {
                    action: 'move',
                    board: JSON.stringify(currentBoard)
                },
                success: function(response) {
                    const result = JSON.parse(response);
                    currentBoard = result.board;
                    renderBoard();
                    if (result.result === 'win') {
                        alert('你赢了!');
                    } else if (result.result === 'lose') {
                        alert('AI赢了!');
                    } else if (result.result === 'draw') {
                        alert('平局!');
                    }
                }
            });
        }
        function resetGame() {
            $.ajax({
                url: 'game.php',
                method: 'POST',
                data: {
                    action: 'reset'
                },
                success: function(response) {
                    const result = JSON.parse(response);
                    currentBoard = result.board;
                    renderBoard();
                }
            });
        }
        renderBoard();
    </script>
</body>
</html>

优化建议

  1. 性能优化

    • 使用缓存存储游戏状态
    • 使用Redis/Memcached存储大量对局数据
    • 使用异步处理提升响应速度
  2. AI算法改进

    • 引入机器学习模型(需要PHP ML库)
    • 使用更复杂的评估函数
    • 实现蒙特卡洛树搜索(MCTS)
  3. 架构改进

    • 使用WebSocket实现实时对战
    • 添加用户系统和对战记录
    • 实现多局对战和排名系统

这个基础框架可以根据你的具体需求进行调整和扩展,需要我详细解释某个部分吗?

抱歉,评论功能暂时关闭!