Skip to content

Commit 655a76e

Browse files
committedMar 21, 2017
Added some feature
1.支持双击展开. 2.查看地雷位置. 3.增加输入验证
1 parent edb0979 commit 655a76e

13 files changed

+224
-49
lines changed
 

‎.babelrc

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"presets": [
3+
["env", { "modules": false }],
4+
"stage-2"
5+
],
6+
"plugins": ["transform-runtime"],
7+
"comments": false,
8+
"env": {
9+
"test": {
10+
"presets": ["env", "stage-2"],
11+
"plugins": [ "istanbul" ]
12+
}
13+
}
14+
}

‎.editorconfig

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
root = true
2+
3+
[*]
4+
charset = utf-8
5+
indent_style = space
6+
indent_size = 2
7+
end_of_line = lf
8+
insert_final_newline = true
9+
trim_trailing_whitespace = true

‎.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
build/*.js
2+
config/*.js

‎.eslintrc.js

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// http://eslint.org/docs/user-guide/configuring
2+
3+
module.exports = {
4+
root: true,
5+
parser: 'babel-eslint',
6+
parserOptions: {
7+
sourceType: 'module'
8+
},
9+
env: {
10+
browser: true,
11+
},
12+
// https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style
13+
extends: 'standard',
14+
// required to lint *.vue files
15+
plugins: [
16+
'html'
17+
],
18+
// add your custom rules here
19+
'rules': {
20+
// allow paren-less arrow functions
21+
'arrow-parens': 0,
22+
// allow async-await
23+
'generator-star-spacing': 0,
24+
// allow debugger during development
25+
'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0
26+
}
27+
}

‎.gitignore

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.DS_Store
2+
node_modules/
3+
dist/
4+
npm-debug.log
5+
yarn-error.log
6+
*.cmd

‎.postcssrc.js

+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
// https://github.com/michael-ciniawsky/postcss-load-config
2+
3+
module.exports = {
4+
"plugins": {
5+
// to edit target browsers: use "browserlist" field in package.json
6+
"autoprefixer": {}
7+
}
8+
}

‎README.md

+1-3
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
> A minesweeper game by vue 2.0
44
5-
<a href="http://woshiguabi.github.io/minesweeper/" target="_blank">Online Demo</a>
6-
75
## Build Setup
86

97
``` bash
@@ -15,4 +13,4 @@ npm run dev
1513

1614
# build for production with minification
1715
npm run build
18-
```
16+
```

‎config/index.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ module.exports = {
77
index: path.resolve(__dirname, '../dist/index.html'),
88
assetsRoot: path.resolve(__dirname, '../dist'),
99
assetsSubDirectory: 'static',
10-
assetsPublicPath: '/',
10+
assetsPublicPath: './',
1111
productionSourceMap: true,
1212
// Gzip off by default as many popular static hosts such as
1313
// Surge or Netlify already gzip all static assets for you.

‎src/components/cell.vue

+3-14
Original file line numberDiff line numberDiff line change
@@ -3,27 +3,16 @@
33
</template>
44
<script>
55
import Utils from '../utils'
6+
import config from '../config'
67
export default {
78
name: 'cell',
89
props: ['row', 'col', 'isBomb', 'status', 'isFlag', 'bombCount'],
910
computed: {
1011
display () {
11-
return Utils.getCellStatus({
12-
isFlag: '',
13-
status0: '',
14-
isBomb: '',
15-
bombCount: '',
16-
bombCount0: ''
17-
}, this)
12+
return Utils.getCellStatus(config.cellDisplayText, this)
1813
},
1914
className () {
20-
return Utils.getCellStatus({
21-
isFlag: 'flag fa-flag',
22-
status0: 'status0',
23-
isBomb: 'bomb',
24-
bombCount: 'bomb-count-',
25-
bombCount0: 'bomb-count-0'
26-
}, this)
15+
return Utils.getCellStatus(config.cellClassName, this)
2716
}
2817
}
2918
}

‎src/components/game.vue

+89-28
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
</vue-drr>
88
<div class="game-config">
99
<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>
1313
<button type="submit">生成</button>
1414
</form>
1515
<div v-if="showTips" class="game-config-tips">{{ tipsText }}</div>
1616
</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">
1818
<tr :key="row" v-for="(rows, row) in cellData">
1919
<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>
2020
</tr>
@@ -23,19 +23,38 @@
2323
<div>Game Over</div>
2424
<div>你美丽了!</div>
2525
<div class="retry"><a href="#" @click.prevent="init">再试一次</a></div>
26+
<div class="retry"><a href="#" @click.prevent="view">查看雷的位置</a></div>
2627
</div>
2728
<div v-if="success" class="success layer">
2829
<div>Win!</div>
2930
<div>你成功了!</div>
3031
<div class="retry"><a href="#" @click.prevent="init">我还要玩</a></div>
3132
</div>
33+
<div v-if="viewBomb" class="layer-transparent"></div>
34+
3235
</div>
3336
</template>
3437
<script>
3538
import cell from './cell'
3639
import config from '../config'
3740
import Utils from '../utils'
3841
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+
3958
export default {
4059
name: 'game',
4160
components: {
@@ -48,6 +67,7 @@
4867
gameOver: false,
4968
cellData: [],
5069
showTips: false,
70+
viewBomb: false,
5171
width: 0,
5272
flagCount: 0,
5373
score: 0,
@@ -74,7 +94,6 @@
7494
this.bombSet.forEach(e => {
7595
let col = e % $this.config.col
7696
let row = ~~(e / $this.config.col)
77-
console.log(col, row)
7897
$this.cellData[row][col].isFlag = 1
7998
})
8099
this.$forceUpdate()
@@ -85,6 +104,17 @@
85104
}
86105
},
87106
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+
},
88118
init () {
89119
if ((~~this.inputCol) > this.config.maxCol || (~~this.inputRow) > this.config.maxRow) {
90120
this.tipsText = '请勿作死设置过大行列!'
@@ -106,6 +136,7 @@
106136
this.showTips = false
107137
this.success = false
108138
this.gameOver = false
139+
this.viewBomb = false
109140
this.score = 0
110141
this.flagCount = 0
111142
this.width = this.config.col * 41 + 1
@@ -160,11 +191,8 @@
160191
cell.isTriggered = true
161192
aroundCell.forEach(e => {
162193
if (e.isTriggered || e.isFlag || e.status === 1) return
163-
let evt = new MouseEvent('mouseup', {
164-
button: 0,
165-
bubbles: true
166-
})
167194
// TODO: cell展开性能优化
195+
let evt = createRightClickEvent()
168196
nextTick(() => {
169197
table.rows[e.row].cells[e.col].dispatchEvent(evt)
170198
})
@@ -173,17 +201,41 @@
173201
this.$forceUpdate()
174202
}
175203
} 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()
184204
}
185205
},
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+
})
187239
},
188240
getAroundCell (row, col) {
189241
let rowArr = [row - 1, row, row + 1]
@@ -204,7 +256,7 @@
204256
<style scoped>
205257
.scoreboard.dragable{
206258
position: fixed;
207-
z-index: 10;
259+
z-index: 99;
208260
max-width: 180px;
209261
max-height: 180px;
210262
min-height: 180px;
@@ -238,6 +290,7 @@
238290
left: 0;
239291
right: 0;
240292
top: 0;
293+
z-index: 100;
241294
display: flex;
242295
align-items: center;
243296
justify-content: center;
@@ -279,6 +332,14 @@
279332
font-family: Arial, Microsoft Yahei;
280333
background-color: rgba(255, 255, 255, .7);
281334
}
335+
.layer-transparent{
336+
position: fixed;
337+
z-index: 90;
338+
top: 0;
339+
left: 0;
340+
right: 0;
341+
bottom: 0;
342+
}
282343
.layer > div{
283344
width: 100%;
284345
}
@@ -313,29 +374,29 @@
313374
background-color: #ddd;
314375
cursor: pointer;
315376
}
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+
}
316386
.classic .flag{
317387
cursor: pointer;
318388
width: 30px;
319389
height: 30px;
320-
font-size: 24px;
321-
color: #f36;
322390
border-style: solid;
323391
border-width: 5px;
324392
border-color: #eee #aaa #aaa #eee;
325393
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;
331394
}
332395
.classic .bomb{
333-
font-size: 20px;
334396
width: 38px;
335397
height: 38px;
336398
border: 1px solid #666;
337399
background-color: #ccc;
338-
color: #f36;
339400
cursor: default;
340401
}
341402
.classic [class^=bomb-count-]{

‎src/config.js

+15-1
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,19 @@ export default {
44
col: 20,
55
maxRow: 100,
66
maxCol: 100,
7-
theme: 'classic'
7+
theme: 'classic',
8+
cellClassName: {
9+
isFlag: 'flag fa-flag',
10+
status0: 'status0',
11+
isBomb: 'bomb fa-bomb',
12+
bombCount: 'bomb-count-',
13+
bombCount0: 'bomb-count-0'
14+
},
15+
cellDisplayText: {
16+
isFlag: '',
17+
status0: '',
18+
isBomb: '',
19+
bombCount: '',
20+
bombCount0: ''
21+
}
822
}

‎src/utils/index.js

+49-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,55 @@
11
const Utils = {}
2+
3+
/* Array.prototype.fill Polyfill By https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill */
4+
/* eslint-disable */
5+
if (!Array.prototype.fill) {
6+
Object.defineProperty(Array.prototype, 'fill', {
7+
value: function(value) {
8+
9+
// Steps 1-2.
10+
if (this == null) {
11+
throw new TypeError('this is null or not defined');
12+
}
13+
14+
var O = Object(this);
15+
16+
// Steps 3-5.
17+
var len = O.length >>> 0;
18+
19+
// Steps 6-7.
20+
var start = arguments[1];
21+
var relativeStart = start >> 0;
22+
23+
// Step 8.
24+
var k = relativeStart < 0 ?
25+
Math.max(len + relativeStart, 0) :
26+
Math.min(relativeStart, len);
27+
28+
// Steps 9-10.
29+
var end = arguments[2];
30+
var relativeEnd = end === undefined ?
31+
len : end >> 0;
32+
33+
// Step 11.
34+
var final = relativeEnd < 0 ?
35+
Math.max(len + relativeEnd, 0) :
36+
Math.min(relativeEnd, len);
37+
38+
// Step 12.
39+
while (k < final) {
40+
O[k] = value;
41+
k++;
42+
}
43+
44+
// Step 13.
45+
return O;
46+
}
47+
});
48+
}
49+
/* eslint-enable */
50+
251
Utils.randomBomb = function (bombCount, cellCount) {
352
console.time('random')
4-
console.log(bombCount, cellCount)
553
if (bombCount > cellCount) {
654
bombCount = cellCount
755
}
@@ -15,7 +63,6 @@ Utils.randomBomb = function (bombCount, cellCount) {
1563
return uniqueRandom()
1664
}
1765
})
18-
console.log(resultArr)
1966
let result = new Set()
2067
resultArr.forEach(e => result.add(e))
2168
console.timeEnd('random')

‎static/.gitkeep

Whitespace-only changes.

0 commit comments

Comments
 (0)
Please sign in to comment.