鸿蒙版(ArkTs) 贪吃蛇,包含无敌模式 最高分 暂停和继续功能

鸿蒙版(ArkTs) 贪吃蛇,包含无敌模式 最高分 暂停和继续功能;

效果图如下:

代码如下:

ts 复制代码
// 所有import语句必须放在文件开头
import router from '@ohos.router';
import promptAction from '@ohos.promptAction';
// Add this import at the top with other imports
// Remove the problematic import
// import { Gradient, GradientDirection } from '@ohos.arkui.graphics';

// 在文件开头添加Preferences导入
import preferences from '@ohos.data.preferences';

// 移除@Entry装饰器
@Entry
@Component
struct Tsc {
  @State snake: Array<[number, number]> = [[5, 5], [5, 6], [5, 7]];
  @State food: [number, number] = [10, 10];
  @State private _moveDirection: number = 3;
  @State score: number = 0;
  @State highScore: number = 0;
  private prefs?: preferences.Preferences; // Use optional type instead of undefined

  @State isInvincible: boolean = false;
  @State foodColor: Color = Color.Red;
  @State snakeHeadColor: Color = Color.Green;
  private gridSize: number = 20;
  private timer: number = 0;
  @State isPlaying: boolean = false;

  // 添加generateFood方法
  generateFood() {
    const gridCells = 12;
    let newFood: [number, number] = [0, 0];
    let validPositionFound = false;
    
    const allPositions: Array<[number, number]> = [];
    for (let x = 0; x < gridCells; x++) {
      for (let y = 0; y < gridCells; y++) {
        allPositions.push([x, y]);
      }
    }
    
    allPositions.sort(() => Math.random() - 0.5);
    
    for (const pos of allPositions) {
      const isOverlap = this.snake.some(segment => 
        segment[0] === pos[0] && segment[1] === pos[1]
      );
      
      if (!isOverlap) {
        newFood = pos;
        validPositionFound = true;
        break;
      }
    }
    
    this.food = newFood;
    this.foodColor = Color.Red; // 设置默认食物颜色
  }

  // 重置游戏状态
  resetGame() {
    this.snake = [[5, 5], [5, 6], [5, 7]];
    this._moveDirection = 3;
    this.score = 0;
    this.generateFood();
  }

  startGame() {
    // 先清除之前的定时器
    if (this.timer) {
      clearInterval(this.timer);
    }
    
    this.resetGame();
    this.isPlaying = true;
    this.timer = setInterval(() => {
      this.moveSnake();
    }, 200);
  }

  // 添加生命周期方法
  aboutToAppear() {
    this.loadHighScore();
  }

  // 加载历史最高分
  async loadHighScore() {
    try {
      this.prefs = await preferences.getPreferences(getContext(this), 'snakeGamePrefs');
      const score = await this.prefs.get('highScore', 0);
      this.highScore = Number(score);
    } catch (err) {
      console.error('Failed to load high score:', err);
    }
  }

  // 保存历史最高分
  async saveHighScore(score: number) {
    try {
      if (this.prefs) { // Add null check
        await this.prefs.put('highScore', score);
        await this.prefs.flush();
      }
    } catch (err) {
      console.error('Failed to save high score:', err);
    }
  }

  endGame() {
    clearInterval(this.timer);
    this.isPlaying = false;
    // 更新历史最高分
    if (this.score > this.highScore) {
      this.highScore = this.score;
      this.saveHighScore(this.highScore);
    }
    promptAction.showToast({
      message: '游戏结束!',
      duration: 2000
    });
  }

  stopGame() {
    clearInterval(this.timer);
    this.isPlaying = false;
    if (this.score > this.highScore) {
      this.highScore = this.score;
      this.saveHighScore(this.highScore);
    }
  }

  moveSnake() {
    if (!this.isPlaying) return;

    let head: [number, number] = [this.snake[0][0], this.snake[0][1]];
    
    switch (this._moveDirection) {
      case 0: head[1] -= 1; break;
      case 1: head[1] += 1; break;
      case 2: head[0] -= 1; break;
      case 3: head[0] += 1; break;
    }

    // 修正边界检测逻辑
    const gridCells = 12; // 与显示区域保持一致
    if (head[0] < 0 || head[0] >= gridCells || 
        head[1] < 0 || head[1] >= gridCells) {
      if (!this.isInvincible) {
        this.endGame();
        return;
      }
      head[0] = (head[0] + gridCells) % gridCells;
      head[1] = (head[1] + gridCells) % gridCells;
    }

    if (head[0] === this.food[0] && head[1] === this.food[1]) {
      this.score += 10;
      this.generateFood();
      // 吃到食物时,只添加新头部,不删除尾部
      this.snake = [head, ...this.snake];
    } else {
      // 没吃到食物时,移动蛇身
      this.snake.pop();
      this.snake = [head, ...this.snake];
    }
  }

  // 添加暂停游戏方法
  @State isPaused: boolean = false; // 添加暂停状态
  
  // 修改暂停游戏方法
  pauseGame() {
    clearInterval(this.timer);
    this.isPlaying = false;
    this.isPaused = true;
  }
  
  // 修改恢复游戏方法
  resumeGame() {
    this.isPlaying = true;
    this.isPaused = false;
    this.timer = setInterval(() => {
      this.moveSnake();
    }, 200);
  }

  build() {
    Column() {
      Button('返回首页')
        .width(100)
        .height(40)
        .fontSize(16)
        .alignSelf(ItemAlign.Start)
        .margin(10)
        .onClick(() => {
          router.pushUrl({
            url: 'pages/Index'
          })
        })

      // 添加历史最高分显示
      Row() {
        Text(`当前得分: ${this.score}`)
          .fontSize(20)
        Text(`最高分: ${this.highScore}`)
          .fontSize(20)
          .margin({ left: 20 })
      }
      .margin({ bottom: 10 })

      // 修改按钮布局
      Row() {
        if (!this.isPlaying && !this.isPaused) {
          Button('开始游戏')
            .width(100)
            .height(35)
            .fontSize(14)
            .margin(5)
            .onClick(() => {
              this.startGame();
            })
        } else if (this.isPlaying) {
          Button('暂停')
            .width(100)
            .height(35)
            .fontSize(14)
            .margin(5)
            .onClick(() => {
              this.pauseGame();
            })
        } else if (this.isPaused) {
          Button('继续')
            .width(100)
            .height(35)
            .fontSize(14)
            .margin(5)
            .onClick(() => {
              this.resumeGame();
            })
        }
        Button('重新开始')
          .width(100)
          .height(35)
          .fontSize(14)
          .margin(5)
          .onClick(() => {
            this.startGame();
          })
        Button('结束游戏')
          .width(100)
          .height(35)
          .fontSize(14)
          .margin(5)
          .onClick(() => {
            this.stopGame();
          })
      }
      .margin({ top: 10 })

      Stack() {
        Circle({ width: this.gridSize, height: this.gridSize })
          .fill(this.foodColor)
          // 使用固定颜色描边
          .stroke(Color.Gray)
          .strokeWidth(2)
          // 添加阴影效果模拟渐变
          .shadow({
            radius: 3,
            color: Color.White,
            offsetX: 1,
            offsetY: 1
          })
          .position({
            x: this.food[0] * this.gridSize,
            y: this.food[1] * this.gridSize
          })
        ForEach(this.snake, (segment: [number, number], index: number) => {
          if (index === 0) {
            Rect({ width: this.gridSize, height: this.gridSize })
              .fill(this.snakeHeadColor)
              .radius(5)
              .position({
                x: segment[0] * this.gridSize,
                y: segment[1] * this.gridSize
              })
          } else {
            // 每节蛇身使用食物颜色
            Circle({ width: this.gridSize, height: this.gridSize })
              .fill(this.foodColor)
              .position({
                x: segment[0] * this.gridSize,
                y: segment[1] * this.gridSize
              })
          }
        })
      }
      .width(this.gridSize * 12)
      .height(this.gridSize * 12)
      .border({ width: 1, color: Color.Black })
      .clip(true) // 添加裁剪确保内容不会超出边框
      .margin({ bottom: 10 })

      Column() {
        Button('上')
          .width(80)
          .height(50)
          .fontSize(18)
          .margin(5)
          .onClick(() => { this._moveDirection = 0; })

        Row() {
          Button('左')
            .width(80)
            .height(50)
            .fontSize(18)
            .margin(5)
            .onClick(() => { this._moveDirection = 2; })
          Button('右')
            .width(80)
            .height(50)
            .fontSize(18)
            .margin(5)
            .onClick(() => { this._moveDirection = 3; })
        }
        
        Button('下')
          .width(80)
          .height(50)
          .fontSize(18)
          .margin(5)
          .onClick(() => { this._moveDirection = 1; })
      }
      .margin({ top: 10 })

      Row() {
        Text('无敌模式:')
          .fontSize(18)
          .fontColor(this.isInvincible ? Color.Red : Color.Black)
          .margin({ right: 10 })
        Toggle({ type: ToggleType.Switch, isOn: this.isInvincible })
          .width(40)
          .height(24)
          .onChange((isOn: boolean) => {
            this.isInvincible = isOn;
          })
        Text(this.isInvincible ? '开启' : '关闭')
          .fontSize(18)
          .fontColor(this.isInvincible ? Color.Red : Color.Black)
          .margin({ left: 10 })
      }
      .margin({ top: 20 })
      .padding(10)
      .borderRadius(10)
      .backgroundColor('#f0f0f0')
      .margin({ top: 10 })
    }
    .width('100%')
    .height('100%')
    .backgroundColor('#E0F7FA')
    .onKeyEvent((event: KeyEvent) => {
      if (event.type === KeyType.Down) {
        switch (event.keyCode) {
          case 19: if (this._moveDirection !== 1) this._moveDirection = 0; break;
          case 20: if (this._moveDirection !== 0) this._moveDirection = 1; break;
          case 21: if (this._moveDirection !== 3) this._moveDirection = 2; break;
          case 22: if (this._moveDirection !== 2) this._moveDirection = 3; break;
        }
      }
    })
  }
}
相关推荐
鸿蒙布道师12 小时前
鸿蒙NEXT开发数值工具类(TS)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
塞尔维亚大汉17 小时前
鸿蒙南向开发 ——轻量系统芯片移植指南(二)
物联网·嵌入式·harmonyos
李元豪18 小时前
华为面试,机器学习深度学习知识点:
机器学习·华为·面试
别说我什么都不会19 小时前
OpenHarmony内核系统调用hats测试用例编写指南
物联网·嵌入式·harmonyos
90后的晨仔20 小时前
鸿蒙ArkTS是如何实现并发的?
harmonyos
鸿蒙布道师1 天前
鸿蒙NEXT开发日期工具类(ArkTs)
android·ios·华为·harmonyos·arkts·鸿蒙系统·huawei
Fanmeang1 天前
DHCP Snooping各种场景实验案例
运维·网络·安全·华为·交换机·dhcp·dhcp snooping
HMSCore1 天前
在应用内购票、寄件时,如何一键填充所需信息?
harmonyos
嘿嘿-g1 天前
华为IP(4)
服务器·网络·华为