遊戲 AI 基礎:從簡單規則到智能對手 🤖
在任何遊戲中,AI 對手的設計都是決定玩家體驗的關鍵因素。一個設計優良的遊戲 AI 不僅要有挑戰性,還要讓玩家感覺「可以戰勝」而不是「完全無法獲勝」。本文將從最基礎的概念開始,帶你了解遊戲 AI 的核心原理、常見算法和實作技巧。
什麼是遊戲 AI? 🎮
遊戲 AI(Game Artificial Intelligence)是指在電子遊戲中控制非玩家角色(NPC)行為的系統。與學術界的「真正的 AI」(如深度學習、神經網路)不同,遊戲 AI 的目標不是「盡可能聰明」,而是「提供有趣且平衡的挑戰」。
遊戲 AI vs 學術 AI
| 特性 | 遊戲 AI | 學術 AI |
|---|---|---|
| 目標 | 提供娛樂性和挑戰性 | 解決複雜問題,追求最優解 |
| 性能要求 | 即時運算(毫秒級) | 可以花費較長時間 |
| 可預測性 | 需要一定程度的可預測性 | 不需要 |
| 失敗容忍度 | 允許「故意犯錯」 | 追求零錯誤 |
| 技術 | 規則引擎、狀態機、簡單演算法 | 機器學習、深度學習、強化學習 |
💡 關鍵洞察:最好的遊戲 AI 不是「最聰明的」,而是「最有趣的」。一個永遠不會輸的 AI 對手會讓玩家感到沮喪,而一個太笨的 AI 則會讓遊戲變得無聊。平衡是關鍵。
AI 難度等級設計 📊
設計多層次的 AI 難度是提供良好遊戲體驗的重要策略。以下是常見的難度等級設計方法:
方法 1:反應時間調整
最簡單的難度控制方法是調整 AI 的「思考時間」或「反應速度」。
範例:石頭剪刀布 AI
class RockPaperScissorsAI {
constructor(difficulty = 'medium') {
this.difficulty = difficulty;
this.delayMap = {
easy: 2000, // 2 秒延遲(給玩家更多思考時間)
medium: 1000, // 1 秒延遲
hard: 500 // 0.5 秒延遲
};
}
async makeMove() {
await this.delay(this.delayMap[this.difficulty]);
return this.selectMove();
}
delay(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
selectMove() {
const moves = ['rock', 'paper', 'scissors'];
return moves[Math.floor(Math.random() * 3)];
}
}
方法 2:決策品質調整
更進階的方法是調整 AI 做出「最佳決策」的機率。
範例:基於機率的決策
class SmartAI {
constructor(difficulty = 'medium') {
// 不同難度下做出最佳決策的機率
this.accuracyMap = {
easy: 0.3, // 30% 機率選擇最佳移動
medium: 0.6, // 60% 機率
hard: 0.9 // 90% 機率
};
this.accuracy = this.accuracyMap[difficulty];
}
makeMove(gameState) {
// 計算最佳移動
const bestMove = this.calculateBestMove(gameState);
// 根據難度決定是否採用最佳移動
if (Math.random() < this.accuracy) {
return bestMove; // 使用最佳移動
} else {
return this.getRandomMove(); // 使用隨機移動
}
}
calculateBestMove(gameState) {
// 使用 Minimax 或其他演算法計算最佳移動
// ...
}
getRandomMove() {
const allMoves = this.getAllPossibleMoves();
return allMoves[Math.floor(Math.random() * allMoves.length)];
}
}
方法 3:資訊限制
限制 AI 能看到的資訊範圍,模擬人類玩家的「視野限制」。
| 難度 | 可見資訊 | 範例 |
|---|---|---|
| 簡單 | 只看當前狀態 | 只考慮下一步 |
| 中等 | 看 2-3 步 | 預測玩家下 2 步 |
| 困難 | 看 5+ 步 | 長期策略規劃 |
常見遊戲 AI 算法 🧠
1. 決策樹(Decision Tree)
最簡單的 AI 結構,適合規則明確的遊戲。
簡單決策樹範例
class SimpleAI {
makeDecision(gameState) {
if (gameState.playerHealth < 30) {
// 玩家血量低,主動攻擊
return 'ATTACK';
} else if (gameState.selfHealth < 20) {
// 自己血量低,防禦或治療
return gameState.hasPotion ? 'HEAL' : 'DEFEND';
} else if (gameState.distance > 5) {
// 距離太遠,靠近
return 'MOVE_CLOSER';
} else {
// 正常戰鬥
return Math.random() > 0.5 ? 'ATTACK' : 'DEFEND';
}
}
}
優點:簡單、快速、可預測
缺點:缺乏靈活性,容易被玩家找到規律
2. 有限狀態機(Finite State Machine, FSM)
將 AI 的行為分為多個「狀態」,根據條件在狀態間轉換。
狀態機範例
class EnemyAI {
constructor() {
this.state = 'PATROL'; // 初始狀態:巡邏
}
update(gameState) {
switch (this.state) {
case 'PATROL':
this.patrol();
if (this.detectPlayer(gameState)) {
this.state = 'CHASE';
}
break;
case 'CHASE':
this.chasePlayer(gameState);
if (this.inAttackRange(gameState)) {
this.state = 'ATTACK';
} else if (!this.canSeePlayer(gameState)) {
this.state = 'PATROL';
}
break;
case 'ATTACK':
this.attackPlayer();
if (!this.inAttackRange(gameState)) {
this.state = 'CHASE';
} else if (this.health < 20) {
this.state = 'RETREAT';
}
break;
case 'RETREAT':
this.retreat();
if (this.health > 50) {
this.state = 'PATROL';
}
break;
}
}
}
優點:結構清晰、易於調試和擴展
缺點:狀態多時會變得複雜
3. Minimax 算法(回合制遊戲)
用於兩人回合制遊戲(如西洋棋、五子棋),通過遞歸搜尋找到最優移動。
Minimax 原理
- Max 層:AI 的回合,選擇能獲得最高分數的移動
- Min 層:玩家的回合,假設玩家會選擇讓 AI 分數最低的移動
- 遞歸:模擬未來 N 步,回溯計算每個移動的最終價值
Minimax 實現(簡化版)
function minimax(board, depth, isMaximizing) {
// 終止條件:到達深度限制或遊戲結束
if (depth === 0 || isGameOver(board)) {
return evaluateBoard(board);
}
if (isMaximizing) {
// AI 的回合:找最大值
let maxScore = -Infinity;
for (let move of getAllPossibleMoves(board)) {
const newBoard = makeMove(board, move);
const score = minimax(newBoard, depth - 1, false);
maxScore = Math.max(maxScore, score);
}
return maxScore;
} else {
// 玩家的回合:找最小值
let minScore = Infinity;
for (let move of getAllPossibleMoves(board)) {
const newBoard = makeMove(board, move);
const score = minimax(newBoard, depth - 1, true);
minScore = Math.min(minScore, score);
}
return minScore;
}
}
// 找出最佳移動
function findBestMove(board, depth) {
let bestMove = null;
let bestScore = -Infinity;
for (let move of getAllPossibleMoves(board)) {
const newBoard = makeMove(board, move);
const score = minimax(newBoard, depth - 1, false);
if (score > bestScore) {
bestScore = score;
bestMove = move;
}
}
return bestMove;
}
優點:在完全資訊遊戲中能找到最優解
缺點:計算量大,需要剪枝優化(Alpha-Beta 剪枝)
4. 行為樹(Behavior Tree)
現代遊戲中最常用的 AI 架構,靈活且模組化。
行為樹由以下節點組成:
- Sequence(序列):依次執行所有子節點,全部成功才成功
- Selector(選擇):依次嘗試子節點,有一個成功就成功
- Action(動作):具體執行的行為(攻擊、移動等)
- Condition(條件):檢查條件是否滿足
行為樹結構範例
Selector(根節點) ├─ Sequence(戰鬥序列) │ ├─ Condition: 玩家在視野內? │ ├─ Condition: 血量 > 30? │ └─ Action: 攻擊玩家 │ ├─ Sequence(治療序列) │ ├─ Condition: 血量 < 30? │ ├─ Condition: 有治療藥水? │ └─ Action: 使用藥水 │ └─ Action: 巡邏
優點:模組化、易於擴展和重用
缺點:設計複雜度較高
實戰技巧與最佳實踐 💡
1. 讓 AI 看起來「人性化」
- ✅ 添加隨機延遲:AI 不應該瞬間反應,加入 200-500ms 的延遲讓它看起來「在思考」
- ✅ 偶爾犯錯:即使在困難模式,也讓 AI 有 5-10% 的機率做出次優選擇
- ✅ 模擬「學習」:記錄玩家的慣用策略,稍微調整 AI 的行為來應對
- ✅ 視覺/音效回饋:讓 AI 的「思考過程」可視化(如顯示「...」)
2. 性能優化
- ⚡ 限制搜尋深度:Minimax 算法不要超過 4-6 層深度
- ⚡ 使用 Alpha-Beta 剪枝:減少 Minimax 的計算量(通常減少 50-70%)
- ⚡ 快取結果:記住已計算過的遊戲狀態(記憶化)
- ⚡ 異步執行:將 AI 計算放在 Web Worker 中,避免阻塞 UI
3. 平衡性設計
- ⚖️ 動態難度調整:根據玩家表現自動調整 AI 難度
- ⚖️ 提供多種模式:讓玩家自行選擇合適的挑戰等級
- ⚖️ 測試不同技能水平:找新手和高手測試,確保所有人都能享受
- ⚖️ 避免「完美 AI」:除非是「不可能模式」,否則保留玩家獲勝的機會
總結與下一步 🎯
遊戲 AI 的設計是藝術與科學的結合。關鍵要點:
- 🎯 目標是「有趣」而非「完美」:AI 應該提供適當的挑戰,而非碾壓玩家
- 🔄 從簡單開始:先實現基本的決策樹或狀態機,再逐步增加複雜度
- 🧪 持續測試:不同玩家對「難度」的感受差異很大,需要廣泛測試
- ⚙️ 提供可調節性:讓玩家或設計師能輕鬆調整 AI 參數
- 📊 收集數據:追蹤玩家勝率、平均遊戲時長等,指導優化方向
🚀 實戰練習
想要親自體驗不同難度的遊戲 AI 嗎?試試我們的石頭剪刀布和猜字遊戲工具:
閱讀更多相關文章: