通过鸿蒙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 未来展望

后续可扩展功能:

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

相关推荐
meilindehuzi_a1 小时前
掌握 ES6 核心语法与大模型(NLP)项目工程化搭建指南
前端·自然语言处理·es6
zhangfeng11331 小时前
deepseek 适配了 华为升腾 是不是 用了类似Megatron-LM deepSpeed框架的??
人工智能·华为
IT_陈寒1 小时前
Vue组件通信这个坑我跳了两次才知道怎么爬出来
前端·人工智能·后端
冰暮流星1 小时前
javascript建立对象之构造函数
开发语言·javascript·ecmascript
smallswan1 小时前
第十四 算数运算
linux·服务器·前端
AI_零食1 小时前
甄嬛人物日志-朗读升级 - 鸿蒙PC Electron框架完整技术实现指南
前端·学习·华为·electron·鸿蒙·鸿蒙系统
HackTwoHub1 小时前
WEB扫描器Invicti-Professional-V26.50.0(自动化爬虫扫描)更新
前端·人工智能·chrome·爬虫·web安全·网络安全·自动化
copyer_xyf1 小时前
Python 文件基本操作
前端·后端·python
Dream-Y.ocean1 小时前
[鸿蒙PC三方库适配实战] 跨平台媒体播放器 mpv 的 鸿蒙PC 平台迁移实践
华为·harmonyos