鸿蒙ArkTS+ArkUI实现五子棋游戏
前言
近期,鸿蒙系统热度飙升,引发了周围众多朋友的热烈探讨。出于这份浓厚的好奇心,我初步浏览了其官方文档,发现信息量庞大,全面消化需耗时良久并考验人的毅力。自踏入编程领域以来,我一直秉持着"实践出真知"的原则,倾向于在动手操作中领悟文字背后的深意。恰逢我之前已利用Java和Python成功开发过五子棋游戏,一个念头油然而生:何不借助鸿蒙系统,再次挑战这一经典游戏的项目实践呢?正是这份灵感与决心,催生了本篇文章的诞生。
让我们一同利用鸿蒙系统,将五子棋游戏从Java和Python的实践迁移到鸿蒙平台,通过亲身实践深入理解鸿蒙的开发魅力。这不仅是一次技术尝试,更是一场充满乐趣与成长的学习之旅。
效果图
技术栈
- 版本:HarmonyOS 5.0.3(15)
- 编程语言:ArkTS
- UI框架:ArkUI
源码
这里只展示pages文件下的代码,如要获取整个项目,可以访问我的GitHub仓库,不知道仓库地址的朋友可以私聊我获取。
Index.ets ------ 开始界面
ts
import { font, router } from '@kit.ArkUI';
@Entry
@Component
struct Index {
// 注册字体
aboutToAppear() {
font.registerFont({
familyName: $r('app.string.index_title_font_name'),
familySrc: $r('app.string.index_title_font_src'),
})
}
build() {
Column() {
Row() {
Text($r("app.string.index_title"))
.fontSize($r('app.float.title_text_font_size'))
.fontWeight(FontWeight.Bold)
.fontFamily('SThuawenxingkai')
}
Row() {
Button() {
Text($r("app.string.start_button_text"))
.fontSize(20)
.fontWeight(FontWeight.Bold)
.fontColor('#000')
.fontFamily('SThuawenxingkai')
}
.onClick(() => {
router.pushUrl({ url: "pages/Second" })
})
.type(ButtonType.Capsule)
.startButtonStyle()
}
}
.height('100%')
.width('100%')
.justifyContent(FlexAlign.Center)
.backgroundImage($r("app.media.background_img"))
.backgroundImageSize(ImageSize.Cover)
}
@Styles
startButtonStyle() {
.margin({
top: 20
})
.backgroundColor($r('sys.color.button_background_color_transparent'))
.width('40%')
.height('6%')
.borderRadius(20)
.shadow({
radius: 10,
color: '#000',
offsetX: 0,
offsetY: 5
})
}
}
Second.ets ------ 游戏界面
ts
// 坐标类型
interface Coord {
x: number;
y: number;
color: boolean;
}
@Entry
@Component
struct Index {
private settings: RenderingContextSettings = new RenderingContextSettings(true)
private context: CanvasRenderingContext2D = new CanvasRenderingContext2D(this.settings)
// 棋盘起始坐标
board_x: number = 0
board_y: number = 0
// 棋盘宽度
board_width: number = 0
// 棋盘线的间距
line_spacing: number = 0
// true黑 false白
chess_color: boolean = true
// 棋子坐标
chess_coord: Coord[] = []
build() {
Flex({ direction: FlexDirection.Column, alignItems: ItemAlign.Center, justifyContent: FlexAlign.Center }) {
Canvas(this.context)
.width('100%')
.height('100%')
.backgroundColor($r("sys.color.ohos_id_color_background"))
.onReady(() => {
this.init()
})
.onClick((e) => {
this.drawChess(e.x, e.y)
})
.backgroundImage($r("app.media.background_img"))
.backgroundImageSize(ImageSize.Cover)
}
.width('100%')
.height('100%')
}
// 初始化棋盘方法
init() {
// 计算宽度,适配横屏
if (this.context.width < this.context.height) {
this.board_width = this.context.width - 40
} else {
this.board_width = this.context.height - 40
}
this.board_x = (this.context.width - this.board_width) / 2
this.board_y = (this.context.height - this.board_width) / 2
// 绘制正方形
this.context.lineWidth = 4
this.context.fillStyle = '#DBC26F'; // 设置填充颜色
this.context.strokeStyle = '#000'
this.context.fillRect(this.board_x, this.board_y, this.board_width, this.board_width); // 填充圆形
this.context.strokeRect(this.board_x, this.board_y, this.board_width, this.board_width)
// 计算棋盘线间距
this.line_spacing = this.board_width / 14
this.context.beginPath(); // 开始新路径
this.context.lineWidth = 2
for (let i = 0; i < 14; i++) {
this.context.moveTo(this.board_x, this.board_y + i * this.line_spacing)
this.context.lineTo(this.board_x + this.board_width, this.board_y + i * this.line_spacing)
}
for (let i = 0; i < 14; i++) {
this.context.moveTo(this.board_x + i * this.line_spacing, this.board_y)
this.context.lineTo(this.board_x + i * this.line_spacing, this.board_y + this.board_width)
}
this.context.stroke() // 绘制
// 绘制棋盘上的五个点
const points: Coord[] = [
{ x: 3, y: 3, color: true },
{ x: 11, y: 3, color: true },
{ x: 3, y: 11, color: true },
{ x: 11, y: 11, color: true },
{ x: 7, y: 7, color: true }
];
this.context.fillStyle = '#000'; // 设置填充颜色
this.context.lineWidth = 1; // 设置描边宽度
for (const point of points) {
this.context.beginPath(); // 新路径
const x = this.board_x + this.line_spacing * point.x;
const y = this.board_y + this.line_spacing * point.y;
this.context.arc(x, y, 4, 0, 2 * Math.PI); // 绘制圆形路径
this.context.fill(); // 填充圆形
}
}
// 绘制棋子
drawChess(x: number, y: number) {
// 判断点击区域是否在棋盘内
if (x >= this.board_x && x <= this.board_x + this.board_width && y >= this.board_y &&
y <= this.board_y + this.board_width) {
// 判断并设置棋子颜色
if (this.chess_color) {
this.context.fillStyle = '#000';
} else {
this.context.fillStyle = '#FFF';
}
// 修正坐标
x = Math.round((x - this.board_x) / this.line_spacing);
y = Math.round((y - this.board_y) / this.line_spacing);
// 判断是否已经有棋子
for (const coord of this.chess_coord) {
if (coord.x === x && coord.y === y) {
return
}
}
// 绘制棋子
this.context.strokeStyle = '#000'; // 设置描边颜色
this.context.beginPath(); // 新路径
this.context.arc(x * this.line_spacing + this.board_x, y * this.line_spacing + this.board_y,
this.line_spacing / 2 - 1, 0, 2 * Math.PI); // 绘制圆形路径
this.context.fill(); // 填充圆形
this.context.stroke(); // 描边圆形
// 加入棋子坐标
this.chess_coord.push({ x, y, color: this.chess_color })
// 判断是否五子连珠
this.checkLink()
// 切换棋子颜色
this.chess_color = !this.chess_color
}
}
// 判断是否五子连珠
checkLink() {
if (!this.chess_coord || this.chess_coord.length === 0) {
return;
}
const lastCoord = this.chess_coord[this.chess_coord.length - 1];
const directions: [number, number][] = [
[1, 0], // 垂直方向
[0, 1], // 水平方向
[1, 1], // 右对角线
[-1, 1]// 左对角线
];
for (const direction of directions) {
for (let method = 0; method < 5; method++) {
const linkingCoords: Coord[] = [];
for (let i = 0; i < 5; i++) {
const newCoord: Coord = {
x: lastCoord.x + direction[0] * (i - method),
y: lastCoord.y + direction[1] * (i - method),
color: lastCoord.color
};
const found = this.chess_coord.find(coord =>
coord.x === newCoord.x && coord.y === newCoord.y && coord.color === newCoord.color
);
if (found) {
linkingCoords.push(found)
}
}
if (linkingCoords.length >= 5) {
linkingCoords.forEach(item => {
console.log(item.x.toString(), item.y.toString(), item.color)
this.context.strokeStyle = '#FEFE00'; // 设置描边颜色
this.context.beginPath(); // 新路径
this.context.arc(item.x * this.line_spacing + this.board_x, item.y * this.line_spacing + this.board_y,
this.line_spacing / 2 - 1, 0, 2 * Math.PI); // 绘制圆形路径
this.context.stroke(); // 描边圆形
})
AlertDialog.show({
message: `恭喜${this.chess_color ? '黑棋' : '白棋'},你赢了!`,
cancel: () => {
// 初始化棋盘
this.chess_coord = []
this.chess_color = true
// 初始化棋盘
this.context.clearRect(0, 0, this.context.width, this.context.height);
this.init()
}
});
}
}
}
}
}
结束语
经过这一系列的探索与实践,我们不仅成功地将五子棋游戏实现到了鸿蒙系统之上,更在这一过程中深刻体会到了鸿蒙平台的强大功能与无限潜力。从初步接触鸿蒙的迷茫,到逐步熟悉并掌握其开发技巧,每一次挑战都见证了我们的成长与进步。如今,回顾这段旅程,我们收获的不仅仅是技术上的提升,更有对编程热爱的加深,以及对未来无限可能的憧憬。愿这份经历能够激励更多开发者,勇敢地在鸿蒙的世界里探索、实践、创新,共同书写属于我们的精彩篇章。
由于我也是初学者,目前实现的功能非常简单,如果后续有功能的更新,将实时更新到GitHub仓库。