首页
归档
笔记
树洞
搜索
友言

文章详情

Interesting People Record Interesting.

/ JavaScript / 文章详情

Vue井字棋游戏

Sonder
2020-07-02
4401字
11分钟
浏览 (2.6k)

效果:

1.gif

源码:

复制代码
<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>
下一篇 / 前端面试题(包含答案)

🎯 相关文章

💡 推荐文章

🕵️‍♂️ 评论 (0)