五子棋游戏开发详解:基于鸿蒙Electron框架和HTML5 Canvas
本文介绍了一款基于Electron和HTML5 Canvas开发的PC版五子棋游戏。该游戏支持15×15标准棋盘,提供三种AI难度等级:简单(随机下棋)、中等(攻防策略)和困难(Minimax算法)。核心功能包括棋盘绘制、胜负判断、AI对战等,采用Canvas实现流畅的图形渲染。技术栈选用Electron实现跨平台桌面应用,结合HTML5/CSS/JavaScript实现游戏逻辑与界面。文章详细解
欢迎加入开源鸿蒙PC社区:
https://harmonypc.csdn.net/
开源atomgit仓库地址:
https://atomgit.com/feng8403000/wuziqi
演示效果



项目背景
五子棋是一种古老而经典的策略棋类游戏,深受人们喜爱。在现代数字化时代,将传统游戏搬到电脑平台上,不仅可以保留游戏的乐趣,还可以通过AI技术提供不同难度的挑战,让玩家随时随地享受游戏的乐趣。
本文将详细介绍如何使用Electron和HTML5 Canvas开发一款PC版五子棋游戏,包括游戏界面设计、核心逻辑实现、AI算法开发以及不同难度等级的实现。
技术栈选择
前端技术
- HTML5 Canvas:用于绘制棋盘和棋子,提供流畅的游戏视觉体验
- JavaScript:实现游戏逻辑和AI算法
- CSS:设计美观的游戏界面
后端技术
- Electron:构建跨平台桌面应用,提供原生桌面体验
技术优势
- 跨平台:Electron可以在Windows、macOS和Linux上运行
- 性能优异:Canvas绘制提供高效的图形渲染
- 开发效率高:使用熟悉的Web技术栈,开发周期短
- 用户体验好:桌面应用提供更沉浸式的游戏体验
游戏功能介绍
核心功能
- 15x15标准棋盘:符合五子棋标准规则的棋盘大小
- 三种难度等级:
- 简单:电脑随机下棋
- 中等:电脑会攻击和防守
- 困难:使用Minimax算法,具有较高的智能
- 玩家与电脑对战:玩家执黑棋,电脑执白棋
- 胜负判断:自动检测五子连珠,判断游戏结果
- 游戏状态显示:实时显示当前游戏状态和轮到谁下棋
- 游戏控制:开始游戏、重新开始功能
界面设计
- 简洁美观:采用现代化的UI设计,界面清爽整洁
- 响应式布局:适配不同窗口大小
- 视觉反馈:下棋时有明显的视觉反馈
- 游戏结束模态框:游戏结束时显示结果
核心代码分析
1. 棋盘绘制
// 绘制棋盘
function drawBoard() {
// 清空画布
ctx.clearRect(0, 0, canvas.width, canvas.height);
// 绘制棋盘网格
ctx.strokeStyle = '#333';
ctx.lineWidth = 1;
for (let i = 0; i < BOARD_SIZE; i++) {
// 绘制垂直线
ctx.beginPath();
ctx.moveTo(i * CELL_SIZE + CELL_SIZE / 2, CELL_SIZE / 2);
ctx.lineTo(i * CELL_SIZE + CELL_SIZE / 2, (BOARD_SIZE - 1) * CELL_SIZE + CELL_SIZE / 2);
ctx.stroke();
// 绘制水平线
ctx.beginPath();
ctx.moveTo(CELL_SIZE / 2, i * CELL_SIZE + CELL_SIZE / 2);
ctx.lineTo((BOARD_SIZE - 1) * CELL_SIZE + CELL_SIZE / 2, i * CELL_SIZE + CELL_SIZE / 2);
ctx.stroke();
}
// 绘制棋子
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === PLAYER) {
drawStone(i, j, '#000'); // 黑棋
} else if (board[i][j] === AI) {
drawStone(i, j, '#fff'); // 白棋
}
}
}
}
代码解析:
- 使用Canvas API绘制15x15的棋盘网格
- 绘制垂直线和水平线,形成棋盘格子
- 根据棋盘数组状态绘制黑白棋子
- 每次棋盘状态变化时调用此函数重绘
2. 胜负判断
// 检查是否获胜
function checkWin(x, y, player) {
// 检查水平方向
let count = 0;
for (let i = Math.max(0, x - 4); i <= Math.min(BOARD_SIZE - 1, x + 4); i++) {
if (board[i][y] === player) {
count++;
if (count === 5) return true;
} else {
count = 0;
}
}
// 检查垂直方向
count = 0;
for (let j = Math.max(0, y - 4); j <= Math.min(BOARD_SIZE - 1, y + 4); j++) {
if (board[x][j] === player) {
count++;
if (count === 5) return true;
} else {
count = 0;
}
}
// 检查对角线方向(左上到右下)
count = 0;
let i = x - 4;
let j = y - 4;
while (i <= x + 4 && j <= y + 4) {
if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE) {
if (board[i][j] === player) {
count++;
if (count === 5) return true;
} else {
count = 0;
}
}
i++;
j++;
}
// 检查对角线方向(右上到左下)
count = 0;
i = x + 4;
j = y - 4;
while (i >= x - 4 && j <= y + 4) {
if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE) {
if (board[i][j] === player) {
count++;
if (count === 5) return true;
} else {
count = 0;
}
}
i--;
j++;
}
return false;
}
代码解析:
- 检查四个方向:水平、垂直、两个对角线
- 每个方向检查以当前落子为中心的9个格子(前后各4个)
- 连续5个相同颜色的棋子则判定为获胜
- 边界处理:确保不会检查棋盘外的格子
3. AI算法实现
简单难度:随机下棋
// 简单难度:随机下棋
function getEasyMove() {
const emptyCells = [];
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
emptyCells.push({ x: i, y: j });
}
}
}
if (emptyCells.length > 0) {
const randomIndex = Math.floor(Math.random() * emptyCells.length);
return emptyCells[randomIndex];
}
return null;
}
中等难度:攻击-防守策略
// 中等难度:优先攻击,其次防守
function getMediumMove() {
// 检查是否有获胜的一步
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
board[i][j] = AI;
if (checkWin(i, j, AI)) {
board[i][j] = EMPTY;
return { x: i, y: j };
}
board[i][j] = EMPTY;
}
}
}
// 检查是否需要防守
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
board[i][j] = PLAYER;
if (checkWin(i, j, PLAYER)) {
board[i][j] = EMPTY;
return { x: i, y: j };
}
board[i][j] = EMPTY;
}
}
}
// 否则随机下棋
return getEasyMove();
}
困难难度:Minimax算法
// 困难难度:基于评分系统
function getHardMove() {
let bestScore = -Infinity;
let bestMove = null;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
board[i][j] = AI;
let score = minimax(board, 3, -Infinity, Infinity, false);
board[i][j] = EMPTY;
if (score > bestScore) {
bestScore = score;
bestMove = { x: i, y: j };
}
}
}
}
return bestMove || getMediumMove();
}
// minimax算法
function minimax(board, depth, alpha, beta, isMaximizing) {
// 检查是否有获胜者
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === AI && checkWin(i, j, AI)) {
return 1000;
}
if (board[i][j] === PLAYER && checkWin(i, j, PLAYER)) {
return -1000;
}
}
}
// 检查是否平局
if (isBoardFull() || depth === 0) {
return evaluateBoard(board);
}
if (isMaximizing) {
let maxScore = -Infinity;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
board[i][j] = AI;
let score = minimax(board, depth - 1, alpha, beta, false);
board[i][j] = EMPTY;
maxScore = Math.max(maxScore, score);
alpha = Math.max(alpha, score);
if (beta <= alpha) {
break;
}
}
}
}
return maxScore;
} else {
let minScore = Infinity;
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === EMPTY) {
board[i][j] = PLAYER;
let score = minimax(board, depth - 1, alpha, beta, true);
board[i][j] = EMPTY;
minScore = Math.min(minScore, score);
beta = Math.min(beta, score);
if (beta <= alpha) {
break;
}
}
}
}
return minScore;
}
}
代码解析:
- 简单难度:随机选择空位置下棋,适合初学者
- 中等难度:优先检查自己是否有获胜机会,其次检查玩家是否有获胜机会进行防守
- 困难难度:使用Minimax算法,考虑未来几步的走法,通过评分系统评估棋盘状态
- Alpha-Beta剪枝:优化Minimax算法,减少计算量
4. 棋盘评估函数
// 评估棋盘
function evaluateBoard(board) {
let score = 0;
// 评估电脑的棋型
for (let i = 0; i < BOARD_SIZE; i++) {
for (let j = 0; j < BOARD_SIZE; j++) {
if (board[i][j] === AI) {
score += evaluatePosition(i, j, AI);
} else if (board[i][j] === PLAYER) {
score -= evaluatePosition(i, j, PLAYER);
}
}
}
return score;
}
// 评估位置
function evaluatePosition(x, y, player) {
let score = 0;
const directions = [
[1, 0], // 水平
[0, 1], // 垂直
[1, 1], // 对角线
[1, -1] // 反对角线
];
for (let [dx, dy] of directions) {
let count = 1;
let empty = 0;
// 正向
let i = x + dx;
let j = y + dy;
while (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && board[i][j] === player) {
count++;
i += dx;
j += dy;
}
if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && board[i][j] === EMPTY) {
empty++;
}
// 反向
i = x - dx;
j = y - dy;
while (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && board[i][j] === player) {
count++;
i -= dx;
j -= dy;
}
if (i >= 0 && i < BOARD_SIZE && j >= 0 && j < BOARD_SIZE && board[i][j] === EMPTY) {
empty++;
}
// 根据连续棋子数和空位评估
if (count === 5) {
score += 1000;
} else if (count === 4 && empty >= 1) {
score += 100;
} else if (count === 3 && empty >= 2) {
score += 10;
} else if (count === 2 && empty >= 2) {
score += 1;
}
}
return score;
}
代码解析:
- 评估每个位置的棋型价值
- 考虑四个方向的连续棋子数
- 考虑棋子两端的空位情况
- 根据不同的棋型给予不同的分数
- 五连珠:1000分
- 活四(两端有空位):100分
- 活三(两端有空位):10分
- 活二(两端有空位):1分
开发过程中的挑战与解决方案
1. Canvas绘制性能优化
挑战:频繁重绘棋盘可能导致性能问题
解决方案:
- 只在必要时重绘棋盘
- 使用requestAnimationFrame优化动画效果
- 避免不必要的计算和绘制操作
2. AI算法效率
挑战:Minimax算法在大棋盘上计算量巨大
解决方案:
- 使用Alpha-Beta剪枝减少搜索空间
- 限制搜索深度(设置为3层)
- 优化评估函数,减少计算复杂度
3. 游戏状态管理
挑战:确保游戏状态的一致性和正确性
解决方案:
- 使用清晰的状态变量管理游戏状态
- 实现完整的游戏流程控制
- 添加适当的错误处理
4. 用户界面设计
挑战:创建美观且用户友好的界面
解决方案:
- 使用现代化的CSS设计
- 实现响应式布局
- 添加适当的视觉反馈
项目结构
electron-openharmony-vue3/
├── ohos_hap/
│ └── web_engine/
│ └── src/
│ └── main/
│ └── resources/
│ └── resfile/
│ └── resources/
│ └── app/
│ ├── index.html # 五子棋游戏主页面
│ ├── main.js # Electron主进程
│ └── preload.js # 预加载脚本
└── docs/
└── GOMOKU_GAME_BLOG.md # 项目博客
未来改进方向
- 多人对战:添加网络对战功能,支持玩家之间在线对战
- 游戏记录:实现游戏回放和历史记录功能
- 自定义棋盘:允许用户自定义棋盘大小和规则
- 音效系统:添加游戏音效,增强游戏体验
- 皮肤系统:允许用户选择不同的棋盘和棋子皮肤
- 难度调整:提供更精细的难度调整选项
- 移动端适配:优化移动端触摸操作体验
- AI训练:使用机器学习技术提升AI水平
总结
通过本项目,我们成功开发了一款功能完整、界面美观的PC版五子棋游戏。游戏采用Electron和HTML5 Canvas技术栈,实现了以下核心功能:
- 15x15标准棋盘
- 三种难度等级(简单、中等、困难)
- 玩家与电脑对战
- 自动胜负判断
- 美观的用户界面
项目中使用的技术和算法包括:
- Canvas绘制技术
- 游戏状态管理
- 胜负判断算法
- 不同难度的AI实现(随机算法、攻击-防守算法、Minimax算法)
- Alpha-Beta剪枝优化
- 棋盘评估系统
这款五子棋游戏不仅提供了娱乐功能,也是学习Electron和Canvas开发的良好示例。通过不断改进和扩展,可以进一步提升游戏的功能和用户体验。
如何运行
- 克隆项目到本地
- 进入项目目录
- 运行Electron应用
- 选择难度等级
- 点击"开始游戏"按钮开始游戏
- 点击棋盘上的位置进行下棋
- 游戏结束后,点击"确定"关闭结果模态框
- 点击"重新开始"按钮可以重新开始游戏
技术栈总结
| 技术 | 用途 | 版本 |
|---|---|---|
| Electron | 桌面应用框架 | 最新版 |
| HTML5 Canvas | 绘制棋盘和棋子 | HTML5 |
| JavaScript | 游戏逻辑和AI算法 | ES6+ |
| CSS | 界面设计 | CSS3 |
通过本项目的开发,我们展示了如何使用现代Web技术构建一个功能完整的桌面游戏应用,希望对开发者有所启发和帮助。
更多推荐
所有评论(0)