通过鸿蒙PC Electron框架技术完成-井字棋游戏 - 实现详解

欢迎加入开源鸿蒙PC社区:

https://harmonypc.csdn.net/

atomgit仓库地址: https://atomgit.com/m0_66062719/jingziqi

一、项目概述

井字棋是一款经典的双人对战游戏,本应用实现了完整的游戏逻辑,支持双人模式和人机对战模式。游戏使用Minimax算法实现AI对手,提供不可战胜的游戏体验。

1.1 功能定位

功能模块 核心能力 业务价值
游戏引擎 棋盘管理、胜负判断 核心游戏逻辑
AI对手 Minimax算法决策 单人游戏体验
计分系统 实时分数统计 竞技性激励
数据持久化 游戏数据保存 进度延续

1.2 技术目标

  • 游戏完整性:完整实现井字棋规则
  • AI智能:实现最优策略的AI对手
  • 用户体验:流畅动画和直观交互
  • 跨平台:一次开发,多端运行

二、技术架构设计

2.1 整体架构

复制代码
┌─────────────────────────────────────────────────────────────┐
│                    表示层 (UI)                            │
│  游戏棋盘、玩家信息、计分板、获胜弹窗                      │
├─────────────────────────────────────────────────────────────┤
│                    业务逻辑层                              │
│  TicTacToe类:游戏引擎、AI决策、胜负判断                 │
├─────────────────────────────────────────────────────────────┤
│                    数据层                                  │
│   LocalStorage:分数统计、游戏记录                       │
└─────────────────────────────────────────────────────────────┘

2.2 核心类设计

javascript 复制代码
class TicTacToe {
    constructor() {
        this.board = Array(9).fill(null);  // 3×3棋盘
        this.currentPlayer = 'X';           // 当前玩家
        this.gameActive = true;            // 游戏状态
        this.isVsAI = false;               // 是否人机对战
        this.winningCombinations = [/* 获胜组合 */];
    }
}

三、核心代码实现

3.1 游戏引擎

javascript 复制代码
makeMove(index) {
    if (!this.gameActive || this.board[index] !== null) return;
    
    this.board[index] = this.currentPlayer;
    this.updateBoard();
    
    if (this.checkWin()) {
        this.handleWin();
    } else if (this.checkDraw()) {
        this.handleDraw();
    } else {
        this.switchPlayer();
        
        if (this.isVsAI && this.currentPlayer === 'O' && this.gameActive) {
            setTimeout(() => this.aiMove(), 500);
        }
    }
}

游戏流程:

  1. 验证移动合法性
  2. 更新棋盘状态
  3. 检查胜负
  4. 切换玩家或触发AI

3.2 胜负判断

javascript 复制代码
winningCombinations = [
    [0, 1, 2], [3, 4, 5], [6, 7, 8],  // 横向
    [0, 3, 6], [1, 4, 7], [2, 5, 8],  // 纵向
    [0, 4, 8], [2, 4, 6]              // 对角线
];

checkWin() {
    for (const combo of this.winningCombinations) {
        const [a, b, c] = combo;
        if (this.board[a] && this.board[a] === this.board[b] && this.board[a] === this.board[c]) {
            this.winningCells = combo;
            return true;
        }
    }
    return false;
}

判断逻辑:

  • 遍历8种获胜组合
  • 检查三个位置是否为同一玩家
  • 记录获胜格子用于高亮显示

3.3 Minimax算法

javascript 复制代码
minimax(board, depth, isMaximizing) {
    const scores = {
        X: -10 + depth,
        O: 10 - depth,
        draw: 0
    };
    
    const result = this.checkResult(board);
    if (result !== null) {
        return scores[result];
    }
    
    if (isMaximizing) {
        let bestScore = -Infinity;
        for (let i = 0; i < 9; i++) {
            if (board[i] === null) {
                board[i] = 'O';
                const score = this.minimax(board, depth + 1, false);
                board[i] = null;
                bestScore = Math.max(score, bestScore);
            }
        }
        return bestScore;
    } else {
        let bestScore = Infinity;
        for (let i = 0; i < 9; i++) {
            if (board[i] === null) {
                board[i] = 'X';
                const score = this.minimax(board, depth + 1, true);
                board[i] = null;
                bestScore = Math.min(score, bestScore);
            }
        }
        return bestScore;
    }
}

算法原理:

  • 递归遍历所有可能的移动
  • Maximizing玩家(AI)选择最高分
  • Minimizing玩家(人类)选择最低分
  • 深度加权:更快获胜/更晚失败得分更高

3.4 AI决策

javascript 复制代码
getBestMove() {
    let bestScore = -Infinity;
    let bestMove = -1;
    
    for (let i = 0; i < 9; i++) {
        if (this.board[i] === null) {
            this.board[i] = 'O';
            const score = this.minimax(this.board, 0, false);
            this.board[i] = null;
            
            if (score > bestScore) {
                bestScore = score;
                bestMove = i;
            }
        }
    }
    
    return bestMove;
}

决策流程:

  1. 遍历所有空位
  2. 模拟AI落子
  3. 使用Minimax评估得分
  4. 选择最高分的位置

四、界面设计

4.1 深色游戏主题

css 复制代码
body {
    background: linear-gradient(135deg, #1a1a2e 0%, #16213e 50%, #0f3460 100%);
}

.header h1 {
    background: linear-gradient(135deg, #e94560 0%, #ff6b6b 50%, #ffa502 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
}

色彩方案:

  • 深蓝紫色背景营造游戏氛围
  • 渐变色标题吸引注意力
  • 红色X和橙色O区分玩家

4.2 棋子动画

css 复制代码
.cell.X {
    color: #e94560;
    animation: xPop 0.3s ease-out;
}

.cell.O {
    color: #ffa502;
    animation: oPop 0.3s ease-out;
}

@keyframes xPop {
    0% { transform: scale(0); opacity: 0; }
    50% { transform: scale(1.2); }
    100% { transform: scale(1); opacity: 1; }
}

@keyframes oPop {
    0% { transform: scale(0) rotate(0deg); }
    50% { transform: scale(1.2) rotate(180deg); }
    100% { transform: scale(1) rotate(360deg); }
}

动画效果:

  • X棋子:缩放弹出
  • O棋子:旋转弹出
  • 增强交互反馈

4.3 获胜效果

css 复制代码
.cell.win {
    background: rgba(233, 69, 96, 0.3);
    animation: winPulse 0.5s ease-in-out infinite;
}

@keyframes winPulse {
    0%, 100% { box-shadow: 0 0 20px rgba(233, 69, 96, 0.4); }
    50% { box-shadow: 0 0 40px rgba(233, 69, 96, 0.8); }
}

五、数据持久化

5.1 LocalStorage使用

javascript 复制代码
loadStats() {
    const saved = localStorage.getItem('ticTacToeStats');
    if (saved) {
        const data = JSON.parse(saved);
        this.scores = data.scores || this.scores;
        this.stats = data.stats || this.stats;
    }
}

saveStats() {
    const data = {
        scores: this.scores,
        stats: this.stats
    };
    localStorage.setItem('ticTacToeStats', JSON.stringify(data));
}

存储数据结构:

javascript 复制代码
{
    scores: { X: 5, O: 3 },
    stats: {
        totalGames: 10,
        drawGames: 2,
        currentStreak: 3,
        lastWinner: 'X'
    }
}

六、功能模块详解

6.1 模式切换

javascript 复制代码
toggleMode() {
    this.isVsAI = !this.isVsAI;
    const btn = document.getElementById('toggleModeBtn');
    btn.textContent = this.isVsAI ? '🤖 人机对战' : '👤 双人模式';
    
    if (this.isVsAI) {
        document.getElementById('playerO').innerHTML = `
            <span class="player-icon">🤖</span>
            <span class="player-name">AI对手</span>
            <span class="player-score">${this.scores.O}</span>
        `;
    } else {
        document.getElementById('playerO').innerHTML = `
            <span class="player-icon">⭕</span>
            <span class="player-name">玩家O</span>
            <span class="player-score">${this.scores.O}</span>
        `;
    }
    
    this.newRound();
}

6.2 游戏统计

javascript 复制代码
handleWin() {
    this.gameActive = false;
    this.scores[this.currentPlayer]++;
    this.stats.totalGames++;
    
    if (this.stats.lastWinner === this.currentPlayer) {
        this.stats.currentStreak++;
    } else {
        this.stats.currentStreak = 1;
    }
    this.stats.lastWinner = this.currentPlayer;
    
    this.highlightWinningCells();
    this.saveStats();
}

6.3 获胜弹窗

javascript 复制代码
showWinOverlay(player) {
    document.getElementById('winIcon').textContent = '🎉';
    document.getElementById('winText').textContent = `玩家${player} 获胜!`;
    document.getElementById('winOverlay').classList.add('show');
}

七、Minimax算法详解

7.1 算法原理

Minimax是一种零和博弈算法,用于在完全信息游戏中找到最优策略。

复制代码
        当前状态
         / | \
        /  |  \
       A   B   C  ← Maximizing层 (AI选择)
      /|\       |
     D E F      G ← Minimizing层 (人类选择)
    ...        ...

7.2 评估函数

javascript 复制代码
const scores = {
    X: -10 + depth,   // 人类获胜,深度越小惩罚越大
    O: 10 - depth,    // AI获胜,深度越小奖励越大
    draw: 0           // 平局
};

深度加权原因:

  • 更快获胜更好(AI优先选择快速获胜的路径)
  • 更晚失败更好(AI优先选择延迟失败的路径)

7.3 状态空间

井字棋的状态空间相对较小:

  • 最多9步
  • 约5478种有效状态
  • 完全搜索可行

八、扩展功能建议

8.1 难度调整

javascript 复制代码
// 限制搜索深度实现难度调整
minimax(board, depth, isMaximizing, maxDepth = 9) {
    if (depth >= maxDepth) {
        return this.evaluateBoard(board);
    }
    // ...
}

8.2 历史记录

javascript 复制代码
// 记录所有游戏步骤
class GameHistory {
    constructor() {
        this.history = [];
    }
    
    addMove(player, position) {
        this.history.push({ player, position, timestamp: Date.now() });
    }
    
    replay() {
        // 重新播放游戏
    }
}

8.3 在线对战

javascript 复制代码
// WebSocket实现在线对战
const socket = new WebSocket('wss://game-server.com');

socket.onmessage = (event) => {
    const move = JSON.parse(event.data);
    app.makeMove(move.position);
};

九、总结

9.1 技术成果

成功实现了一个完整的井字棋游戏,包含:

  1. 游戏引擎:完整的3×3棋盘管理
  2. Minimax AI:不可战胜的AI对手
  3. 双人模式:本地双人对战
  4. 计分系统:实时分数和统计
  5. 数据持久化:LocalStorage保存
  6. 动画效果:流畅的视觉反馈

9.2 技术价值

  • 算法学习:实践Minimax博弈算法
  • 游戏设计:完整的游戏状态管理
  • 用户体验:流畅的交互和动画

9.3 未来展望

后续可扩展功能:

  • 难度级别调整
  • 游戏历史记录
  • 在线多人对战
  • 移动端优化

相关推荐
风花一世月4 分钟前
⚡ 我把一座含氢能源园区搬进了浏览器(五类能流实时算守恒,在线直接玩)
前端·人工智能
棉猴4 分钟前
玩游戏学Python4-字符串
python·游戏·字符串·pygame·玩游戏
释厄62318 分钟前
智能体释放度子集律——文本 ⊂ 音频 ⊂ 视频⊂ 游戏
开发语言·游戏·microsoft·音视频
羲云25 分钟前
Claude 越界事件之后:Agent 权限设计为什么不能只靠提示词
前端
行者全栈架构师39 分钟前
【鸿蒙心迹】鸿蒙网络请求架构实战——@ohos.net.http 到 Axios 封装、拦截器与统一错误处理(HarmonyOS 7.x)
前端·算法·架构
全栈Agent 小李1 小时前
【无标题】
前端·后端·agent·ai编程·全栈·cursor·mcp
羲云1 小时前
别让 AI 凭记忆做调研:给 WorkBuddy 接上可核验的实时搜索
前端
只睡四小时1 小时前
AI 生成 PPTX:11 页课件编译出 429 个形状
javascript·python·pptx·ai生成ppt·ooxml
老陈说编程1 小时前
2. 鸿蒙(HarmonyOS)超级终端与生态
华为·harmonyos
deli0071 小时前
连接池到底配多大?QPS 和 RT 算一遍,再跑 1 万次请求实测超时率
前端