当前位置: 首页 > news >正文

鸿蒙开发案例:绘制中国象棋棋盘与棋子的技术教程

本文将介绍如何使用鸿蒙提供的UI组件来绘制一个中国象棋棋盘并放置棋子。通过本教程,您将学会基本的UI构建技巧,以及如何在鸿蒙环境中创建一个简单的象棋游戏界面。

一、定义棋盘线条与棋子位置

首先,我们需要定义几个基础类来帮助我们构造棋盘。ChessLine类用于表示棋盘上的线段,而MyPosition类则用来记录棋盘上每个位置是否需要特殊的标记(如“兵”、“卒”、“炮”的位置)。

class ChessLine {startPoint: [number, number] = [0, 0];endPoint: [number, number] = [0, 0];
}class MyPosition {x: number = 0;y: number = 0;topLeft: boolean = true;topRight: boolean = true;bottomLeft: boolean = true;bottomRight: boolean = true;constructor(x: number, y: number, topLeft: boolean, topRight: boolean, bottomLeft: boolean, bottomRight: boolean) {this.x = x;this.y = y;this.topLeft = topLeft;this.topRight = topRight;this.bottomLeft = bottomLeft;this.bottomRight = bottomRight;}
}

二、创建棋子类

接下来,我们定义ChessPiece类来代表棋盘上的每一个棋子。这个类包括棋子的颜色、类型等属性,并且有一个方法getColor()来获取棋子的颜色值。

@ObservedV2
class ChessPiece {@Trace opacity: number = 1;@Trace value: string = "";@Trace type: number = 0; // 0: 无棋, 1: 红棋,2: 黑棋redColor: string = `rgb(144,11,11)`;blackColor: string = `rgb(78,56,23)`;constructor(value: string, type: number) {this.value = value;this.type = type;}setValue(value: string, type: number) {this.value = value;this.type = type;}getColor() {if (this.type === 1) {return this.redColor;} else if (this.type === 2) {return this.blackColor;}return "#00000000";}
}

三、构建棋盘

使用ChessBoard类来构建整个棋盘,其中包括棋盘的基本尺寸、棋子数组、棋盘线段数组等。在这个类中,我们还定义了初始化游戏的方法initGame(),它会根据规则在棋盘上放置棋子。

@Entry
@Component
struct ChessBoard {cellWidth: number = 70;borderPieceWidth: number = 12;pieceSize: number = 66;pieces: ChessPiece[] = [];lines: ChessLine[] = [];positions: MyPosition[] = [];selectedIndex: number = -1; // -1表示未点击任何棋子,非-1表示当前正在点击的棋子aboutToAppear(): void {for (let i = 0; i < 9 * 10; i++) {this.pieces.push(new ChessPiece("", 0));}this.initGame();// 初始化水平线和垂直线...}initGame() {// 设置棋子初始位置...}build() {Column({ space: 10 }) {// 构建棋盘框架和线条...}}
}

四、绘制棋子

最后,我们需要在棋盘上绘制棋子。这里使用了Flex和ForEach等组件来遍历棋子数组,并根据棋子的类型绘制不同的样式。

Flex({ wrap: FlexWrap.Wrap }) {ForEach(this.pieces, (piece: ChessPiece, index: number) => {Stack() {Text(piece.value)// 设置棋子文本样式...}.opacity(piece.opacity).width(`${this.cellWidth}lpx`).height(`${this.cellWidth}lpx`).onClick(() => {// 处理点击事件...})})
}

【完整代码】

class ChessLine {startPoint: [number, number] = [0, 0];endPoint: [number, number] = [0, 0];
}class MyPosition {x: number = 0;y: number = 0;topLeft: boolean = true;topRight: boolean = true;bottomLeft: boolean = true;bottomRight: boolean = true;constructor(x: number, y: number, topLeft: boolean, topRight: boolean, bottomLeft: boolean, bottomRight: boolean) {this.x = x;this.y = y;this.topLeft = topLeft;this.topRight = topRight;this.bottomLeft = bottomLeft;this.bottomRight = bottomRight;}
}@ObservedV2
class ChessPiece {@Trace opacity: number = 1;@Trace value: string = "";@Trace type: number = 0; // 0: 无棋, 1: 红棋,2: 黑棋redColor: string = `rgb(144,11,11)`;blackColor: string = `rgb(78,56,23)`;constructor(value: string, type: number) {this.value = value;this.type = type;}setValue(value: string, type: number) {this.value = value;this.type = type;}getColor() {if (this.type === 1) {return this.redColor;} else if (this.type === 2) {return this.blackColor;}return "#00000000";}
}@Entry
@Component
struct ChessBoard {cellWidth: number = 70;borderPieceWidth: number = 12;pieceSize: number = 66;pieces: ChessPiece[] = [];lines: ChessLine[] = [];positions: MyPosition[] = [];selectedIndex: number = -1; // -1表示未点击任何棋子,非-1表示当前正在点击的棋子aboutToAppear(): void {for (let i = 0; i < 9 * 10; i++) {this.pieces.push(new ChessPiece("", 0));}this.initGame();// 初始化水平线和垂直线for (let i = 0; i < 10; i++) {this.lines.push({startPoint: [0, this.cellWidth * i],endPoint: [this.cellWidth * 8, this.cellWidth * i]});this.lines.push({startPoint: [this.cellWidth * i, 0],endPoint: [this.cellWidth * i, this.cellWidth * (i === 0 || i === 8 ? 9 : 4)]});this.lines.push({startPoint: [this.cellWidth * i, this.cellWidth * 5],endPoint: [this.cellWidth * i, this.cellWidth * 9]});}// 初始化九宫格内的斜线this.lines.push({startPoint: [3 * this.cellWidth, 0],endPoint: [5 * this.cellWidth, 2 * this.cellWidth],});this.lines.push({startPoint: [5 * this.cellWidth, 0],endPoint: [3 * this.cellWidth, 2 * this.cellWidth],});this.lines.push({startPoint: [3 * this.cellWidth, 7 * this.cellWidth],endPoint: [5 * this.cellWidth, 9 * this.cellWidth],});this.lines.push({startPoint: [5 * this.cellWidth, 7 * this.cellWidth],endPoint: [3 * this.cellWidth, 9 * this.cellWidth],});// 兵卒炮位置标this.positions.push(new MyPosition(1, 2, true, true, true, true))this.positions.push(new MyPosition(7, 2, true, true, true, true))this.positions.push(new MyPosition(0, 3, false, true, false, true))this.positions.push(new MyPosition(2, 3, true, true, true, true))this.positions.push(new MyPosition(4, 3, true, true, true, true))this.positions.push(new MyPosition(6, 3, true, true, true, true))this.positions.push(new MyPosition(8, 3, true, false, true, false))this.positions.push(new MyPosition(1, 7, true, true, true, true))this.positions.push(new MyPosition(7, 7, true, true, true, true))this.positions.push(new MyPosition(0, 6, false, true, false, true))this.positions.push(new MyPosition(2, 6, true, true, true, true))this.positions.push(new MyPosition(4, 6, true, true, true, true))this.positions.push(new MyPosition(6, 6, true, true, true, true))this.positions.push(new MyPosition(8, 6, true, false, true, false))}initGame() {for (let i = 0; i < 9 * 10; i++) {this.pieces[i].setValue("", 0);}this.pieces[0].setValue("车", 2)this.pieces[1].setValue("马", 2)this.pieces[2].setValue("象", 2)this.pieces[3].setValue("士", 2)this.pieces[4].setValue("将", 2)this.pieces[5].setValue("士", 2)this.pieces[6].setValue("象", 2)this.pieces[7].setValue("马", 2)this.pieces[8].setValue("车", 2)this.pieces[19].setValue("炮", 2)this.pieces[25].setValue("炮", 2)this.pieces[27].setValue("卒", 2)this.pieces[29].setValue("卒", 2)this.pieces[31].setValue("卒", 2)this.pieces[33].setValue("卒", 2)this.pieces[35].setValue("卒", 2)this.pieces[54].setValue("兵", 1)this.pieces[56].setValue("兵", 1)this.pieces[58].setValue("兵", 1)this.pieces[60].setValue("兵", 1)this.pieces[62].setValue("兵", 1)this.pieces[64].setValue("炮", 1)this.pieces[70].setValue("炮", 1)this.pieces[81].setValue("车", 1)this.pieces[82].setValue("马", 1)this.pieces[83].setValue("相", 1)this.pieces[84].setValue("仕", 1)this.pieces[85].setValue("帅", 1)this.pieces[86].setValue("仕", 1)this.pieces[87].setValue("相", 1)this.pieces[88].setValue("马", 1)this.pieces[89].setValue("车", 1)}build() {Column({ space: 10 }) {Column() {Stack() {// 棋盘矩形边框Rect().margin({top: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`,left: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`}).width(`${this.cellWidth * 8 + this.borderPieceWidth}lpx`).height(`${this.cellWidth * 9 + this.borderPieceWidth}lpx`).fillOpacity(0).stroke(Color.Black).strokeWidth(`${this.borderPieceWidth / 3}lpx`);// 绘制线条ForEach(this.lines, (line: ChessLine, _index: number) => {Line().margin({ left: `${this.cellWidth / 2}lpx`, top: `${this.cellWidth / 2}lpx` }).startPoint([`${line.startPoint[0]}lpx`, `${line.startPoint[1]}lpx`]).endPoint([`${line.endPoint[0]}lpx`, `${line.endPoint[1]}lpx`]).stroke(Color.Black);});// 添加"兵卒炮"标记ForEach(this.positions, (position: MyPosition, _index: number) => {if (position.topLeft) {Polyline().margin({left: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`,top: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`}).points([[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y - this.borderPieceWidth}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x - this.borderPieceWidth}lpx`, `${this.cellWidth * position.y}lpx`],]).width(1).height(1).fillOpacity(0).stroke(Color.Black);}if (position.topRight) {Polyline().margin({left: `${this.cellWidth / 2 + this.borderPieceWidth / 2}lpx`,top: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`}).points([[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y - this.borderPieceWidth}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x + this.borderPieceWidth}lpx`, `${this.cellWidth * position.y}lpx`],]).width(1).height(1).fillOpacity(0).stroke(Color.Black)}if (position.bottomLeft) {Polyline().margin({left: `${this.cellWidth / 2 - this.borderPieceWidth / 2}lpx`,top: `${this.cellWidth / 2 + this.borderPieceWidth / 2}lpx`}).points([[`${this.cellWidth * position.x - this.borderPieceWidth}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y + this.borderPieceWidth}lpx`],]).width(1).height(1).fillOpacity(0).stroke(Color.Black)}if (position.bottomRight) {Polyline().margin({left: `${this.cellWidth / 2 + this.borderPieceWidth / 2}lpx`,top: `${this.cellWidth / 2 + this.borderPieceWidth / 2}lpx`}).points([[`${this.cellWidth * position.x + this.borderPieceWidth}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y}lpx`],[`${this.cellWidth * position.x}lpx`, `${this.cellWidth * position.y + this.borderPieceWidth}lpx`],]).width(1).height(1).fillOpacity(0).stroke(Color.Black)}});// 绘制棋子Flex({ wrap: FlexWrap.Wrap }) {ForEach(this.pieces, (piece: ChessPiece, index: number) => {Stack() {Text(piece.value).width(`${this.pieceSize}lpx`).height(`${this.pieceSize}lpx`).backgroundColor(piece.type !== 0 ? `rgb(192,149,106)` : Color.Transparent).textAlign(TextAlign.Center).fontSize(`${this.pieceSize / 2}lpx`).fontColor(piece.getColor()).borderColor(piece.getColor()).borderRadius(`50%`).borderWidth(`2lpx`).textShadow({radius: 2,color: Color.White,offsetX: 2,offsetY: 2});Circle().width(`${this.pieceSize - 15}lpx`).height(`${this.pieceSize - 15}lpx`).fillOpacity(0).strokeWidth(2).stroke(piece.getColor()).strokeDashArray([0.2, 1]);}.opacity(piece.opacity).width(`${this.cellWidth}lpx`).height(`${this.cellWidth}lpx`).onClick(() => {if (this.selectedIndex === -1) {this.selectedIndex = index;animateToImmediately({iterations: 3,duration: 300,onFinish: () => {animateToImmediately({iterations: 1,duration: 0}, () => {piece.opacity = 1;});}}, () => {piece.opacity = 0.5;});} else {piece.value = this.pieces[this.selectedIndex].value;piece.type = this.pieces[this.selectedIndex].type;this.pieces[this.selectedIndex].value = '';this.pieces[this.selectedIndex].type = 0;this.selectedIndex = -1;}});});}.width('100%').height('100%');}.align(Alignment.TopStart).width(`${this.cellWidth * 9}lpx`).height(`${this.cellWidth * 10}lpx`);}.padding(10).backgroundColor(Color.Orange).borderRadius(10);Button('重新开始').onClick(() => {this.initGame();});}.width('100%');}
}


http://www.mrgr.cn/news/52052.html

相关文章:

  • Java 枚举类
  • 自定义类型——结构体
  • c#编写的各类应用程序
  • 65.DDR3读写控制器的设计与验证(2)
  • 60. 排列序列
  • Windows11桌面快捷方式图标变为白色方块-如何解决
  • C++11 使用 {} 进行初始化
  • 【微信小程序_18_WXS脚本】
  • TemporalBench:一个专注于细粒度时间理解的多模态视频理解的新基准。
  • 从实习到春招成为一名安全工程师,我经历了什么
  • mqtt与云服务器
  • 2024了,传统行业转行AI,可不可行?
  • Java 虚拟机(JVM)中的内存泄漏排查技巧及各种内存查看命令分析工具推荐
  • C语言中点操作符(.)和箭头操作符(->)的区别
  • 汽车免拆诊断案例 | 2023款零跑C01纯电车后备厢盖无法电动打开和关闭
  • 对“一个中心,三重防护”中安全管理中心的理解
  • 数据结构深度优先搜索遍历连通图+非连通图(C语言代码+遍历+终端输入内容)
  • 超详细的B/S和C/S架构对比
  • 【PT-RS】
  • SIEMENS罗宾康LDZ14501001.140功率单元适合哪些场合使用?