Javascript Object for Tic Tac Toe game

拜拜、爱过 提交于 2020-04-07 10:30:57

问题


Complete newbie here on the Javascript topic. I am trying to code out a Tic Tac Toe game, while using JS' Objects to save code space. I figured I might create a JS Object which will all 9 fields defined in the HTML code with ids 'one' to 'nine' as values, and then also have a custom method which can be used to swap value's textContent as follows:

var fields = {
    one: document.querySelector('#one'),
    two: document.querySelector('#two'),
    three: document.querySelector('#three'),
    four: document.querySelector('#four'),
    five: document.querySelector('#five'),
    six: document.querySelector('#six'),
    seven: document.querySelector('#seven'),
    eight: document.querySelector('#eight'),
    nine: document.querySelector('#nine'),
    swap: function(element) {
        if (this.element.textContent === "") {
            this.element.textContent = "X";
        } else if (this.element.textContent === "X") {
            this.element.textContent = "O";
        } else {
            this.element.textContent = "";
        }
    }
}

Then, I figured I would just add a bunch of addEventListeners like so:

fields['one'].addEventListener('click', fields.swap(fields['one']));

The thing is, I am probably totally treating this concept as it would operate in Python, and I am probably messing up the syntax here. Can anyone give me some ideas on where I am making an error?

The code copied above does not work at the moment.

HTML that it works with is as follows (I have omitted formatting here to save on space):

<body>
  <div class="container">
    <table id="gameboard">
      <tr class="row">
      <td id="one" class="gameField">X</td>
      <td id="two" class="gameField">X</td>
      <td id="three" class="gameField">X</td>
    </tr>
    <tr class="row">
      <td id="four" class="gameField">X</td>
      <td id="five" class="gameField">X</td>
      <td id="six" class="gameField">X</td>
    </tr>
    <tr class="row">
      <td id="seven" class="gameField">X</td>
      <td id="eight" class="gameField">X</td>
      <td id="nine" class="gameField">X</td>
    </tr>
  </table>
</div>


回答1:


Separate you swap function out of your object and just get rid of the object all together. Add a class to all of the HTMLElements you wish to add an EventListener to and then query them all using the following:

<div id="one" class="your-class"></div>
<div id="two" class="your-class"></div>

function swap(element) {
   if (element.textContent === ""){
      element.textContent = "X";
    }else if (element.textContent === "X") {
      element.textContent = "O";
    }else {
      element.textContent = "";
    }
}

document.querySelectorAll('.your-class').forEach(function (element) {
   element.addEventListener('click', swap(element));
});



回答2:


Tic-Tac-Vue!

Just add styles, sorry got carried away, maybe it's of some interest.

//
const board = [
  [1, 2, 3],
  [1, 2, 3],
  [1, 2, 3]
];

new Vue({
  el: '#app',
  data() {
    return {
      plays: 0,
      player: true,
      winner: '',
      board: JSON.parse(JSON.stringify(board))
    }
  },
  methods: {
    resetGame() {
      this.plays = 0
      this.winner = ''
      this.board = JSON.parse(JSON.stringify(board))
    },
    isBool(value) {
      return typeof(value) === typeof(true)
    },
    play(x, y) {
      if (!this.isBool(this.board[x][y]) && this.winner === '') {
        this.board[x][y] = this.player
        this.plays++
          this.checkWin(this.player)
        this.player = !this.player
      }
    },
    slot(x, y) {
      return {
        'fa-circle-o': this.isBool(this.board[x][y]) && this.board[x][y] === true,
        'fa-times': this.isBool(this.board[x][y]) && this.board[x][y] === false
      }
    },
    endGame(player) {
      this.winner = player
    },
    checkWin(player) {
      // check horizontal win
      for (var i = 0; i <= 2; i++) {
        if (this.board[i][0] === player &&
          this.board[i][1] === player &&
          this.board[i][2] === player) {
          this.endGame(player);
        }
      }
      // check vertical win
      for (var i = 0; i <= 2; i++) {
        if (this.board[0][i] === player &&
          this.board[1][i] === player &&
          this.board[2][i] === player) {
          this.endGame(player);
        }
      }
      // check diagonal win
      if ((this.board[0][0] === player &&
          this.board[1][1] === player &&
          this.board[2][2] === player) ||
        this.board[0][2] === player &&
        this.board[1][1] === player &&
        this.board[2][0] === player) {
        this.endGame(player);
      }
      if (this.plays === 9) {
        this.endGame(-1);
      }
    }
  }
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<style>
  table tr td {
    min-width: 20px;
    min-height: 20px;
    padding: 3px;
    text-align: center;
  }
</style>
<div id="app">

  <h3>Tic-Tac-Vue</h3>

  <p>It's player <i :class="['fa', {'fa-circle-o': player, 'fa-times': !player}]"></i>'s go!</p>

  <table border="1">
    <tr>
      <td @click="play(0,0)"><i :class="['fa', slot(0,0)]"></i></td>
      <td @click="play(0,1)"><i :class="['fa', slot(0,1)]"></i></td>
      <td @click="play(0,2)"><i :class="['fa', slot(0,2)]"></i></td>
    </tr>
    <tr>
      <td @click="play(1,0)"><i :class="['fa', slot(1,0)]"></i></td>
      <td @click="play(1,1)"><i :class="['fa', slot(1,1)]"></i></td>
      <td @click="play(1,2)"><i :class="['fa', slot(1,2)]"></i></td>
    </tr>
    <tr>
      <td @click="play(2,0)"><i :class="['fa', slot(2,0)]"></i></td>
      <td @click="play(2,1)"><i :class="['fa', slot(2,1)]"></i></td>
      <td @click="play(2,2)"><i :class="['fa', slot(2,2)]"></i></td>
    </tr>
  </table>

  <p v-if="winner === true || winner === false">Player <i :class="['fa', {'fa-circle-o': !player, 'fa-times': player}]"></i> is the winner!!</p>
  <p v-if="winner === -1">Game Over, Draw!!</p>
  <button @click="resetGame()">Reset Game</button>
</div>

See it working here: https://jsfiddle.net/7ktbphaf/




回答3:


So funny thing, I have solved this problem with bits of Jeremy Dejno's code, but had to adjust it. Taking into account the HTML code I posted in the first post, here's what worked for me:

function swap(){
    if (this.textContent === ""){
      this.textContent = "X";
    }else if (this.textContent === "X") {
      this.textContent = "O";
    }else {
      this.textContent = "";
    }
  }

document.querySelectorAll('.gameField').forEach(function(element){
    element.addEventListener('click',swap);
  })

Since this is a completely new thing for me (I am coming from a Python background), can someone tell me if I understand this correctly: After calling .addEventListener on every item with .gameField class, a swap function is called on every click event on any of them, and the swap function can be called without any arguments because THIS keyword makes it try to modify .textContent property of whatever object it is called on?



来源:https://stackoverflow.com/questions/52049591/javascript-object-for-tic-tac-toe-game

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!