📜  玩井字游戏 (1)

📅  最后修改于: 2023-12-03 14:56:14.324000             🧑  作者: Mango

玩井字游戏

简介

井字游戏是一种两人对弈的纸笔游戏。通常在一个 3×3 的正方形网格上进行。两人轮流在网格中打上自己的记号,一般来说先在横向、纵向或者对角线连成一条线的人获胜。

基本规则
  1. 游戏开始前,棋盘为空。
  2. 玩家轮流落子。
  3. 先在横向、纵向或者对角线连成一条线的人获胜。
  4. 若棋盘已满,双方平局。
开发思路
  1. 绘制游戏界面
  2. 每次轮到玩家落子时,获取落子坐标及玩家信息。
  3. 在棋盘上落子,并判断胜负及平局情况。
  4. 提示胜负情况,并询问是否继续游戏。
  5. 若继续游戏,则重置棋盘,继续轮流玩家落子。
编程实现
HTML结构
<div id="game">
   <div class="board">
      <div class="cell" data-row="0" data-col="0"></div>
      <div class="cell" data-row="0" data-col="1"></div>
      <div class="cell" data-row="0" data-col="2"></div>
      <div class="cell" data-row="1" data-col="0"></div>
      <div class="cell" data-row="1" data-col="1"></div>
      <div class="cell" data-row="1" data-col="2"></div>
      <div class="cell" data-row="2" data-col="0"></div>
      <div class="cell" data-row="2" data-col="1"></div>
      <div class="cell" data-row="2" data-col="2"></div>
   </div>
   <div class="status"></div>
   <button class="new-game">New Game</button>
</div>
CSS样式
#game {
  width: 300px;
  margin: auto;
  text-align: center;
}

.board {
  display: grid;
  grid-template-columns: 1fr 1fr 1fr;
  grid-template-rows: 1fr 1fr 1fr;
  width: 150px;
  height: 150px;
  margin: 20px auto;
  border: 2px solid black;
}

.cell {
  border: 1px solid black;
  width: 50px;
  height: 50px;
  box-sizing: border-box;
  cursor: pointer;
  background-color: #f5f5f5;
}

.cell:hover {
  background-color: #c3c3c3;
}

.status {
  margin-bottom: 20px;
  font-size: 24px;
}

.new-game {
  font-size: 16px;
  padding: 10px 30px;
  background-color: #4CAF50;
  border: none;
  color: white;
  cursor: pointer;
  border-radius: 5px;
}

.new-game:hover {
  background-color: #3e8e41;
}
JavaScript代码
const game = {
  board: [
    ['', '', ''],
    ['', '', ''],
    ['', '', '']
  ],
  players: ['X', 'O'],
  currentPlayer: '',
  init: function() {
    this.renderBoard()
    this.setupEventListener()
    this.startNewGame()
  },
  renderBoard: function() {
    const boardEl = document.querySelector('.board')
    let cellsHTML = ''
    for (let row = 0; row < this.board.length; row++) {
      for (let col = 0; col < this.board[row].length; col++) {
        cellsHTML += `<div class="cell" data-row="${row}" data-col="${col}"></div>`
      }
    }
    boardEl.innerHTML = cellsHTML
  },
  setupEventListener: function() {
    const cells = document.querySelectorAll('.cell')
    cells.forEach(cell => {
      cell.addEventListener('click', () => {
        const row = cell.dataset.row
        const col = cell.dataset.col
        if (this.board[row][col] === '') {
          this.board[row][col] = this.currentPlayer
          this.renderBoard()
          const winner = this.checkWinner()
          if (winner) {
            this.showStatus(`Player ${this.currentPlayer} won!`)
            this.endGame()
          } else if (this.isBoardFull()) {
            this.showStatus('Tie game!')
            this.endGame()
          } else {
            this.changeTurn()
          }
        }
      })
    })
    const newGameBtn = document.querySelector('.new-game')
    newGameBtn.addEventListener('click', () => {
      this.startNewGame()
    })
  },
  startNewGame: function() {
    this.currentPlayer = this.players[0]
    this.board = [
      ['', '', ''],
      ['', '', ''],
      ['', '', '']
    ]
    this.renderBoard()
    this.showStatus(`${this.currentPlayer} turn`)
  },
  changeTurn: function() {
    this.currentPlayer = this.currentPlayer === 'X' ? 'O' : 'X'
    this.showStatus(`${this.currentPlayer} turn`)
  },
  checkWinner: function() {
    const winningLines = [
      // rows
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      // columns
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      // diagonals
      [0, 4, 8],
      [2, 4, 6]
    ]
    for (let line of winningLines) {
      const [a, b, c] = line
      if (
        this.board[Math.floor(a / 3)][a % 3] === this.currentPlayer &&
        this.board[Math.floor(b / 3)][b % 3] === this.currentPlayer &&
        this.board[Math.floor(c / 3)][c % 3] === this.currentPlayer
      ) {
        return true
      }
    }
    return false
  },
  isBoardFull: function() {
    for (let row of this.board) {
      if (row.indexOf('') !== -1) return false
    }
    return true
  },
  showStatus: function(message) {
    const statusEl = document.querySelector('.status')
    statusEl.textContent = message
  },
  endGame: function() {
    const cells = document.querySelectorAll('.cell')
    cells.forEach(cell => {
      cell.style.cursor = 'default'
      cell.removeEventListener('click', () => {})
    })
  }
}

game.init()
Demo

运行上述代码即可在浏览器中玩井字游戏。