鸿蒙HarmonyOS 5小游戏实践:数字记忆挑战(附:源代码)

2025-06-29 10:01:42
107次阅读
0个评论

数字记忆挑战游戏:打造提升大脑记忆力的鸿蒙应用

在当今数字时代,人们a的记忆力面临着前所未有的挑战。从日常的待办事项到复杂的工作任务,强大的记忆力都是提高效率和表现的关键。本文将介绍一款基于鸿蒙系统开发的数字记忆挑战游戏,它不仅能为用户提供有趣的娱乐体验,还能有效地锻炼和提升记忆力。我们将深入探讨游戏的设计理念、核心功能、技术实现以及如何通过这款应用帮助用户增强记忆能力。

screenshots (13).gif

游戏设计理念与功能特点

数字记忆挑战游戏的设计灵感来源于经典的记忆训练方法,通过让用户在有限时间内记忆数字的位置并按顺序点击来锻炼短期记忆能力。游戏遵循"循序渐进"的原则,设计了三种不同难度模式,满足不同年龄段和记忆水平用户的需求:

  • 简单模式(4×3网格,数字1-6):适合初学者和儿童,提供较短的记忆时间和较少的数字,帮助用户建立记忆信心和基础方法
  • 中等模式(5×4网格,数字1-10):适合有一定记忆基础的用户,增加了数字数量和记忆难度,挑战用户的记忆容量
  • 困难模式(6×5网格,数字1-15):为记忆高手设计,最多的数字数量和较长的记忆时间,全面考验用户的记忆能力和反应速度

游戏的核心功能围绕记忆训练的科学原理展开,通过以下机制提升训练效果:

  • 限时记忆机制:在显示数字阶段,根据难度不同设置2.5-4秒的记忆时间,模拟真实记忆场景中的时间压力
  • 错误容错机制:设置3次错误机会,让用户在压力下锻炼记忆准确性,同时避免因一次错误就结束游戏
  • 得分系统:根据难度设置不同的得分标准,鼓励用户挑战更高难度,获得更高分数
  • 渐进式挑战:完成当前关卡后自动进入下一轮,数字数量和难度逐步增加,持续刺激大脑记忆能力的提升

技术实现与核心代码解析

游戏状态管理与流程控制

游戏采用状态机模式管理不同阶段的逻辑,定义了四种主要状态:

enum GameState {
  READY,        // 准备状态
  SHOWING_NUMBERS, // 显示数字状态
  PLAYING,      // 游戏进行状态
  GAME_OVER     // 游戏结束状态
}

状态之间的转换构成了游戏的核心流程:从准备状态开始,用户选择难度后进入数字显示状态,记忆时间结束后进入游戏进行状态,用户按顺序点击数字,当错误次数用尽或时间结束时进入游戏结束状态。

startGame() {
  const config = this.getGridConfig(this.gameMode)
  this.currentNumber = 1
  this.score = 0
  this.mistakesLeft = 3

  const result = this.generateNumbers()
  const numbers = result.numbers
  const blanks = result.blanks
  this.numbers = numbers
  this.blankPositions = blanks

  this.showNumbers = true
  this.gameState = GameState.SHOWING_NUMBERS

  // 显示数字3秒后隐藏
  let showTime = 3000
  if (this.gameMode === GameMode.HARD) showTime = 4000
  if (this.gameMode === GameMode.EASY) showTime = 2500

  this.showTimer = setTimeout(() => {
    this.showNumbers = false
    this.gameState = GameState.PLAYING
    this.startTimer()
  }, showTime)
}

数字生成与网格布局算法

游戏使用Fisher-Yates洗牌算法生成随机数字排列,确保每次游戏的数字位置都是随机的,增加了游戏的挑战性和趣味性:

// Fisher-Yates洗牌算法
for (let i = nums.length - 1; i > 0; i--) {
  const j = Math.floor(Math.random() * (i + 1));
  let temp = nums[i]; nums[i] = nums[j]; nums[j] = temp;
}

网格布局根据不同难度模式动态生成,使用鸿蒙系统的Grid组件实现灵活的网格布局:

Grid() {
  ForEach(this.numbers, (num: number, index?: number) => {
    GridItem() {
      Column() {
        // 数字卡片内容
      }
      .width('100%')
      .height('100%')
      .justifyContent(FlexAlign.Center)
      .alignItems(HorizontalAlign.Center)
      .backgroundColor(
        this.blankPositions.includes(index!) ? '#EEEEEE' :
          num < this.currentNumber ? '#4CAF50' : '#4A90E2'
      )
      .borderRadius(8)
      .onClick(() => {
        if (!this.blankPositions.includes(index!)) {
          this.handleCardClick(num, index!)
        }
      })
    }
  })
}
.columnsTemplate(new Array(this.getGridConfig(this.gameMode).cols).fill('1fr').join(' '))
.rowsTemplate(new Array(this.getGridConfig(this.gameMode).rows).fill('1fr').join(' '))
.columnsGap(10)
.rowsGap(10)
.width('90%')
.height(this.getGridConfig(this.gameMode).rows * 70)
.margin({ bottom: 20 })

交互逻辑与反馈机制

游戏实现了完善的交互反馈机制,包括:

  • 视觉反馈:已点击的数字卡片变为绿色,未点击的数字显示为"?",空白格为灰色
  • 错误提示:点击错误数字时显示提示信息,并减少错误次数
  • 进度提示:顶部信息栏实时显示当前需要点击的数字、分数、剩余时间和错误次数
  • 完成提示:完成当前关卡或游戏结束时显示相应的提示信息
handleCardClick(num: number, index: number) {
  if (this.gameState !== GameState.PLAYING) return
  if (this.blankPositions.includes(index)) return // 空白格不可点击

  if (num !== this.currentNumber) {
    this.mistakesLeft--
    promptAction.showToast({
      message: `错误! 剩余机会: ${this.mistakesLeft}`,
      duration: 1000
    })

    if (this.mistakesLeft <= 0) {
      this.gameOver()
    }
    return
  }

  // 正确点击逻辑
  this.currentNumber++

  // 根据难度设置不同的得分
  let points = 10
  if (this.gameMode === GameMode.HARD) points = 15
  if (this.gameMode === GameMode.EASY) points = 5

  this.score += points

  // 检查是否完成
  const config = this.getGridConfig(this.gameMode)
  if (this.currentNumber > config.maxNum) {
    this.levelComplete()
  }
}

记忆训练的科学原理与应用

短期记忆的训练方法

数字记忆挑战游戏的设计基于认知心理学中的短期记忆理论。短期记忆(工作记忆)是指信息在大脑中保持的时间约为15-30秒,容量有限,通常为7±2个组块。游戏通过以下方式锻炼短期记忆:

  • 组块化训练:用户需要将数字及其位置信息组合成组块进行记忆,提高记忆效率
  • 复述训练:在记忆时间内,用户需要主动复述数字及其位置,强化记忆痕迹
  • 视觉空间记忆训练:将数字与空间位置结合记忆,锻炼大脑的视觉空间记忆能力

记忆提升的渐进式训练

游戏的三种难度模式遵循渐进式训练原则,符合记忆能力提升的规律:

  1. 简单模式:小网格、少数字,帮助用户建立记忆信心,掌握基本的记忆方法
  2. 中等模式:中等网格、中等数量数字,挑战用户的记忆容量,训练记忆策略
  3. 困难模式:大网格、多数字,全面考验用户的记忆能力和反应速度,提升记忆极限

应用场景与用户群体

这款数字记忆挑战游戏适用于多种场景和用户群体:

  • 儿童教育:帮助儿童从小锻炼记忆力,提高学习能力
  • 学生群体:缓解学习压力,提升记忆效率,为考试做准备
  • 上班族:在工作间隙进行短暂的记忆训练,缓解大脑疲劳,提高工作效率
  • 中老年人:预防记忆力衰退,降低认知障碍风险,保持大脑活力

游戏优化

当前优化点

游戏在开发过程中进行了多方面的优化,提升用户体验:

  • 响应式布局:适配不同尺寸的鸿蒙设备屏幕,确保在手机、平板等设备上都有良好的显示效果
  • 性能优化:使用鸿蒙系统的高效渲染机制,保证游戏在各种设备上都能流畅运行
  • 用户界面优化:简洁明了的界面设计,清晰的视觉反馈,让用户专注于记忆训练

附:源代码

import { promptAction } from "@kit.ArkUI";

enum GameState {
  READY,
  SHOWING_NUMBERS,
  PLAYING,
  GAME_OVER
}

enum GameMode {
  EASY,     // 4x3网格,数字1-6
  MEDIUM,   // 5x4网格,数字1-10
  HARD      // 6x5网格,数字1-15
}

interface GridConfig {
  cols: number;
  rows: number;
  maxNum: number;
}

interface nerateNumbers {
  numbers: number[];
  blanks: number[];
}

@Component
struct NumberMemoryGame {
  @State gameState: GameState = GameState.READY
  @State numbers: number[] = []
  @State currentNumber: number = 1
  @State score: number = 0
  @State timer: number = 0
  @State showNumbers: boolean = false
  @State gameMode: GameMode = GameMode.MEDIUM
  @State blankPositions: number[] = []
  @State mistakesLeft: number = 3 // 剩余错误次数
  private gameTimer: number = 0
  private showTimer: number = 0

  // 根据模式获取网格配置
  private getGridConfig(mode: GameMode): GridConfig {
    switch (mode) {
      case GameMode.EASY:
        return {cols: 4, rows: 3, maxNum: 6}
      case GameMode.MEDIUM:
        return {cols: 5, rows: 4, maxNum: 10}
      case GameMode.HARD:
        return {cols: 6, rows: 5, maxNum: 15}
      default:
        return {cols: 5, rows: 4, maxNum: 10}
    }
  }

  // 生成数字和空白格
  generateNumbers(): nerateNumbers {
    const config = this.getGridConfig(this.gameMode)
    const totalCells = config.cols * config.rows
    const numbers: number[] = []
    const blanks: number[] = []

    // 随机选择空白格位置
    const blankCount = totalCells - config.maxNum // 确保每个数字只出现一次
    while (blanks.length < blankCount) {
      const pos = Math.floor(Math.random() * totalCells)
      if (!blanks.includes(pos)) {
        blanks.push(pos)
      }
    }

    // 生成数字1-maxNum的随机排列
    const nums: number[] = []
    for (let i = 1; i <= config.maxNum; i++) {
      nums.push(i)
    }

    // Fisher-Yates洗牌算法
    for (let i = nums.length - 1; i > 0; i--) {
      const j = Math.floor(Math.random() * (i + 1));
      let temp = nums[i]; nums[i] = nums[j]; nums[j] = temp;
    }

    // 填充数字到网格
    let numIndex = 0
    for (let i = 0; i < totalCells; i++) {
      if (blanks.includes(i)) {
        numbers.push(0) // 0表示空白格
      } else {
        numbers.push(nums[numIndex++])
      }
    }

    return {numbers, blanks}
  }

  // 开始新游戏
  startGame() {
    const config = this.getGridConfig(this.gameMode)
    this.currentNumber = 1
    this.score = 0
    this.mistakesLeft = 3

    const result = this.generateNumbers()
    const numbers = result.numbers
    const blanks = result.blanks
    this.numbers = numbers
    this.blankPositions = blanks

    this.showNumbers = true
    this.gameState = GameState.SHOWING_NUMBERS

    // 显示数字3秒后隐藏
    if (this.showTimer) {
      clearTimeout(this.showTimer)
    }

    // 根据难度设置不同的记忆时间
    let showTime = 3000
    if (this.gameMode === GameMode.HARD) showTime = 4000
    if (this.gameMode === GameMode.EASY) showTime = 2500

    this.showTimer = setTimeout(() => {
      this.showNumbers = false
      this.gameState = GameState.PLAYING
      this.startTimer()
    }, showTime)
  }

  // 开始计时
  startTimer() {
    // 根据难度设置不同的时间限制
    let timeLimit = 30
    if (this.gameMode === GameMode.HARD) timeLimit = 45
    if (this.gameMode === GameMode.EASY) timeLimit = 20

    this.timer = timeLimit

    if (this.gameTimer) {
      clearInterval(this.gameTimer)
    }

    this.gameTimer = setInterval(() => {
      this.timer--
      if (this.timer <= 0) {
        this.gameOver()
      }
    }, 1000)
  }

  // 处理卡片点击
  handleCardClick(num: number, index: number) {
    if (this.gameState !== GameState.PLAYING) return
    if (this.blankPositions.includes(index)) return // 空白格不可点击

    if (num !== this.currentNumber) {
      this.mistakesLeft--
      promptAction.showToast({
        message: `错误! 剩余机会: ${this.mistakesLeft}`,
        duration: 1000
      })

      if (this.mistakesLeft <= 0) {
        this.gameOver()
      }
      return
    }

    // 正确点击
    this.currentNumber++

    // 根据难度设置不同的得分
    let points = 10
    if (this.gameMode === GameMode.HARD) points = 15
    if (this.gameMode === GameMode.EASY) points = 5

    this.score += points

    // 检查是否完成
    const config = this.getGridConfig(this.gameMode)
    if (this.currentNumber > config.maxNum) {
      this.levelComplete()
    }
  }

  // 关卡完成
  levelComplete() {
    clearInterval(this.gameTimer)
    promptAction.showToast({
      message: `恭喜完成! 得分: ${this.score}`,
      duration: 2000
    })

    // 准备下一轮
    setTimeout(() => {
      this.startGame()
    }, 2000)
  }

  // 游戏结束
  gameOver() {
    clearInterval(this.gameTimer)
    this.gameState = GameState.GAME_OVER
    promptAction.showToast({
      message: `游戏结束! 最终得分: ${this.score}`,
      duration: 2000
    })
  }

  build() {
    Column() {
      // 游戏状态判断
      if (this.gameState === GameState.READY) {
        this.buildStartScreen()
      } else if (this.gameState === GameState.GAME_OVER) {
        this.buildGameOverScreen()
      } else {
        this.buildGameScreen()
      }
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#F5F7FA')
  }

  // 开始界面
  @Builder buildStartScreen() {
    Column() {
      Text("数字记忆挑战")
        .fontSize(28)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ bottom: 30 })

      Text("记住数字的位置\n按1开始的顺序点击数字\n每个数字只出现一次\n错误不能超过3次")
        .fontSize(16)
        .textAlign(TextAlign.Center)
        .fontColor('#666666')
        .margin({ bottom: 40 })

      Text("选择难度模式:")
        .fontSize(18)
        .fontColor('#333333')
        .margin({ bottom: 15 })

      // 模式选择按钮
      Button("简单模式", { type: ButtonType.Capsule })
        .onClick(() => {
          this.gameMode = GameMode.EASY
        })
        .width(240)
        .height(50)
        .fontSize(18)
        .backgroundColor(this.gameMode === GameMode.EASY ? '#4CAF50' : '#E0E0E0')
        .fontColor(this.gameMode === GameMode.EASY ? Color.White : '#333333')
        .margin({ bottom: 15 })

      Button("中等模式", { type: ButtonType.Capsule })
        .onClick(() => {
          this.gameMode = GameMode.MEDIUM
        })
        .width(240)
        .height(50)
        .fontSize(18)
        .backgroundColor(this.gameMode === GameMode.MEDIUM ? '#2196F3' : '#E0E0E0')
        .fontColor(this.gameMode === GameMode.MEDIUM ? Color.White : '#333333')
        .margin({ bottom: 15 })

      Button("困难模式", { type: ButtonType.Capsule })
        .onClick(() => {
          this.gameMode = GameMode.HARD
        })
        .width(240)
        .height(50)
        .fontSize(18)
        .backgroundColor(this.gameMode === GameMode.HARD ? '#F44336' : '#E0E0E0')
        .fontColor(this.gameMode === GameMode.HARD ? Color.White : '#333333')
        .margin({ bottom: 30 })

      Button("开始挑战", { type: ButtonType.Capsule })
        .onClick(() => this.startGame())
        .width(240)
        .height(50)
        .fontSize(18)
        .backgroundColor('#4A90E2')
        .fontColor(Color.White)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  // 游戏结束界面
  @Builder buildGameOverScreen() {
    Column() {
      Text(this.mistakesLeft <= 0 ? "机会用尽!" : "时间到!")
        .fontSize(24)
        .fontWeight(FontWeight.Bold)
        .fontColor('#F44336')
        .margin({ bottom: 15 })

      Text(`最终得分: ${this.score}`)
        .fontSize(20)
        .fontWeight(FontWeight.Bold)
        .fontColor('#333333')
        .margin({ bottom: 10 })

      Text(`模式: ${
      this.gameMode === GameMode.EASY ? "简单" :
        this.gameMode === GameMode.MEDIUM ? "中等" : "困难"
      }`)
        .fontSize(18)
        .fontColor('#666666')
        .margin({ bottom: 30 })

      Button("再试一次", { type: ButtonType.Capsule })
        .onClick(() => this.startGame())
        .width(200)
        .height(45)
        .fontSize(17)
        .backgroundColor('#4A90E2')
        .fontColor(Color.White)
        .margin({ bottom: 15 })

      Button("选择模式", { type: ButtonType.Capsule })
        .onClick(() => {
          this.gameState = GameState.READY
        })
        .width(200)
        .height(45)
        .fontSize(17)
        .backgroundColor('#9E9E9E')
        .fontColor(Color.White)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
    .alignItems(HorizontalAlign.Center)
  }

  // 游戏界面
  @Builder buildGameScreen() {
    Column() {
      // 顶部信息栏
      Row() {
        Column() {
          Text("当前数字")
            .fontSize(14)
            .fontColor('#666666')
          Text(`${this.currentNumber > this.getGridConfig(this.gameMode).maxNum ? '完成!' : this.currentNumber}`)
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .fontColor(this.currentNumber > this.getGridConfig(this.gameMode).maxNum ? '#4CAF50' : '#333333')
        }
        .margin({ right: 25 })

        Column() {
          Text("分数")
            .fontSize(14)
            .fontColor('#666666')
          Text(`${this.score}`)
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .fontColor('#FF9800')
        }
        .margin({ right: 25 })

        Column() {
          Text("时间")
            .fontSize(14)
            .fontColor('#666666')
          Text(`${this.timer}s`)
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .fontColor(this.timer <= 5 ? '#F44336' : '#333333')
        }

        Column() {
          Text("机会")
            .fontSize(14)
            .fontColor('#666666')
          Text(`${this.mistakesLeft}`)
            .fontSize(20)
            .fontWeight(FontWeight.Bold)
            .fontColor(this.mistakesLeft <= 1 ? '#F44336' : '#333333')
        }
      }
      .width('100%')
      .justifyContent(FlexAlign.Start)
      .padding({ left: 20, top: 15, bottom: 15 })

      // 游戏提示
      Text(this.showNumbers ? "记住这些数字的位置..." : `请点击数字 ${this.currentNumber}`)
        .fontSize(16)
        .fontColor('#666666')
        .margin({ bottom: 15 })

      // 数字网格
      Grid() {
        ForEach(this.numbers, (num: number, index?: number) => {
          GridItem() {
            Column() {
              if (this.blankPositions.includes(index!)) {
                // 空白格
                Text("")
                  .width('100%')
                  .height('100%')
                  .backgroundColor('#EEEEEE')
              } else if (this.showNumbers || num < this.currentNumber) {
                // 已显示或已点击的数字
                Text(num.toString())
                  .fontSize(22)
                  .fontWeight(FontWeight.Bold)
                  .fontColor('#FFFFFF')
              } else {
                // 未点击的数字
                Text("?")
                  .fontSize(22)
                  .fontWeight(FontWeight.Bold)
                  .fontColor('#FFFFFF')
              }
            }
            .width('100%')
            .height('100%')
            .justifyContent(FlexAlign.Center)
            .alignItems(HorizontalAlign.Center)
            .backgroundColor(
              this.blankPositions.includes(index!) ? '#EEEEEE' :
                num < this.currentNumber ? '#4CAF50' : '#4A90E2'
            )
            .borderRadius(8)
            .onClick(() => {
              if (!this.blankPositions.includes(index!)) {
                this.handleCardClick(num, index!)
              }
            })
          }
        })
      }
      .columnsTemplate(new Array(this.getGridConfig(this.gameMode).cols).fill('1fr').join(' '))
      .rowsTemplate(new Array(this.getGridConfig(this.gameMode).rows).fill('1fr').join(' '))
      .columnsGap(10)
      .rowsGap(10)
      .width('90%')
      .height(this.getGridConfig(this.gameMode).rows * 70)
      .margin({ bottom: 20 })
    }
    .width('100%')
    .height('100%')
    .alignItems(HorizontalAlign.Center)
  }
}

@Entry
@Component
struct NumberMemoryGamePage {
  build() {
    Stack() {
      NumberMemoryGame()
    }
    .width('100%')
    .height('100%')
  }
}

结语

数字记忆挑战游戏作为一款基于鸿蒙系统开发的记忆训练应用,不仅展现了鸿蒙系统在应用开发中的强大能力,更为用户提供了一种科学、有趣的记忆训练方式。通过循序渐进的难度设计和科学的记忆训练原理,这款游戏能够帮助不同年龄段的用户提升记忆力,锻炼大脑思维能力。

随着鸿蒙生态的不断发展和完善,类似的脑力训练应用将在教育、健康等领域发挥更大的作用。数字记忆挑战游戏只是一个开始,未来我们可以期待更多基于鸿蒙系统的创新应用,为用户的生活和学习带来更多的便利和价值。如果你对记忆训练感兴趣,不妨下载这款游戏,开始你的记忆提升之旅吧!

收藏00

登录 后评论。没有帐号? 注册 一个。