@toc
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)
实现过程
- 创建
MineSweeping
项目 - 修改
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) }
- 点击"开始游戏"进行初始化棋盘、棋盘格埋雷、计算棋盘格周边雷数。
- 创建
-
初始化棋盘
当前以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宫格的方式,以中间方格为基准,周边存在雷的方格数量累加在一起即为当前基准格的周边雷数。同时在计算时不能超出给定的行数和列数。// 统计周边雷数 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; }
- 给"开始游戏"按钮添加点击效果。
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);
}
5. 点击棋盘格处理方式
// 需要引入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;
})
#### 预览效果

#### 说明
本项目已提交至开源仓:[仓库地址](https://gitee.com/openharmony/vendor_hihope/tree/master/rk3568/demo)
经典小游戏扫雷源码(https://ost.51cto.com/resource/2157)
[想了解更多关于开源的内容,请访问:](https://ost.51cto.com/#bkwz)
[51CTO 开源基础软件社区](https://ost.51cto.com#bkwz)
https://ost.51cto.com/#bkwz