下面是一个基于鸿蒙OS (HarmonyOS) 的五子棋小游戏的实现代码。这个实现使用Java语言和鸿蒙的Ability框架。
1. 创建项目结构
首先创建一个鸿蒙应用项目,结构如下:
/src/main/java/com/example/gobang/
├── MainAbilitySlice.java // 主界面逻辑
├── GameView.java // 游戏视图和逻辑
└── resources/
├── base/
│ ├── layout/
│ │ └── ability_main.xml // 布局文件
│ └── graphic/
│ └── board_bg.xml // 棋盘背景
2. 实现代码
GameView.java (游戏核心逻辑)
package com.example.gobang;
import ohos.agp.components.Component;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.agp.utils.Color;
import ohos.agp.utils.RectFloat;
import ohos.app.Context;
public class GameView extends Component implements Component.DrawTask {
private static final int ROWS = 15; // 棋盘行数
private static final int COLS = 15; // 棋盘列数
private static final int WIN_COUNT = 5; // 胜利条件
private int[][] board; // 0-空 1-黑子 2-白子
private boolean isBlackTurn = true; // 黑棋先行
private boolean gameOver = false;
private OnGameOverListener listener;
private Paint linePaint;
private Paint blackPaint;
private Paint whitePaint;
private Paint lastMovePaint;
private int lastMoveX = -1;
private int lastMoveY = -1;
public GameView(Context context) {
super(context);
init();
}
private void init() {
board = new int[ROWS][COLS];
linePaint = new Paint();
linePaint.setColor(new Color(0xFF000000));
linePaint.setStrokeWidth(2);
blackPaint = new Paint();
blackPaint.setColor(new Color(0xFF000000));
blackPaint.setStyle(Paint.Style.FILL_STYLE);
whitePaint = new Paint();
whitePaint.setColor(new Color(0xFFFFFFFF));
whitePaint.setStyle(Paint.Style.FILL_STYLE);
lastMovePaint = new Paint();
lastMovePaint.setColor(new Color(0xFFFF0000));
lastMovePaint.setStrokeWidth(3);
addDrawTask(this);
setClickedListener((component) -> handleClick());
}
@Override
public void onDraw(Component component, Canvas canvas) {
int width = getWidth();
int height = getHeight();
float cellSize = Math.min(width, height) / (float) Math.max(ROWS, COLS);
// 绘制棋盘
for (int i = 0; i < ROWS; i++) {
float y = i * cellSize + cellSize / 2;
canvas.drawLine(0, y, width, y, linePaint);
}
for (int j = 0; j < COLS; j++) {
float x = j * cellSize + cellSize / 2;
canvas.drawLine(x, 0, x, height, linePaint);
}
// 绘制棋子
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (board[i][j] == 1) {
drawPiece(canvas, i, j, cellSize, blackPaint);
} else if (board[i][j] == 2) {
drawPiece(canvas, i, j, cellSize, whitePaint);
}
}
}
// 标记最后一步
if (lastMoveX != -1 && lastMoveY != -1) {
float centerX = lastMoveY * cellSize + cellSize / 2;
float centerY = lastMoveX * cellSize + cellSize / 2;
float radius = cellSize / 4;
canvas.drawCircle(centerX, centerY, radius, lastMovePaint);
}
}
private void drawPiece(Canvas canvas, int row, int col, float cellSize, Paint paint) {
float centerX = col * cellSize + cellSize / 2;
float centerY = row * cellSize + cellSize / 2;
float radius = cellSize / 2 - 5;
canvas.drawCircle(centerX, centerY, radius, paint);
}
private void handleClick() {
if (gameOver) return;
int width = getWidth();
int height = getHeight();
float cellSize = Math.min(width, height) / (float) Math.max(ROWS, COLS);
// 获取点击位置
float x = getTouchPoint().getX();
float y = getTouchPoint().getY();
int row = Math.round((y - cellSize / 2) / cellSize);
int col = Math.round((x - cellSize / 2) / cellSize);
if (row >= 0 && row < ROWS && col >= 0 && col < COLS && board[row][col] == 0) {
board[row][col] = isBlackTurn ? 1 : 2;
lastMoveX = row;
lastMoveY = col;
if (checkWin(row, col)) {
gameOver = true;
if (listener != null) {
listener.onGameOver(isBlackTurn ? "黑棋胜利!" : "白棋胜利!");
}
} else if (isBoardFull()) {
gameOver = true;
if (listener != null) {
listener.onGameOver("平局!");
}
} else {
isBlackTurn = !isBlackTurn;
}
invalidate();
}
}
private boolean checkWin(int row, int col) {
int player = board[row][col];
return checkDirection(row, col, 1, 0, player) || // 水平
checkDirection(row, col, 0, 1, player) || // 垂直
checkDirection(row, col, 1, 1, player) || // 对角线
checkDirection(row, col, 1, -1, player); // 反对角线
}
private boolean checkDirection(int row, int col, int dx, int dy, int player) {
int count = 1;
// 正向检查
for (int i = 1; i < WIN_COUNT; i++) {
int r = row + i * dx;
int c = col + i * dy;
if (r < 0 || r >= ROWS || c < 0 || c >= COLS || board[r][c] != player) {
break;
}
count++;
}
// 反向检查
for (int i = 1; i < WIN_COUNT; i++) {
int r = row - i * dx;
int c = col - i * dy;
if (r < 0 || r >= ROWS || c < 0 || c >= COLS || board[r][c] != player) {
break;
}
count++;
}
return count >= WIN_COUNT;
}
private boolean isBoardFull() {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
if (board[i][j] == 0) {
return false;
}
}
}
return true;
}
public void reset() {
for (int i = 0; i < ROWS; i++) {
for (int j = 0; j < COLS; j++) {
board[i][j] = 0;
}
}
isBlackTurn = true;
gameOver = false;
lastMoveX = -1;
lastMoveY = -1;
invalidate();
}
public void setOnGameOverListener(OnGameOverListener listener) {
this.listener = listener;
}
public interface OnGameOverListener {
void onGameOver(String message);
}
}
MainAbilitySlice.java (主界面)
package com.example.gobang;
import ohos.aafwk.ability.AbilitySlice;
import ohos.aafwk.content.Intent;
import ohos.agp.components.Button;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Text;
import ohos.agp.window.dialog.ToastDialog;
public class MainAbilitySlice extends AbilitySlice {
@Override
public void onStart(Intent intent) {
super.onStart(intent);
DirectionalLayout layout = new DirectionalLayout(this);
layout.setOrientation(DirectionalLayout.VERTICAL);
// 状态文本
Text statusText = new Text(this);
statusText.setText("当前回合: 黑棋");
statusText.setTextSize(50);
statusText.setPadding(10, 10, 10, 10);
// 游戏视图
GameView gameView = new GameView(this);
gameView.setOnGameOverListener(message -> {
new ToastDialog(this)
.setText(message)
.show();
statusText.setText("游戏结束 - " + message);
});
// 重置按钮
Button resetButton = new Button(this);
resetButton.setText("重新开始");
resetButton.setPadding(10, 10, 10, 10);
resetButton.setClickedListener(component -> {
gameView.reset();
statusText.setText("当前回合: 黑棋");
});
// 添加组件到布局
layout.addComponent(statusText);
layout.addComponent(gameView);
layout.addComponent(resetButton);
super.setUIContent(layout);
}
}
ability_main.xml (布局文件)
<?xml version="1.0" encoding="utf-8"?>
<DirectionalLayout
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent"
ohos:orientation="vertical">
<Text
ohos:id="$+id:status_text"
ohos:width="match_parent"
ohos:height="50vp"
ohos:text="当前回合: 黑棋"
ohos:text_size="20fp"
ohos:padding="10vp"/>
<com.example.gobang.GameView
ohos:id="$+id:game_view"
ohos:width="match_parent"
ohos:height="0vp"
ohos:weight="1"/>
<Button
ohos:id="$+id:reset_button"
ohos:width="match_parent"
ohos:height="50vp"
ohos:text="重新开始"
ohos:margin="10vp"/>
</DirectionalLayout>
3. 功能说明
- 游戏规则:标准五子棋规则,先连成五子的一方获胜
- 界面元素 :
- 棋盘:15×15网格
- 棋子:黑色和白色圆形
- 状态显示:当前回合信息
- 重置按钮:重新开始游戏
- 交互 :
- 点击棋盘落子
- 自动判断胜负
- 显示最后一步落子位置