1

#DAYU200体验官# 经典小游戏之扫雷[初版]-开源基础软件社区-51CTO.COM

 1 year ago
source link: https://ost.51cto.com/posts/14411
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

#DAYU200体验官# 经典小游戏之扫雷[初版] 原创 精华

1992年4月6日,"扫雷"小游戏首次搭载在Windows3.1,至今正好30周年,如今被贴上了"暴露年龄"标签😂😂,本节实现"扫雷"小游戏并运行在DAYU200开发板上

  • 开发板:DAYU200
  • 系统版本:OpenHarmony v3.2 Beta1
  • Sdk版本:ohos-sdk 3.2.2.5
  • 开发工具:DevEco Studio 3.0.0.901(For OpenHarmony)
  1. 创建MineSweeping项目
  2. 修改index.ets页面代码,使用Stack容器、Image组件、Text组件构建开始游戏按钮。
Stack({alignContent: Alignment.Center}) {
  Image($r('app.media.start_game'))
    .width(240)
    .height(120)
  Text('开始游戏')
    .fontSize(18)
    .fontColor(Color.White)
    .fontWeight(FontWeight.Bold)
}
  1. 点击"开始游戏"进行初始化棋盘、棋盘格埋雷、计算棋盘格周边雷数。
  • 初始化棋盘
    当前以4*4棋盘格为例,使用Grid网格容器,由"行"和"列"分割的单元格组成棋盘。定义棋盘格类Board如下:
class Board {
  x: number	// 棋盘格行标识
  y: number	// 棋盘格列标识
  content: string	// 周边雷数
  isCover: boolean	// 默认显示图片
  isMine: boolean	// 是否雷区
  isClick: boolean	// 是否点击

  constructor(x: number, y: number, content: string, isCover: boolean, isMine: boolean, isClick: boolean) {
    this.x = x;
    this.y = y;
    this.content = content;
    this.isCover = isCover;
    this.isMine = isMine;
    this.isClick = isClick;
  }
}

通过循环渲染ForEach方式,构建Grid网格容器中的单元格GridItem

Grid() {
  ForEach(this.boards, (item: Board) => {
    GridItem() {
      Stack({alignContent: Alignment.Center}) {
        Image(item.isCover ? $r('app.media.loading_icon') : (item.isMine ? $r('app.media.app_icon') : $r('app.media.click_bg')))
          .width((!item.isCover && item.isMine) ? 80 : '100%')
        Text(item.isClick ? ((item.content === '9' || item.content === '0') ? '' : item.content) : '')
          .fontSize(26).fontWeight(FontWeight.Bold)
      }
      .width('100%').height(100)
    }
  }, (item: Board) => (item.x + ',' + item.y).toString())
}
.width('95%')
.columnsTemplate(this.gridFr)
.columnsGap(0)
.rowsGap(0)
.height(500)
  • 棋盘格埋雷
    使用随机方式,进行埋雷,代码如下:
// 埋雷
setMine = (rows: number, cols: number) => {
  // 当达到设定的数量时跳出
  if (this.mineCount >= this.maxMineNum) {
    return false;
  }
  // 随机获取坐标值
  let randomX = Math.floor(Math.random() * rows);
  let randomY = Math.floor(Math.random() * cols);
  // 埋雷
  this.boards.forEach(item => {
    if (item.x === randomX && item.y === randomY) {
      if (!item.isMine) {
        item.isMine = true;
        this.mineCount++;
      }
    }
  })
  this.setMine(rows, cols);
}
  • 计算棋盘格周边雷数
    周边雷数的计算,使用9宫格的方式,以中间方格为基准,周边存在雷的方格数量累加在一起即为当前基准格的周边雷数。同时在计算时不能超出给定的行数和列数。
    #DAYU200体验官# 经典小游戏之扫雷[初版]-开源基础软件社区
// 统计周边雷数
boardAreaMine = (rows: number, cols: number) => {
  // 判断周边雷,并计数
  let boards = this.boards;
  for (let i = 0; i < boards.length; i++) {
    let cell = boards[i];
    if (cell.isMine) {
      continue;
    }
    let count = 0;
    // 左上
    let leftTopCellX = cell.x - 1, leftTopCellY = cell.y - 1;
    if (leftTopCellX >= 0 && leftTopCellY >= 0 && leftTopCellX < rows && leftTopCellY < cols) {
      boards.filter(item => {
        if (item.x === leftTopCellX && item.y === leftTopCellY && item.isMine) {
          count++;
        }
      })
    }
    // 上
    let topCellX = cell.x - 1, topCellY = cell.y;
    if (topCellX >= 0 && topCellY >= 0 && topCellX < rows && topCellY < cols) {
      boards.filter(item => {
        if (item.x === topCellX && item.y === topCellY && item.isMine) {
          count++;
        }
      })
    }
    // 右上
    let rightTopCellX = cell.x - 1, rightTopCellY = cell.y + 1;
    if (rightTopCellX >= 0 && rightTopCellY >= 0 && rightTopCellX < rows && rightTopCellY < cols) {
      boards.filter(item => {
        if (item.x === rightTopCellX && item.y === rightTopCellY && item.isMine) {
          count++;
        }
      })
    }
    // 右
    let rightCellX = cell.x, rightCellY = cell.y + 1;
    if (rightCellX >= 0 && rightCellY >= 0 && rightCellX < rows && rightCellY < cols) {
      boards.filter(item => {
        if (item.x === rightCellX && item.y === rightCellY && item.isMine) {
          count++;
        }
      })
    }
    // 右下
    let rightBottomCellX = cell.x + 1, rightBottomCellY = cell.y + 1;
    if (rightBottomCellX >= 0 && rightBottomCellY >= 0 && rightBottomCellX < rows && rightBottomCellY < cols) {
      boards.filter(item => {
        if (item.x === rightBottomCellX && item.y === rightBottomCellY && item.isMine) {
          count++;
        }
      })
    }
    // 下
    let bottomCellX = cell.x + 1, bottomCellY = cell.y;
    if (bottomCellX >= 0 && bottomCellY >= 0 && bottomCellX < rows && bottomCellY < cols) {
      boards.filter(item => {
        if (item.x === bottomCellX && item.y === bottomCellY && item.isMine) {
          count++;
        }
      })
    }
    // 左下
    let leftBottomCellX = cell.x + 1, leftBottomCellY = cell.y - 1;
    if (leftBottomCellX >= 0 && leftBottomCellY >= 0 && leftBottomCellX < rows && leftBottomCellY < cols) {
      boards.filter(item => {
        if (item.x === leftBottomCellX && item.y === leftBottomCellY && item.isMine) {
          count++;
        }
      })
    }
    // 左
    let leftCellX = cell.x, leftCellY = cell.y - 1;
    if (leftCellX >= 0 && leftCellY >= 0 && leftCellX < rows && leftCellY < cols) {
      boards.filter(item => {
        if (item.x === leftCellX && item.y === leftCellY && item.isMine) {
          count++;
        }
      })
    }
    if (count === 0) {
      count = 9;
    }
    cell.content = count.toString();
  }
  this.boards = boards;
}
  1. 给"开始游戏"按钮添加点击效果。
Stack({alignContent: Alignment.Center}) {
}
.onClick(() => {
   // 此处编写逻辑代码
   this.init();
})

// 初始化棋盘,埋雷,计算棋盘格周边雷数初始化方法
init = () => {
  this.initBoard(this.boardRowsNum, this.boardColsNum);
  this.setMine(this.boardRowsNum, this.boardColsNum);
  this.boardAreaMine(this.boardRowsNum, this.boardColsNum);
}
  1. 点击棋盘格处理方式
// 需要引入prompt
import prompt from '@ohos.prompt';

GridItem() {...}
.onClick(() => {
  if ((this.clickCount - 1) === this.maxMineNum) {
    prompt.showToast({
      message: '恭喜你,成功排雷!',
      duration: 2000
    })
    this.boards = [];
    return false;
  }
  let tempBoards = this.boards;
  this.boards = new Array<Board>();
  tempBoards.forEach(temp => {
    if (temp.x === item.x && temp.y === item.y) {
      temp.isClick = true;
      temp.isCover = false
      if (temp.isMine) {
        AlertDialog.show({
          message: '您踩雷了,游戏结束~',
          autoCancel: false,
          primaryButton: {
            value: '重新开始',
            action: () => {
              this.init();
            }
          },
          secondaryButton: {
            value: '不玩了~',
            action: () => {
              this.boards = [];
            }
          },
          alignment: DialogAlignment.Center
        })
      } else {
        this.clickCount--;
      }
    }
  })
  this.boards = tempBoards;
})

#DAYU200体验官# 经典小游戏之扫雷[初版]-开源基础软件社区

本项目已提交至开源仓:仓库地址


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK