鸿蒙ArkTS+ArkUI实现五子棋游戏

鸿蒙ArkTS+ArkUI实现五子棋游戏

前言

近期,鸿蒙系统热度飙升,引发了周围众多朋友的热烈探讨。出于这份浓厚的好奇心,我初步浏览了其官方文档,发现信息量庞大,全面消化需耗时良久并考验人的毅力。自踏入编程领域以来,我一直秉持着"实践出真知"的原则,倾向于在动手操作中领悟文字背后的深意。恰逢我之前已利用Java和Python成功开发过五子棋游戏,一个念头油然而生:何不借助鸿蒙系统,再次挑战这一经典游戏的项目实践呢?正是这份灵感与决心,催生了本篇文章的诞生。

让我们一同利用鸿蒙系统,将五子棋游戏从Java和Python的实践迁移到鸿蒙平台,通过亲身实践深入理解鸿蒙的开发魅力。这不仅是一次技术尝试,更是一场充满乐趣与成长的学习之旅。

效果图



技术栈

  1. 版本:HarmonyOS 5.0.3(15)
  2. 编程语言:ArkTS
  3. 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仓库。

相关推荐
Bruce_Liuxiaowei2 小时前
HarmonyOS Next~鸿蒙系统功耗优化体系解析:前台交互与后台任务的全场景节能设计
华为·harmonyos
Bruce_Liuxiaowei4 小时前
HarmonyOS Next~鸿蒙系统性能优化全解析:检测、分析与场景实践
华为·性能优化·harmonyos
别说我什么都不会5 小时前
OpenHarmony深度解读之分布式软总线:设备认证机制分析
分布式·操作系统·harmonyos
__Benco5 小时前
OpenHarmony子系统开发 - 电池管理(二)
人工智能·harmonyos
蓬莱宫的生活6 小时前
华为Pura先锋盛典及鸿蒙智家产品发布,空气算法重构健康家居“阔”美学
华为·重构·harmonyos
二川bro6 小时前
HarmonyOS NEXT(九) :图形渲染体系
华为·图形渲染·harmonyos
png7 小时前
从零开始纯血鸿蒙天气预报-天气弹窗(1)
harmonyos·arkts·arkui
威哥爱编程9 小时前
HarmonyOS NEXT 基于原生能力获取视频缩略图
华为·harmonyos·arkts
威哥爱编程9 小时前
HarmonyOS NEXT 实现拖动卡片背景模糊效果
华为·harmonyos·arkts