@Entry
@Component
struct MemoryGame {
  // 游戏卡片数据
  @State cards: CardItem[] = []
  
  // 当前翻开的卡片索引
  @State flippedIndexes: number[] = []
 
  // 游戏得分
  @State score: number = 0
  
  // 游戏计时
  @State timeElapsed: number = 0
  private timer: number = 0

  // 初始化卡片数据
  aboutToAppear() {
    this.resetGame()
// 重置游戏

  resetGame() {
    // 生成配对卡片(示例使用数字配对)
    const numbers = [1,1,2,2,3,3,4,4,5,5,6,6]
    this.cards = numbers
      .sort(() => Math.random() - 0.5) // 随机排序
      .map((num, index) => ({
        id: index,
        value: num,
        isFlipped: false,
        isMatched: false
      }))
    
    this.score = 0
    this.timeElapsed = 0
    this.startTimer()
// 启动计时器

  startTimer() {
    if (this.timer) clearInterval(this.timer)
    this.timer = setInterval(() => {
      this.timeElapsed++
    }, 1000)
// 处理卡片点击

  handleCardClick(index: number) {
    // 如果已经匹配或正在动画中,则忽略点击
    if (this.cards[index].isMatched || this.flippedIndexes.length >= 2) return

    // 翻转卡片
    this.cards[index].isFlipped = true
    this.flippedIndexes.push(index)

    // 检查是否匹配
    if (this.flippedIndexes.length === 2) {
      const [first, second] = this.flippedIndexes
      if (this.cards[first].value === this.cards[second].value) {
        // 匹配成功
        this.cards[first].isMatched = true
        this.cards[second].isMatched = true
        this.score += 100
        this.flippedIndexes = []
        this.checkGameOver()
else {

        // 匹配失败,延迟后翻转回来
        setTimeout(() => {
          this.cards[first].isFlipped = false
          this.cards[second].isFlipped = false
          this.flippedIndexes = []
        }, 1000)
}

// 检查游戏是否结束

  checkGameOver() {
    if (this.cards.every(card => card.isMatched)) {
      clearInterval(this.timer)
      // 显示胜利提示
      alert(`游戏结束!得分:{this.score} 用时:{this.timeElapsed}秒`)
}

  build() {
    Column() {
      // 得分和计时显示
      Row({ justify: FlexAlign.SpaceBetween }) {
        Text(`得分:${this.score}`).fontSize(20)
        Text(`时间:${this.timeElapsed}秒`).fontSize(20)
      }.padding(10)

      // 游戏主区域
      Grid() {
        ForEach(this.cards, (item: CardItem, index) => {
          GridItem() {
            // 单个卡片组件
            CardComponent({
              item: item,
              onClick: () => this.handleCardClick(index)
            })
})

.columnsTemplate('1fr 1fr 1fr 1fr') // 4列布局

      .columnsGap(10)
      .rowsGap(10)
      .padding(10)

      // 重置按钮
      Button('重新开始')
        .onClick(() => this.resetGame())
        .margin(10)
}

// 卡片组件

@Component
struct CardComponent {
  @Link item: CardItem
  onClick: () => void

  build() {
    Column() {
      if (this.item.isFlipped || this.item.isMatched) {
        Text(this.item.value.toString())
          .fontSize(30)
          .fontColor(Color.White)
else {

        Text('?')
          .fontSize(30)
          .fontColor(Color.Black)
}

    .size({ width: 80, height: 100 })
    .justifyContent(FlexAlign.Center)
    .borderRadius(10)
    .backgroundColor(this.item.isMatched ? Color.Green : (this.item.isFlipped ? Color.Blue : Color.Gray))
    .onClick(() => this.onClick())
    // 添加翻转动画
    .animation({ duration: 300, curve: Curve.EaseOut })
}

// 卡片数据接口
interface CardItem {
  id: number
  value: number
  isFlipped: boolean
  isMatched: boolean

代码解析:
游戏架构

使用Grid布局实现4x3的卡片矩阵(可根据需要调整columnsTemplate)

卡片组件CardComponent实现单个卡片的显示逻辑

主组件MemoryGame管理游戏状态和逻辑
核心功能实现

卡片翻转逻辑:通过isFlipped状态控制显示内容

匹配检测:记录两次点击的索引,比较value值是否相同

动画效果:使用.animation()实现平滑的翻转动画

游戏计时:通过setInterval实现秒表功能

状态管理:使用@State装饰器管理游戏数据
关键功能点

// 卡片点击处理逻辑
handleCardClick(index: number) {
  // 防止重复点击
  if (this.cards[index].isMatched || this.flippedIndexes.length >= 2) return

  // 翻转卡片
  this.cards[index].isFlipped = true
  this.flippedIndexes.push(index)

  // 检查匹配
  if (this.flippedIndexes.length === 2) {
    const [first, second] = this.flippedIndexes
    if (this.cards[first].value === this.cards[second].value) {
      // 匹配成功处理
      this.cards[first].isMatched = true
      this.cards[second].isMatched = true
      this.score += 100
      this.checkGameOver()
else {

      // 匹配失败处理(延迟翻转)
      setTimeout(() => {
        this.cards[first].isFlipped = false
        this.cards[second].isFlipped = false
      }, 1000)
this.flippedIndexes = []

}

布局系统

使用Grid网格布局实现卡片排列

通过columnsTemplate控制列数

使用Flex布局管理得分和计时显示

运行效果:
4x3网格显示12张背面卡片

点击卡片翻转显示数字

匹配成功卡片保持翻开状态(变绿色)

匹配失败卡片1秒后翻转回去

顶部显示当前得分和用时

全部匹配后弹出得分提示

扩展建议:
增加难度选择:通过修改columnsTemplate实现不同大小的网格

添加音效:使用AudioPlayer播放点击和匹配音效

增加卡片图案:使用Image组件代替数字

实现计分动画:使用属性动画实现得分变化效果

添加本地存储:使用Preferences保存最高分记录

这个示例展示了HarmonyOS应用开发的核心技术:
声明式UI开发

状态管理

组件化开发

动画实现

事件处理

开发环境要求:
DevEco Studio 3.1+

HarmonyOS SDK API 9+

模拟器或真机运行

Logo

讨论HarmonyOS开发技术,专注于API与组件、DevEco Studio、测试、元服务和应用上架分发等。

更多推荐