|
7 | 7 | </vue-drr>
|
8 | 8 | <div class="game-config">
|
9 | 9 | <form action="" @submit.prevent="init">
|
10 |
| - <label>行: <input type="number" v-model="inputRow"></label> |
11 |
| - <label>列: <input type="number" v-model="inputCol"></label> |
12 |
| - <label>雷的数量: <input type="number" v-model="inputBombCount"></label> |
| 10 | + <label>行: <input type="number" min="2" :max="config.maxRow" v-model="inputRow"></label> |
| 11 | + <label>列: <input type="number" min="2" :max="config.maxCol" v-model="inputCol"></label> |
| 12 | + <label>雷的数量: <input type="number" min="1" :max="~~inputRow * ~~inputCol - 1" v-model="inputBombCount"></label> |
13 | 13 | <button type="submit">生成</button>
|
14 | 14 | </form>
|
15 | 15 | <div v-if="showTips" class="game-config-tips">{{ tipsText }}</div>
|
16 | 16 | </div>
|
17 |
| - <table :width="width" class="game" :class="{'tips-open': showTips}" @mouseup="handleClick" @contextmenu.prevent="handleRightClick"> |
| 17 | + <table :width="width" class="game" :class="{'tips-open': showTips}" @click="handleClick" @contextmenu.prevent="handleRightClick" @dblclick="handleDblClick"> |
18 | 18 | <tr :key="row" v-for="(rows, row) in cellData">
|
19 | 19 | <cell :key="col" v-for="(cell, col) in rows" :row="cell.row" :col="cell.col" :isBomb="cell.isBomb" :status="cell.status" :isFlag="cell.isFlag" :bombCount="cell.bombCount"></cell>
|
20 | 20 | </tr>
|
|
23 | 23 | <div>Game Over</div>
|
24 | 24 | <div>你美丽了!</div>
|
25 | 25 | <div class="retry"><a href="#" @click.prevent="init">再试一次</a></div>
|
| 26 | + <div class="retry"><a href="#" @click.prevent="view">查看雷的位置</a></div> |
26 | 27 | </div>
|
27 | 28 | <div v-if="success" class="success layer">
|
28 | 29 | <div>Win!</div>
|
29 | 30 | <div>你成功了!</div>
|
30 | 31 | <div class="retry"><a href="#" @click.prevent="init">我还要玩</a></div>
|
31 | 32 | </div>
|
| 33 | + <div v-if="viewBomb" class="layer-transparent"></div> |
| 34 | + |
32 | 35 | </div>
|
33 | 36 | </template>
|
34 | 37 | <script>
|
35 | 38 | import cell from './cell'
|
36 | 39 | import config from '../config'
|
37 | 40 | import Utils from '../utils'
|
38 | 41 | import VueDRR from 'vue-drag-resize-rotate'
|
| 42 | +
|
| 43 | + /* F**k IE */ |
| 44 | + const createRightClickEvent = (function () { |
| 45 | + return 'ActiveXObject' in window ? function () { |
| 46 | + let evt = document.createEvent('MouseEvent') |
| 47 | + evt.initMouseEvent('click', true, true, window, 0, 0, 0, 0, 0, false, false, false, false, 0, null) |
| 48 | + return evt |
| 49 | + } : function () { |
| 50 | + let evt = new MouseEvent('click', { |
| 51 | + button: 0, |
| 52 | + bubbles: true |
| 53 | + }) |
| 54 | + return evt |
| 55 | + } |
| 56 | + })() |
| 57 | +
|
39 | 58 | export default {
|
40 | 59 | name: 'game',
|
41 | 60 | components: {
|
|
48 | 67 | gameOver: false,
|
49 | 68 | cellData: [],
|
50 | 69 | showTips: false,
|
| 70 | + viewBomb: false, |
51 | 71 | width: 0,
|
52 | 72 | flagCount: 0,
|
53 | 73 | score: 0,
|
|
74 | 94 | this.bombSet.forEach(e => {
|
75 | 95 | let col = e % $this.config.col
|
76 | 96 | let row = ~~(e / $this.config.col)
|
77 |
| - console.log(col, row) |
78 | 97 | $this.cellData[row][col].isFlag = 1
|
79 | 98 | })
|
80 | 99 | this.$forceUpdate()
|
|
85 | 104 | }
|
86 | 105 | },
|
87 | 106 | methods: {
|
| 107 | + view () { |
| 108 | + this.gameOver = false |
| 109 | + this.viewBomb = true |
| 110 | + let $this = this |
| 111 | + this.bombSet.forEach(e => { |
| 112 | + let col = e % $this.config.col |
| 113 | + let row = ~~(e / $this.config.col) |
| 114 | + $this.cellData[row][col].status = 1 |
| 115 | + }) |
| 116 | + this.$forceUpdate() |
| 117 | + }, |
88 | 118 | init () {
|
89 | 119 | if ((~~this.inputCol) > this.config.maxCol || (~~this.inputRow) > this.config.maxRow) {
|
90 | 120 | this.tipsText = '请勿作死设置过大行列!'
|
|
106 | 136 | this.showTips = false
|
107 | 137 | this.success = false
|
108 | 138 | this.gameOver = false
|
| 139 | + this.viewBomb = false |
109 | 140 | this.score = 0
|
110 | 141 | this.flagCount = 0
|
111 | 142 | this.width = this.config.col * 41 + 1
|
|
160 | 191 | cell.isTriggered = true
|
161 | 192 | aroundCell.forEach(e => {
|
162 | 193 | if (e.isTriggered || e.isFlag || e.status === 1) return
|
163 |
| - let evt = new MouseEvent('mouseup', { |
164 |
| - button: 0, |
165 |
| - bubbles: true |
166 |
| - }) |
167 | 194 | // TODO: cell展开性能优化
|
| 195 | + let evt = createRightClickEvent() |
168 | 196 | nextTick(() => {
|
169 | 197 | table.rows[e.row].cells[e.col].dispatchEvent(evt)
|
170 | 198 | })
|
|
173 | 201 | this.$forceUpdate()
|
174 | 202 | }
|
175 | 203 | } else if (clickType === 2) {
|
176 |
| - if (!cell.isFlag) { |
177 |
| - this.flagCount++ |
178 |
| - cell.isFlag = true |
179 |
| - } else { |
180 |
| - this.flagCount-- |
181 |
| - cell.isFlag = false |
182 |
| - } |
183 |
| - this.$forceUpdate() |
184 | 204 | }
|
185 | 205 | },
|
186 |
| - handleRightClick () { |
| 206 | + handleRightClick (ev) { |
| 207 | + if (ev.target.nodeName !== 'TD') return |
| 208 | + let col = ev.target.cellIndex |
| 209 | + let row = ev.target.parentNode.rowIndex |
| 210 | + let cell = this.cellData[row][col] |
| 211 | + if (cell.status === 1) return |
| 212 | + if (!cell.isFlag) { |
| 213 | + this.flagCount++ |
| 214 | + cell.isFlag = true |
| 215 | + } else { |
| 216 | + this.flagCount-- |
| 217 | + cell.isFlag = false |
| 218 | + } |
| 219 | + this.$forceUpdate() |
| 220 | + }, |
| 221 | + handleDblClick (ev) { |
| 222 | + if (ev.target.nodeName !== 'TD') return |
| 223 | + let col = ev.target.cellIndex |
| 224 | + let row = ev.target.parentNode.rowIndex |
| 225 | + let cell = this.cellData[row][col] |
| 226 | + if (cell.status !== 1) return |
| 227 | + let table = this.$el.querySelector('table') |
| 228 | + let aroundCell = this.getAroundCell(row, col) |
| 229 | + let nextTick = this.$nextTick |
| 230 | + cell.isTriggered = true |
| 231 | + aroundCell.forEach(e => { |
| 232 | + if (e.isTriggered || e.isFlag || e.status === 1) return |
| 233 | + // TODO: cell展开性能优化 |
| 234 | + let evt = createRightClickEvent() |
| 235 | + nextTick(() => { |
| 236 | + table.rows[e.row].cells[e.col].dispatchEvent(evt) |
| 237 | + }) |
| 238 | + }) |
187 | 239 | },
|
188 | 240 | getAroundCell (row, col) {
|
189 | 241 | let rowArr = [row - 1, row, row + 1]
|
|
204 | 256 | <style scoped>
|
205 | 257 | .scoreboard.dragable{
|
206 | 258 | position: fixed;
|
207 |
| - z-index: 10; |
| 259 | + z-index: 99; |
208 | 260 | max-width: 180px;
|
209 | 261 | max-height: 180px;
|
210 | 262 | min-height: 180px;
|
|
238 | 290 | left: 0;
|
239 | 291 | right: 0;
|
240 | 292 | top: 0;
|
| 293 | + z-index: 100; |
241 | 294 | display: flex;
|
242 | 295 | align-items: center;
|
243 | 296 | justify-content: center;
|
|
279 | 332 | font-family: Arial, Microsoft Yahei;
|
280 | 333 | background-color: rgba(255, 255, 255, .7);
|
281 | 334 | }
|
| 335 | + .layer-transparent{ |
| 336 | + position: fixed; |
| 337 | + z-index: 90; |
| 338 | + top: 0; |
| 339 | + left: 0; |
| 340 | + right: 0; |
| 341 | + bottom: 0; |
| 342 | + } |
282 | 343 | .layer > div{
|
283 | 344 | width: 100%;
|
284 | 345 | }
|
|
313 | 374 | background-color: #ddd;
|
314 | 375 | cursor: pointer;
|
315 | 376 | }
|
| 377 | + .classic .bomb, .classic .flag{ |
| 378 | + color: #f36; |
| 379 | + font-size: 24px; |
| 380 | + font-family: FontAwesome; |
| 381 | + font-weight: normal; |
| 382 | + text-rendering: auto; |
| 383 | + -webkit-font-smoothing: antialiased; |
| 384 | + -moz-osx-font-smoothing: grayscale; |
| 385 | + } |
316 | 386 | .classic .flag{
|
317 | 387 | cursor: pointer;
|
318 | 388 | width: 30px;
|
319 | 389 | height: 30px;
|
320 |
| - font-size: 24px; |
321 |
| - color: #f36; |
322 | 390 | border-style: solid;
|
323 | 391 | border-width: 5px;
|
324 | 392 | border-color: #eee #aaa #aaa #eee;
|
325 | 393 | background-color: #ddd;
|
326 |
| - font-family: FontAwesome; |
327 |
| - font-weight: normal; |
328 |
| - text-rendering: auto; |
329 |
| - -webkit-font-smoothing: antialiased; |
330 |
| - -moz-osx-font-smoothing: grayscale; |
331 | 394 | }
|
332 | 395 | .classic .bomb{
|
333 |
| - font-size: 20px; |
334 | 396 | width: 38px;
|
335 | 397 | height: 38px;
|
336 | 398 | border: 1px solid #666;
|
337 | 399 | background-color: #ccc;
|
338 |
| - color: #f36; |
339 | 400 | cursor: default;
|
340 | 401 | }
|
341 | 402 | .classic [class^=bomb-count-]{
|
|
0 commit comments