1/* 2 * Copyright (C) 2022 HiHope Open Source Organization . 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http:// www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * 14 * limitations under the License. 15 */ 16import prompt from '@ohos.prompt'; 17class Board { 18 x: number 19 y: number 20 content: string 21 isCover: boolean 22 isMine: boolean 23 isClick: boolean 24 25 constructor(x: number, y: number, content: string, isCover: boolean, isMine: boolean, isClick: boolean) { 26 this.x = x; 27 this.y = y; 28 this.content = content; 29 this.isCover = isCover; 30 this.isMine = isMine; 31 this.isClick = isClick; 32 } 33} 34 35 36@Entry 37@Component 38struct Index { 39 @State boards: Array<Board> = new Array<Board>(); 40 // 当前设置雷计数 41 @State mineCount: number = 0; 42 // 最大雷数 43 private maxMineNum: number = 4; 44 45 // 棋盘行/列数 46 private boardRowsNum: number = 4; 47 private boardColsNum: number = 4; 48 49 @State images: Array<Resource> = [$r("app.media.app_icon"), $r('app.media.loading_icon')] 50 @State gridFr: string = ""; 51 @State clickCount: number = 0; 52 53 // 初始化棋盘行显示数 54 initGrid = (rows: number) => { 55 for (let i = 0; i < rows; i++) { 56 this.gridFr += (i === 0 ? '1fr' : ' 1fr'); 57 } 58 } 59 60 init = () => { 61 this.initBoard(this.boardRowsNum, this.boardColsNum); 62 this.setMine(this.boardRowsNum, this.boardColsNum); 63 this.boardAreaMine(this.boardRowsNum, this.boardColsNum); 64 } 65 66 // 初始化棋盘 67 initBoard = (rows: number, cols: number) => { 68 this.boards = new Array<Board>(); 69 this.clickCount = rows * cols; 70 this.mineCount = 0; 71 this.gridFr = ""; 72 this.initGrid(rows); 73 for (let i = 0; i < rows; i++) { 74 for (let j = 0; j < cols; j++) { 75 this.boards.push(new Board(i, j, '0', true, false, false)) 76 } 77 } 78 } 79 80 // 埋雷 81 setMine = (rows: number, cols: number) => { 82 // 当达到设定的数量时跳出 83 if (this.mineCount >= this.maxMineNum) { 84 return false; 85 } 86 // 随机获取坐标值 87 let randomX = Math.floor(Math.random() * rows); 88 let randomY = Math.floor(Math.random() * cols); 89 // 埋雷 90 this.boards.forEach(item => { 91 if (item.x === randomX && item.y === randomY) { 92 if (!item.isMine) { 93 item.isMine = true; 94 this.mineCount++; 95 } 96 } 97 }) 98 this.setMine(rows, cols); 99 } 100 101 // 统计周边雷数 102 boardAreaMine = (rows: number, cols: number) => { 103 // 判断周边雷,并计数 104 let boards = this.boards; 105 for (let i = 0; i < boards.length; i++) { 106 let cell = boards[i]; 107 if (cell.isMine) { 108 continue; 109 } 110 let count = 0; 111 // 左上 112 let leftTopCellX = cell.x - 1, leftTopCellY = cell.y - 1; 113 if (leftTopCellX >= 0 && leftTopCellY >= 0 && leftTopCellX < rows && leftTopCellY < cols) { 114 boards.filter(item => { 115 if (item.x === leftTopCellX && item.y === leftTopCellY && item.isMine) { 116 count++; 117 } 118 }) 119 } 120 // 上 121 let topCellX = cell.x - 1, topCellY = cell.y; 122 if (topCellX >= 0 && topCellY >= 0 && topCellX < rows && topCellY < cols) { 123 boards.filter(item => { 124 if (item.x === topCellX && item.y === topCellY && item.isMine) { 125 count++; 126 } 127 }) 128 } 129 // 右上 130 let rightTopCellX = cell.x - 1, rightTopCellY = cell.y + 1; 131 if (rightTopCellX >= 0 && rightTopCellY >= 0 && rightTopCellX < rows && rightTopCellY < cols) { 132 boards.filter(item => { 133 if (item.x === rightTopCellX && item.y === rightTopCellY && item.isMine) { 134 count++; 135 } 136 }) 137 } 138 // 右 139 let rightCellX = cell.x, rightCellY = cell.y + 1; 140 if (rightCellX >= 0 && rightCellY >= 0 && rightCellX < rows && rightCellY < cols) { 141 boards.filter(item => { 142 if (item.x === rightCellX && item.y === rightCellY && item.isMine) { 143 count++; 144 } 145 }) 146 } 147 // 右下 148 let rightBottomCellX = cell.x + 1, rightBottomCellY = cell.y + 1; 149 if (rightBottomCellX >= 0 && rightBottomCellY >= 0 && rightBottomCellX < rows && rightBottomCellY < cols) { 150 boards.filter(item => { 151 if (item.x === rightBottomCellX && item.y === rightBottomCellY && item.isMine) { 152 count++; 153 } 154 }) 155 } 156 // 下 157 let bottomCellX = cell.x + 1, bottomCellY = cell.y; 158 if (bottomCellX >= 0 && bottomCellY >= 0 && bottomCellX < rows && bottomCellY < cols) { 159 boards.filter(item => { 160 if (item.x === bottomCellX && item.y === bottomCellY && item.isMine) { 161 count++; 162 } 163 }) 164 } 165 // 左下 166 let leftBottomCellX = cell.x + 1, leftBottomCellY = cell.y - 1; 167 if (leftBottomCellX >= 0 && leftBottomCellY >= 0 && leftBottomCellX < rows && leftBottomCellY < cols) { 168 boards.filter(item => { 169 if (item.x === leftBottomCellX && item.y === leftBottomCellY && item.isMine) { 170 count++; 171 } 172 }) 173 } 174 // 左 175 let leftCellX = cell.x, leftCellY = cell.y - 1; 176 if (leftCellX >= 0 && leftCellY >= 0 && leftCellX < rows && leftCellY < cols) { 177 boards.filter(item => { 178 if (item.x === leftCellX && item.y === leftCellY && item.isMine) { 179 count++; 180 } 181 }) 182 } 183 if (count === 0) { 184 count = 9; 185 } 186 cell.content = count.toString(); 187 } 188 this.boards = boards; 189 } 190 191 192 build() { 193 Column({space: 20}) { 194 Row() { 195 Stack({alignContent: Alignment.Center}) { 196 Image($r('app.media.start_game')) 197 .width(240) 198 .height(120) 199 Text('开始游戏') 200 .fontSize(18) 201 .fontColor(Color.White) 202 .fontWeight(FontWeight.Bold) 203 } 204 .onClick(() => { 205 this.init(); 206 }) 207 } 208 209 210 Grid() { 211 ForEach(this.boards, (item: Board) => { 212 GridItem() { 213 Stack({alignContent: Alignment.Center}) { 214 Image(item.isCover ? $r('app.media.loading_icon') : (item.isMine ? $r('app.media.app_icon') : $r('app.media.click_bg'))) 215 .width((!item.isCover && item.isMine) ? 80 : '100%') 216 Text(item.isClick ? ((item.content === '9' || item.content === '0') ? '' : item.content) : '') 217 .fontSize(26).fontWeight(FontWeight.Bold) 218 } 219 .width('100%').height(100) 220 } 221 .border({ 222 width: 1, 223 style: BorderStyle.Solid, 224 color: Color.White 225 }) 226 .onClick(() => { 227 if ((this.clickCount - 1) === this.maxMineNum) { 228 prompt.showToast({ 229 message: '恭喜你,成功排雷!', 230 duration: 2000 231 }) 232 this.boards = []; 233 return false; 234 } 235 let tempBoards = this.boards; 236 this.boards = new Array<Board>(); 237 tempBoards.forEach(temp => { 238 if (temp.x === item.x && temp.y === item.y) { 239 temp.isClick = true; 240 temp.isCover = false 241 if (temp.isMine) { 242 AlertDialog.show({ 243 message: '您踩雷了,游戏结束~', 244 autoCancel: false, 245 primaryButton: { 246 value: '重新开始', 247 action: () => { 248 this.init(); 249 } 250 }, 251 secondaryButton: { 252 value: '不玩了~', 253 action: () => { 254 this.boards = []; 255 } 256 }, 257 alignment: DialogAlignment.Center 258 }) 259 } else { 260 this.clickCount--; 261 } 262 } 263 }) 264 this.boards = tempBoards; 265 }) 266 }, (item: Board) => (item.x + ',' + item.y).toString()) 267 } 268 .width('95%') 269 .columnsTemplate(this.gridFr) 270 .columnsGap(0) 271 .rowsGap(0) 272 .height(500) 273 274 if (this.boards.length > 0) { 275 Row() { 276 Text(`还剩多少方格${this.clickCount}`).fontSize(16).fontWeight(FontWeight.Bold) 277 Text(`总共有${this.maxMineNum}个雷需要排`).fontSize(16).fontWeight(FontWeight.Bold) 278 } 279 .width('100%') 280 .justifyContent(FlexAlign.SpaceAround) 281 } 282 } 283 .width('100%') 284 .height('100%') 285 } 286}