Electron for鸿蒙PC实战项目之麻将游戏

项目概述

这是一个基于 Electron 开发的麻将游戏应用,实现了四人麻将的核心玩法和规则。本项目展示了如何在 Electron 环境中构建复杂的桌面游戏应用,包含游戏状态管理、AI 决策系统、用户交互处理和响应式界面设计。游戏支持 1 名人类玩家与 3 名 AI 对手进行对战,实现了完整的麻将游戏流程(洗牌、发牌、打牌、吃、碰、杠、胡)。同时新增鸿蒙 PC 平台适配方案,优化了 AI 决策效率、动画渲染流畅度和系统兼容性,核心玩法在鸿蒙端完全兼容,可作为复杂 Electron 游戏迁移鸿蒙 PC 的实践案例。

技术架构

项目采用 Electron 主进程 - 渲染进程架构,新增鸿蒙适配层,核心模块包括:

  1. 主进程模块:负责窗口管理、应用生命周期和鸿蒙环境适配
  2. 渲染进程模块:包含游戏核心逻辑、UI 渲染和用户交互(鸿蒙端优化)
  3. IPC 通信层:实现主进程和渲染进程之间的安全通信(鸿蒙端兼容)
  4. 游戏逻辑引擎:处理麻将规则、游戏流程和状态管理
  5. AI 决策系统:优化鸿蒙端决策效率,减少资源占用
  6. UI 渲染系统:适配鸿蒙 PC 窗口特性,简化动画提升流畅度
  7. 鸿蒙适配层:处理系统能力配置、库依赖管理和硬件兼容

核心算法实现(鸿蒙适配优化)

1. 游戏状态管理 - 鸿蒙兼容扩展

javascript

运行

复制代码
// 游戏状态(鸿蒙兼容优化)
const gameState = {
  status: 'ready', // ready, playing, paused, ended
  currentPlayer: 0,
  players: [
    { name: '玩家1', tiles: [], score: 0, isComputer: false },
    { name: '电脑1', tiles: [], score: 0, isComputer: true },
    { name: '电脑2', tiles: [], score: 0, isComputer: true },
    { name: '电脑3', tiles: [], score: 0, isComputer: true }
  ],
  discardedTiles: [],
  remainingTiles: [],
  round: 1,
  dealer: 0,
  selectedTile: null,
  // 新增:鸿蒙环境标记与性能配置
  isHarmonyOS: process.env.OHOS_ENV ? true : false,
  aiThinkDelay: process.env.OHOS_ENV ? 800 : 1000, // 鸿蒙端缩短AI思考延迟
  animationSpeed: process.env.OHOS_ENV ? 0.7 : 1.0 // 鸿蒙端加快动画速度提升流畅度
};

2. 主进程代码(main.js)- 鸿蒙核心适配

javascript

运行

复制代码
// Electron主进程代码(鸿蒙适配版)
const { app, BrowserWindow } = require('electron');
const path = require('path');
let mainWindow;

function createWindow() {
  // 鸿蒙PC必须禁用硬件加速(解决窗口渲染异常、动画卡顿问题)
  app.disableHardwareAcceleration();

  mainWindow = new BrowserWindow({
    width: 900,
    height: 700,
    title: '麻将游戏',
    resizable: true,
    webPreferences: {
      preload: path.join(__dirname, 'src', 'preload.js'),
      nodeIntegration: false, // 鸿蒙端强制关闭,提升安全性
      contextIsolation: true, // 保持上下文隔离,兼容鸿蒙web引擎
      enableRemoteModule: false
    },
    // 鸿蒙PC窗口适配优化
    fullscreenable: false, // 禁用全屏,避免系统兼容性冲突
    titleBarStyle: 'default', // 适配鸿蒙原生标题栏样式
    backgroundColor: '#f5f5f5' // 优化鸿蒙端初始渲染背景
  });

  // 加载应用的index.html
  mainWindow.loadFile(path.join(__dirname, 'src', 'index.html'));
  
  // 鸿蒙环境检测与额外配置
  if (process.env.OHOS_ENV) {
    console.log('Running on HarmonyOS PC, applying compatibility patches');
    // 鸿蒙端禁用窗口缩放动画,减少性能消耗
    mainWindow.setHasShadow(false);
  }

  // 窗口关闭时触发
  mainWindow.on('closed', () => {
    mainWindow = null;
  });
}

// 应用事件处理(保持原有逻辑,新增鸿蒙兼容)
app.whenReady().then(createWindow);
app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});
app.on('activate', () => {
  if (BrowserWindow.getAllWindows().length === 0) {
    createWindow();
  }
});

3. AI 决策系统 - 鸿蒙性能优化

针对鸿蒙端资源限制,优化 AI 决策逻辑,减少计算耗时:

javascript

运行

复制代码
// 电脑玩家动作(鸿蒙性能优化版)
function computerAction() {
  if (gameState.status !== 'playing') return;
  
  const player = gameState.players[gameState.currentPlayer];
  
  // 鸿蒙端优化:简化AI决策算法,减少递归和循环次数
  const tileToDiscard = gameState.isHarmonyOS 
    ? selectTileToDiscardHarmony(player.tiles) 
    : selectTileToDiscard(player.tiles);
  
  const tileIndex = player.tiles.findIndex(tile => 
    tile.type === tileToDiscard.type && tile.value === tileToDiscard.value
  );
  
  // 鸿蒙端缩短思考延迟,提升游戏流畅度
  setTimeout(() => {
    discardTile(gameState.currentPlayer, tileIndex);
  }, gameState.aiThinkDelay + (gameState.isHarmonyOS ? 0 : Math.random() * 1500));
}

// 鸿蒙端专用:简化的牌型分析与弃牌选择
function selectTileToDiscardHarmony(tiles) {
  // 核心策略:优先弃置风牌、箭牌等难以组成顺子/刻子的牌
  const sortedTiles = [...tiles].sort(sortTiles);
  
  // 分离序数牌(万、条、饼)和字牌(风、龙)
  const honorTiles = sortedTiles.filter(tile => 
    tile.type === 'wind' || tile.type === 'dragon'
  );
  
  // 优先弃置字牌
  if (honorTiles.length > 0) {
    // 进一步筛选:弃置单张字牌,保留成对字牌
    const honorCounts = {};
    honorTiles.forEach(tile => {
      const key = `${tile.type}-${tile.value}`;
      honorCounts[key] = (honorCounts[key] || 0) + 1;
    });
    
    const singleHonors = honorTiles.filter(tile => {
      const key = `${tile.type}-${tile.value}`;
      return honorCounts[key] === 1;
    });
    
    return singleHonors.length > 0 ? singleHonors[0] : honorTiles[0];
  }
  
  // 无一字牌时,弃置最孤立的序数牌(简化版分析)
  return sortedTiles[0];
}

4. 牌型识别与胡牌判定 - 鸿蒙算法优化

优化递归深度,避免鸿蒙端栈溢出,提升判定效率:

javascript

运行

复制代码
// 判断是否可以胡牌(鸿蒙优化版)
function canWin(tiles) {
  if (tiles.length !== 14) return false;
  
  const sortedTiles = [...tiles].sort(sortTiles);
  
  // 鸿蒙端优化:限制递归深度,使用迭代辅助判定
  for (let i = 0; i < sortedTiles.length; i++) {
    if (i < sortedTiles.length - 1 &&
        sortedTiles[i].type === sortedTiles[i + 1].type &&
        sortedTiles[i].value === sortedTiles[i + 1].value) {
      
      const remainingTiles = [...sortedTiles];
      remainingTiles.splice(i, 2);
      
      // 鸿蒙端使用优化后的判定函数
      if (gameState.isHarmonyOS) {
        if (checkWinningPatternHarmony(remainingTiles)) return true;
      } else {
        if (checkWinningPattern(remainingTiles)) return true;
      }
    }
  }
  
  return false;
}

// 鸿蒙端专用:迭代式牌型判定(替代递归,减少栈消耗)
function checkWinningPatternHarmony(tiles) {
  const stack = [tiles];
  
  while (stack.length > 0) {
    const currentTiles = stack.pop();
    
    if (currentTiles.length === 0) return true;
    
    // 尝试组成刻子
    if (currentTiles.length >= 3 &&
        currentTiles[0].type === currentTiles[1].type &&
        currentTiles[0].value === currentTiles[1].value &&
        currentTiles[0].type === currentTiles[2].type &&
        currentTiles[0].value === currentTiles[2].value) {
      
      const remaining = [...currentTiles];
      remaining.splice(0, 3);
      stack.push(remaining);
      continue;
    }
    
    // 尝试组成顺子
    if (currentTiles.length >= 3 &&
        currentTiles[0].type === currentTiles[1].type &&
        currentTiles[0].type === currentTiles[2].type &&
        canFormSequence(currentTiles[0], currentTiles[1], currentTiles[2])) {
      
      const remaining = [...currentTiles];
      remaining.splice(0, 3);
      stack.push(remaining);
      continue;
    }
  }
  
  return false;
}

5. UI 渲染系统 - 鸿蒙适配优化

简化动画效果,批量处理 DOM 操作,提升鸿蒙端渲染性能:

javascript

运行

复制代码
// 更新玩家手牌显示(鸿蒙适配版)
function updatePlayerTiles() {
  const currentPlayer = gameState.players[gameState.currentPlayer];
  const playerTilesContainer = elements.playerTiles.south;
  
  playerTilesContainer.innerHTML = '';
  const sortedTiles = [...currentPlayer.tiles].sort(sortTiles);
  
  // 鸿蒙端优化:使用DocumentFragment批量添加DOM,减少重绘
  const fragment = document.createDocumentFragment();
  
  sortedTiles.forEach((tile, index) => {
    const tileElement = document.createElement('div');
    tileElement.className = 'tile';
    tileElement.dataset.index = index;
    
    if (gameState.selectedTile === index) {
      tileElement.classList.add('selected');
    }
    
    // 仅对当前人类玩家添加点击事件
    if (!currentPlayer.isComputer) {
      tileElement.addEventListener('click', () => selectTile(index));
    }
    
    // 鸿蒙端简化牌面样式,减少CSS渲染压力
    if (gameState.isHarmonyOS) {
      tileElement.style.transition = 'transform 0.2s ease, box-shadow 0.2s ease';
      tileElement.innerHTML = `<span class="tile-icon simple">${getTileSimpleDisplayName(tile)}</span>`;
    } else {
      tileElement.textContent = getTileDisplayName(tile);
    }
    
    tileElement.dataset.type = tile.type;
    tileElement.dataset.value = tile.value;
    fragment.appendChild(tileElement);
  });
  
  playerTilesContainer.appendChild(fragment);
  
  // 鸿蒙端优化:其他玩家手牌使用简化渲染(减少DOM节点)
  updateOtherPlayersTilesHarmony();
}

// 鸿蒙端专用:简化其他玩家手牌渲染
function updateOtherPlayersTilesHarmony() {
  const otherPlayers = ['north', 'east', 'west'];
  otherPlayers.forEach(direction => {
    const container = elements.playerTiles[direction];
    container.innerHTML = '';
    
    const player = gameState.players[getPlayerIndexByDirection(direction)];
    const tileCount = player.tiles.length;
    
    // 不渲染具体牌面,仅显示牌背数量(减少DOM压力)
    for (let i = 0; i < tileCount; i++) {
      const tileElement = document.createElement('div');
      tileElement.className = 'tile tile-back simple';
      container.appendChild(tileElement);
    }
  });
}

6. IPC 通信机制 - 鸿蒙兼容调整

保持通信逻辑不变,优化鸿蒙端消息传递效率:

javascript

运行

复制代码
// 渲染进程preload.js(鸿蒙兼容版)
const { contextBridge, ipcRenderer } = require('electron');
const MAHJONG_CONSTANTS = require('./constants');

// 安全地暴露API给渲染进程
contextBridge.exposeInMainWorld('mahjongGame', {
  // 游戏控制API(鸿蒙端保持兼容)
  game: {
    start: () => ipcRenderer.send('game:start'),
    pause: () => ipcRenderer.send('game:pause'),
    resume: () => ipcRenderer.send('game:resume'),
    reset: () => ipcRenderer.send('game:reset')
  },
  
  // 窗口控制(适配鸿蒙窗口行为)
  window: {
    minimize: () => ipcRenderer.send('window:minimize'),
    maximize: () => {
      // 鸿蒙端禁用最大化,避免布局错乱
      if (!process.env.OHOS_ENV) {
        ipcRenderer.send('window:maximize');
      }
    },
    close: () => ipcRenderer.send('window:close')
  },
  
  // 对话框(鸿蒙端优化:使用系统原生对话框)
  dialog: {
    showMessageBox: (options) => ipcRenderer.invoke('dialog:showMessageBox', {
      ...options,
      // 鸿蒙端简化对话框样式,提升响应速度
      type: gameState.isHarmonyOS ? 'none' : options.type
    })
  },
  
  // 获取常量(新增鸿蒙环境标记)
  constants: {
    ...MAHJONG_CONSTANTS,
    IS_HARMONY_OS: process.env.OHOS_ENV ? true : false
  }
});

项目结构

1. 原始 Electron 项目结构(保持不变)

plaintext

复制代码
60-mahjong/
├── README.md          # 项目说明文档
├── main.js            # Electron主进程代码
├── package.json       # 项目配置和依赖
└── src/               # 渲染进程代码
    ├── index.html     # 应用主页面
    ├── preload.js     # 预加载脚本
    ├── renderer.js    # 游戏核心逻辑
    ├── constants.js   # 游戏常量
    └── style.css      # 样式表

2. 鸿蒙 PC 适配后项目结构(新增 / 调整)

plaintext

复制代码
ohos_hap/                # 鸿蒙应用根目录(整合Electron项目)
├── electron/            # Electron鸿蒙核心依赖
│   └── libs/
│       └── arm64-v8a/  # 鸿蒙核心库文件(必须完整)
│           ├── libelectron.so
│           ├── libadapter.so
│           ├── libffmpeg.so
│           └── libc++_shared.so
├── web_engine/
│   └── src/
│       └── main/
│           └── resources/
│               └── resfile/
│                   └── resources/
│                       └── app/  # 原有60-mahjong项目代码迁移至此
│                           ├── main.js          # 已适配鸿蒙的主进程代码
│                           ├── package.json     # 适配后的依赖配置
│                           └── src/             # 原有src目录完整迁移
│                               ├── index.html
│                               ├── preload.js
│                               ├── renderer.js
│                               ├── constants.js
│                               └── style.css
└── module.json5        # 鸿蒙应用配置文件(新增)

鸿蒙适配核心配置文件

1. package.json(适配调整)

json

复制代码
{
  "name": "mahjong-harmonyos",
  "version": "1.0.0",
  "main": "main.js",
  "scripts": {
    "start": "electron .", // 原有Electron运行脚本
    "dev": "electron . --dev", // 原有开发模式脚本
    "harmony:build": "ohos build --mode debug", // 新增鸿蒙编译脚本
    "harmony:run": "ohos run" // 新增鸿蒙运行脚本
  },
  "dependencies": {
    "electron": "^34.0.0" // 升级Electron至34+(鸿蒙适配最低要求)
  },
  // 新增鸿蒙适配配置
  "harmonyos": {
    "apiVersion": 20,
    "sysCapabilities": ["windowManager", "storage", "graphics", "multimedia.audio"]
  }
}

2. module.json5(鸿蒙新增配置文件)

json5

复制代码
{
  "app": {
    "bundleName": "com.example.mahjong",
    "bundleVersion": "1.0.0",
    "minAPIVersion": 20
  },
  "module": {
    "name": "mahjong_module",
    "type": "application",
    "srcPath": "./",
    "deviceTypes": ["pc"], // 指定为鸿蒙PC设备
    "reqSysCapabilities": [ // 仅保留必要系统能力
      "windowManager", // 窗口管理能力
      "storage", // 本地存储(游戏存档/分数记录)
      "graphics", // 图形渲染(手牌/动画)
      "multimedia.audio", // 音效播放
      "permission:ohos.permission.READ_USER_STORAGE",
      "permission:ohos.permission.WRITE_USER_STORAGE"
    ],
    "abilities": [
      {
        "name": "MainAbility",
        "srcPath": "./web_engine",
        "description": "麻将游戏主入口",
        "icon": "$media:icon",
        "label": "Mahjong Game",
        "visible": true,
        "launchType": "standard"
      }
    ]
  }
}

鸿蒙 PC 适配改造核心步骤

1. 环境准备

  • 系统要求:Windows 10/11、8GB RAM 以上、20GB 可用空间
  • 工具安装
    • DevEco Studio 5.0+(安装鸿蒙 SDK API 20+)
    • Node.js 18.x+
    • Electron 34+(鸿蒙适配最低版本)

2. 项目迁移与依赖配置

  1. 登录Electron 鸿蒙官方仓库
  2. 下载 Electron 34 + 版本的 Release 包(.zip 格式)
  3. 解压后将electron/libs/arm64-v8a/目录复制到ohos_hap/electron/libs/下(确保 4 个核心.so 库完整)
  4. 将原有 60-mahjong 项目的所有文件复制到ohos_hap/web_engine/src/main/resources/resfile/resources/app/目录下

3. 代码改造

  1. 修改 main.js:添加硬件加速禁用代码,优化窗口配置
  2. 调整 package.json:升级 Electron 版本,新增鸿蒙编译 / 运行脚本
  3. 创建 module.json5:配置应用信息、系统能力和设备类型
  4. 优化 renderer.js:
    • 新增鸿蒙环境判断逻辑
    • 简化 AI 决策算法和 UI 渲染效果
    • 用迭代替代部分递归,避免栈溢出
    • 批量处理 DOM 操作,减少重绘

4. 编译与运行

  1. 在 DevEco Studio 中打开 ohos_hap 目录
  2. 配置签名:进入 File → Project Structure → Signing Configs,自动生成调试签名
  3. 连接鸿蒙 PC 设备:启用开发者模式和 USB 调试,通过 USB Type-C 连接电脑
  4. 编译运行:点击 Run 按钮或执行npm run harmony:run

5. 验证检查项

  • ✅ 应用窗口正常显示,无黑屏 / 闪退
  • ✅ 洗牌、发牌流程正常,牌面无错位
  • ✅ AI 玩家自动出牌,无卡顿
  • ✅ 吃、碰、杠、胡等操作逻辑正常
  • ✅ 分数计算准确,游戏状态同步更新
  • ✅ 控制台无 "SysCap 不匹配" 或 "找不到.so 文件" 错误
  • ✅ 响应式布局生效,窗口大小可调整
  • ✅ 音效正常播放(若启用)

跨平台兼容性

平台 适配策略 特殊处理
Windows 标准 Electron 运行 无特殊配置
macOS 标准 Electron 运行 保留 dock 图标激活逻辑
Linux 标准 Electron 运行 确保系统依赖库完整
鸿蒙 PC 通过 Electron 鸿蒙适配层运行 1. 禁用硬件加速2. 使用特定目录结构3. 简化 AI 决策和 UI 渲染4. 用迭代替代部分递归算法5. 批量处理 DOM 操作6. 配置必要系统能力(windowManager、storage、graphics)

鸿蒙端调试技巧与常见问题解决

1. 调试技巧

  • 日志查看:在 DevEco Studio 的 Log 面板中过滤 "Electron" 或 "Mahjong" 关键词,定位错误
  • 性能分析:使用 DevEco Studio 的 Performance 工具,重点监控 AI 决策和 DOM 渲染耗时
  • 断点调试:在鸿蒙适配相关代码(如 AI 优化函数、渲染函数)中打断点,逐步调试

2. 常见问题解决

问题现象 解决方案
"SysCap 不匹配" 错误 检查 module.json5 中的 reqSysCapabilities,仅保留必要系统能力
"找不到.so 文件" 错误 确认 arm64-v8a 目录下 4 个核心库文件完整
窗口不显示 / 黑屏 在 main.js 中添加 app.disableHardwareAcceleration (),检查窗口尺寸配置
AI 决策卡顿 启用鸿蒙端专用 AI 函数 selectTileToDiscardHarmony,缩短思考延迟
胡牌判定错误 检查 checkWinningPatternHarmony 迭代逻辑,确保牌型分解正确
手牌渲染错位 简化鸿蒙端牌面样式,使用 DocumentFragment 批量添加 DOM
存储失败 确认 module.json5 中已申请存储权限,使用 try-catch 包裹 localStorage 操作

性能优化建议(鸿蒙端专属)

  1. 算法优化

    • 用迭代替代递归(如胡牌判定),避免栈溢出和性能消耗
    • 简化 AI 决策逻辑,优先基于规则筛选,减少复杂计算
    • 缓存牌型分析结果,避免重复计算
  2. 渲染优化

    • 简化 UI 样式,减少 CSS 动画和复杂选择器
    • 批量处理 DOM 操作,使用 DocumentFragment 减少重绘
    • 其他玩家手牌使用简化渲染(仅显示牌背数量)
  3. 资源优化

    • 压缩音效和图片资源,减少加载时间
    • 延迟加载非核心资源(如规则说明)
    • 及时清理事件监听,避免内存泄漏
  4. 交互优化

    • 缩短 AI 思考延迟和动画时长
    • 优化触摸板点击响应,提升操作精度
    • 窗口失去焦点时自动暂停游戏,减少资源占用

如何运行

1. 原有 Electron 环境(Windows/macOS/Linux)

bash

运行

复制代码
# 安装依赖
npm install

# 启动应用
npm start

# 开发模式
npm run dev

2. 鸿蒙 PC 环境

bash

运行

复制代码
# 进入鸿蒙应用根目录
cd ohos_hap

# 安装依赖
npm install

# 编译项目
npm run harmony:build

# 连接设备后运行
npm run harmony:run

总结

本项目提供了完整的三消游戏实现和 Electron 迁移鸿蒙 PC 的详细方案,重点优化了动画性能、算法效率和系统兼容性。通过学习本项目,您可以掌握 Electron 桌面应用开发、三消游戏核心算法(匹配检测、特殊方块逻辑)以及鸿蒙 PC 平台适配的关键技术,适合 Electron 开发者和鸿蒙生态开发者参考实践。

相关推荐
晚霞的不甘2 小时前
Flutter + OpenHarmony 发布与运维指南:从上架 AppGallery 到线上监控的全生命周期管理
运维·flutter·harmonyos
大雨倾城2 小时前
网页端和桌面端的electron通信Webview
javascript·vue.js·react.js·electron
鸿蒙开发工程师—阿辉2 小时前
HarmonyOS 5 极致动效实验室:粒子动画与高性能特效
华为·harmonyos
yuegu7772 小时前
Electron for鸿蒙PC实战项目之俄罗斯方块游戏
华为·electron·harmonyos
FrameNotWork2 小时前
HarmonyOS 应用性能优化全指南:渲染、状态管理、线程、内存、网络一站式提升
华为·性能优化·harmonyos
晚霞的不甘2 小时前
Flutter + OpenHarmony 插件开发指南:深度集成原生能力,打造高性能鸿蒙扩展
flutter·华为·harmonyos
搬砖的青蛙12 小时前
游戏运行库整合包,可避免99%游戏启动问题,支持xp-11系统
游戏·运行库·xp-11
遇到困难睡大觉哈哈16 小时前
HarmonyOS —— Remote Communication Kit 拦截器(Interceptor)高阶定制能力笔记
笔记·华为·harmonyos