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
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/
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?
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));
});