• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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}