package com.example.chess;
import ohos.aafwk.ability.Ability;
import ohos.aafwk.content.Intent;
import ohos.agp.colors.RgbColor;
import ohos.agp.components.Component;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.TableLayout;
import ohos.agp.components.element.ShapeElement;
import ohos.agp.utils.Color;
import ohos.agp.components.Component.DrawTask;
import ohos.agp.render.Canvas;
import ohos.agp.render.Paint;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;
import java.util.ArrayList;
import java.util.List;
public class ChessAbility extends Ability {
private static final int BOARD_SIZE = 9; // 9x10棋盘
private static final int GRID_SIZE = 60; // 网格大小
private ChessPiece[][] board = new ChessPiece[10][9]; // 10行9列
private ChessPiece selectedPiece = null;
@Override
public void onStart(Intent intent) {
super.onStart(intent);
DirectionalLayout layout = new DirectionalLayout(this);
ChessBoard boardView = new ChessBoard(this);
layout.addComponent(boardView);
super.setUIContent(layout);
initBoard(); // 初始化棋盘
// 初始化棋子位置
private void initBoard() {
// 红方棋子
board[0][0] = new ChessPiece(ChessPiece.ROOK, ChessPiece.RED, 0, 0);
board[0][1] = new ChessPiece(ChessPiece.HORSE, ChessPiece.RED, 0, 1);
board[0][2] = new ChessPiece(ChessPiece.ELEPHANT, ChessPiece.RED, 0, 2);
board[0][3] = new ChessPiece(ChessPiece.GUARD, ChessPiece.RED, 0, 3);
board[0][4] = new ChessPiece(ChessPiece.KING, ChessPiece.RED, 0, 4);
board[0][5] = new ChessPiece(ChessPiece.GUARD, ChessPiece.RED, 0, 5);
board[0][6] = new ChessPiece(ChessPiece.ELEPHANT, ChessPiece.RED, 0, 6);
board[0][7] = new ChessPiece(ChessPiece.HORSE, ChessPiece.RED, 0, 7);
board[0][8] = new ChessPiece(ChessPiece.ROOK, ChessPiece.RED, 0, 8);
board[2][1] = new ChessPiece(ChessPiece.CANNON, ChessPiece.RED, 2, 1);
board[2][7] = new ChessPiece(ChessPiece.CANNON, ChessPiece.RED, 2, 7);
board[3][0] = new ChessPiece(ChessPiece.PAWN, ChessPiece.RED, 3, 0);
// ... 其他棋子初始化类似
// 黑方棋子
board[9][0] = new ChessPiece(ChessPiece.ROOK, ChessPiece.BLACK, 9, 0);
// ... 其他棋子初始化
// 棋子类
static class ChessPiece {
public static final int KING = 0;
public static final int GUARD = 1;
public static final int ELEPHANT = 2;
public static final int HORSE = 3;
public static final int ROOK = 4;
public static final int CANNON = 5;
public static final int PAWN = 6;
public static final int RED = 0;
public static final int BLACK = 1;
int type;
int color;
int row;
int col;
public ChessPiece(int type, int color, int row, int col) {
this.type = type;
this.color = color;
this.row = row;
this.col = col;
// 检查移动是否合法(简化版)
public boolean isValidMove(int newRow, int newCol, ChessPiece[][] board) {
// 实现具体棋子移动规则
return true;
}
// 棋盘视图
class ChessBoard extends Component {
private Paint boardPaint;
private Paint highlightPaint;
public ChessBoard(Context context) {
super(context);
initPaints();
setClickedListener(this::onBoardClick);
private void initPaints() {
boardPaint = new Paint();
boardPaint.setColor(new Color(0, 0, 0));
boardPaint.setStrokeWidth(2);
highlightPaint = new Paint();
highlightPaint.setColor(new Color(255, 255, 0, 100));
@Override
public void onDraw(Component component, Canvas canvas) {
super.onDraw(component, canvas);
drawBoard(canvas);
drawPieces(canvas);
drawHighlights(canvas);
// 绘制棋盘网格
private void drawBoard(Canvas canvas) {
for (int i = 0; i <= BOARD_SIZE; i++) {
// 画横线
canvas.drawLine(0, i GRID_SIZE, BOARD_SIZE GRID_SIZE, i * GRID_SIZE, boardPaint);
// 画竖线(前5列)
canvas.drawLine(i GRID_SIZE, 0, i GRID_SIZE, 4 * GRID_SIZE, boardPaint);
// 画竖线(后5列)
canvas.drawLine(i GRID_SIZE, 5 GRID_SIZE, i GRID_SIZE, 9 GRID_SIZE, boardPaint);
// 画楚河汉界
canvas.drawText("楚河 汉界", BOARD_SIZE/2 GRID_SIZE - 80, 4.5f GRID_SIZE, boardPaint);
// 绘制棋子
private void drawPieces(Canvas canvas) {
for (int r = 0; r < 10; r++) {
for (int c = 0; c < 9; c++) {
ChessPiece piece = board[r][c];
if (piece != null) {
int x = c * GRID_SIZE + GRID_SIZE/2;
int y = r * GRID_SIZE + GRID_SIZE/2;
// 绘制棋子背景
Paint piecePaint = new Paint();
piecePaint.setColor(piece.color == ChessPiece.RED ?
Color.RED : Color.BLACK);
canvas.drawCircle(x, y, GRID_SIZE/2 - 5, piecePaint);
// 绘制棋子文字
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(30);
canvas.drawText(getPieceName(piece.type), x - 15, y + 10, textPaint);
}
}
// 获取棋子名称
private String getPieceName(int type) {
switch(type) {
case ChessPiece.KING: return "将";
case ChessPiece.ROOK: return "车";
case ChessPiece.HORSE: return "马";
case ChessPiece.CANNON: return "炮";
case ChessPiece.GUARD: return "士";
case ChessPiece.ELEPHANT: return "象";
case ChessPiece.PAWN: return "兵";
default: return "";
}
// 绘制选中高亮
private void drawHighlights(Canvas canvas) {
if (selectedPiece != null) {
int x = selectedPiece.col * GRID_SIZE;
int y = selectedPiece.row * GRID_SIZE;
canvas.drawRect(x, y, x + GRID_SIZE, y + GRID_SIZE, highlightPaint);
}
// 棋盘点击处理
private boolean onBoardClick(Component component, TouchEvent event) {
if (event.getAction() != TouchEvent.PRIMARY_POINT_DOWN) {
return false;
int col = (int)(event.getPointerPosition(0).getX() / GRID_SIZE);
int row = (int)(event.getPointerPosition(0).getY() / GRID_SIZE);
// 边界检查
if (row < 0 |row >= 10
col < 0
| col >= 9) return true;
ChessPiece clickedPiece = board[row][col];
if (selectedPiece == null) {
// 选择棋子
if (clickedPiece != null) {
selectedPiece = clickedPiece;
invalidate();
} else {
// 移动棋子
if (selectedPiece.isValidMove(row, col, board)) {
board[selectedPiece.row][selectedPiece.col] = null;
selectedPiece.row = row;
selectedPiece.col = col;
board[row][col] = selectedPiece;
selectedPiece = null;
invalidate();
return true;
}
代码解析:
整体结构
ChessAbility:主Ability,负责初始化界面和棋盘
ChessPiece:棋子数据类,存储棋子类型、颜色和位置
ChessBoard:自定义棋盘组件,处理绘制和交互
核心功能实现
棋盘绘制:使用Canvas绘制9×10的网格和"楚河汉界"
棋子表示:用类封装棋子类型(将/车/马/炮等)和颜色(红/黑)
交互逻辑:
点击棋子时高亮选中
再次点击合法位置时移动棋子
移动验证:isValidMove()方法预留了棋子规则实现接口
鸿蒙特性实现
使用Component的自定义绘制能力(onDraw方法)
通过setClickedListener处理触摸事件
使用Canvas进行2D图形绘制
颜色管理使用Color和Paint类
棋子移动规则要点(需在isValidMove中完善):
将/帅:只能在九宫内直线移动一步
士/仕:九宫内斜线移动一步
象/相:田字移动,不能过河
车:直线任意距离移动
马:日字移动,需考虑蹩马腿
炮:直线移动,吃子需隔一子
兵/卒:只能向前,过河后可左右移动
扩展建议:
游戏状态管理
添加游戏状态(等待/结束)
实现胜负判定逻辑
添加计时功能
视觉优化
使用图片替代文字表示棋子
添加棋子移动动画
实现吃子特效
多人对战
添加蓝牙对战功能
实现网络对战模块
添加AI对战功能
音效与震动
添加棋子移动音效
实现胜负提示音
关键操作添加震动反馈
鸿蒙开发注意事项:
图形绘制使用ohos.agp.render.Canvas类
事件处理使用ohos.multimodalinput.event包
布局推荐使用DirectionalLayout或TableLayout
资源管理使用ResourceTable访问资源文件