Vue井字棋游戏
Sonder
2020-07-02
4401字
11分钟
浏览 (2.6k)
效果:
源码:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
body {
font: 14px "Century Gothic", Futura, sans-serif;
margin: 20px;
}
ol,
ul {
padding-left: 30px;
}
.board-row:after {
clear: both;
content: "";
display: table;
}
.status {
margin-bottom: 10px;
}
.square {
background: #fff;
border: 1px solid #999;
float: left;
font-size: 100px;
font-weight: 700;
line-height: 100px;
height: 100px;
margin-right: -1px;
margin-top: -1px;
padding: 0;
text-align: center;
width: 100px;
}
.square:focus {
outline: none;
}
.kbd-navigation .square:focus {
background: #ddd;
}
.game-info {
margin-top: 20px;
}
</style>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.6/vue.min.js"></script>
</head>
<body>
<div id="app">
<Game></Game>
</div>
<template id="tplSquare">
<button class="square" @click="$emit('click')">{{id}}</button>
</template>
<template id="tplBoard">
<div class="row">
<div class="board-row" v-for="row in [[0,1,2],[3,4,5],[6,7,8]]">
<Square v-for="i in row" :id="squares[i]" @click="$emit('click', i)" />
</div>
</div>
</template>
<template id="tplGame">
<div class="game">
<div class="game-board">
<Board @click="click" :squares="history[stepNumber].squares" />
</div>
<div class="game-info">
<div v-if="winner">Winner: {{winner}}</div>
<div v-if="!winner">Next player: {{xIsNext ? "X" : "O"}}</div>
<ol>
<li v-for="(h,move) in history">
<button @click="jumpTo(move)">{{move?"Go to move #"+move:"Go to game start"}}</button>
</li>
</ol>
</div>
</div>
</template>
<script>
Vue.component('Square', {
props: { id: null },
// template: `<button class="square" @click="$emit('click')">{{id}}</button>`,
template: "#tplSquare"
})
Vue.component('Board', {
props: { squares: [] },
template: "#tplBoard"
})
Vue.component('Game', {
data() {
return {
history: [{ squares: Array(9).fill(null) }],
stepNumber: 0,
xIsNext: true,
status: "",
winner: "",
}
},
methods: {
jumpTo(step) {
this.stepNumber = step
this.xIsNext = (step % 2) === 0
},
calculateWinner(squares) {
const lines = [
[0, 1, 2], [3, 4, 5], [6, 7, 8],
[0, 3, 6], [1, 4, 7], [2, 5, 8],
[0, 4, 8], [2, 4, 6],
];
for (let i = 0; i < lines.length; i++) {
const [a, b, c] = lines[i];
if (squares[a] && squares[a] === squares[b] && squares[a] === squares[c]) {
return squares[a];
}
}
return null;
},
click(id) {
const history = this.history.slice(0, this.stepNumber + 1)
const current = history[history.length - 1]
const squares = current.squares.slice()
this.winner = this.calculateWinner(squares)
if (this.winner || squares[id]) return
squares[id] = this.xIsNext ? "X" : "O"
this.history = history.concat([{ squares: squares }])
this.stepNumber = history.length
this.xIsNext = !this.xIsNext
this.winner = this.calculateWinner(squares)
}
},
template: "#tplGame"
})
new Vue({ el: '#app' })
</script>
</body>
</html>