Skip to content

Instantly share code, notes, and snippets.

@angeloreale
Last active December 24, 2019 08:42
Show Gist options
  • Save angeloreale/38a2ba136c487b83ae0d3833d197c677 to your computer and use it in GitHub Desktop.
Save angeloreale/38a2ba136c487b83ae0d3833d197c677 to your computer and use it in GitHub Desktop.
<template lang="pug">
.tictactoe
.board
.row(v-for="(row, y) in currentMatrix", :key="y")
button.cell(v-for="(cell, x) in row", :key="x", :position="x, y", @click="userPlays(x,y)", :disabled="end || currentMatrix[y][x] !== 0")="{{setIcon(x,y)}}"
.status="{{status}}"
button(v-if="end" @click="rebootGame")="Reboot"
</template>
<script>
export default {
name: 'app',
data: function () {
return {
currentMatrix: [[0, 0, 0], [0, 0, 0], [0, 0, 0]],
status: 'In progress',
end: false,
userIcon: 'x',
machineIcon: 'o'
}
},
methods: {
setIcon (x, y) {
return this.currentMatrix[y][x] === 0 ? '' : this.currentMatrix[y][x] === 1 ? this.userIcon : this.machineIcon
},
userPlays (myX, myY) {
if (this.currentMatrix[myY][myX] === 0) {
this.$set(this.currentMatrix[myY], myX, 1)
}
this.hasAnyPlayerWon(myX, myY)
if (!this.end) {
this.computerPlays()
}
},
computerPlays () {
let isWinning = this.isUserAboutToWin()
if (isWinning && isWinning.isWinning) {
let computerX = isWinning.positionToWatch[0]
let computerY = isWinning.positionToWatch[1]
if (!this.end) {
this.$set(this.currentMatrix[computerY], computerX, 2)
}
this.hasAnyPlayerWon(computerX, computerY)
} else {
let computerX = Math.floor(Math.random() * 3)
let computerY = Math.floor(Math.random() * 3)
while (this.currentMatrix[computerY][computerX] !== 0) {
computerX = Math.floor(Math.random() * 3)
computerY = Math.floor(Math.random() * 3)
}
this.hasAnyPlayerWon(computerX, computerY)
if (!this.end) {
this.$set(this.currentMatrix[computerY], computerX, 2)
}
}
},
hasAnyPlayerWon (thisx, thisy) {
// verify row victory
if (this.currentMatrix[thisy].filter(el => el === 1).length === 3) {
this.endGame('1')
return true
} else if (this.currentMatrix[thisy].filter(el => el === 2).length === 3) {
this.endGame('2')
return true
}
// verify column victory
if (this.currentMatrix.filter(el => el[thisx] === 1).length === 3) {
this.endGame('1')
return true
} else if (this.currentMatrix.filter(el => el[thisx] === 2).length === 3) {
this.endGame('2')
return true
}
// verify diagonal victory
let diagonals = [[{ position: [0, 0], value: this.currentMatrix[0][0] },
{ position: [1, 1], value: this.currentMatrix[1][1] },
{ position: [2, 2], value: this.currentMatrix[2][2] }],
[{ position: [0, 2], value: this.currentMatrix[0][2] },
{ position: [1, 1], value: this.currentMatrix[1][1] },
{ position: [2, 0], value: this.currentMatrix[2][0] }]]
for (let i = 0; i < diagonals.length; i++) {
for (let j = 0; j < diagonals[i].length; j++) {
if (diagonals[i].filter(el => el.value === 1).length === 3) {
this.endGame('1')
return true
} else if (diagonals[i].filter(el => el.value === 2).length === 3) {
this.endGame('2')
return true
}
}
}
// verify draw
for (let k = 0; k < this.currentMatrix.length; k++) {
for (let g = 0; g < this.currentMatrix[k].length; g++) {
if (this.currentMatrix[k][g] === 0) {
return true
}
}
if (k === this.currentMatrix.length - 1) {
this.endGame('3')
return false
}
}
return false
},
isUserAboutToWin () {
let newPosition = {}
for (let y = 0; y < this.currentMatrix.length; y++) {
for (let x = 0; x < this.currentMatrix[y].length; x++) {
if (!newPosition.isWinning) {
var position = -1
}
// verify row
if (this.currentMatrix[y][x] === 1 &&
(this.currentMatrix[y].filter(el => el === 1).length > 1) &&
(this.currentMatrix[y].indexOf(0) !== -1)) {
position = this.currentMatrix[y].findIndex(el => el === 0)
return { isWinning: true, positionToWatch: [position, y] }
}
// verify column
if (this.currentMatrix[y][x] === 1 &&
(this.currentMatrix.filter(el => el[x] === 1).length > 1) &&
(this.currentMatrix.findIndex(el => el[x] === 0) !== -1)) {
position = this.currentMatrix.findIndex(el => el[x] === 0)
return { isWinning: true, positionToWatch: [x, position] }
}
// verify diagonal
let diagonals = [[{ position: [0, 0], value: this.currentMatrix[0][0] },
{ position: [1, 1], value: this.currentMatrix[1][1] },
{ position: [2, 2], value: this.currentMatrix[2][2] }],
[{ position: [0, 2], value: this.currentMatrix[0][2] },
{ position: [1, 1], value: this.currentMatrix[1][1] },
{ position: [2, 0], value: this.currentMatrix[2][0] }]]
for (let i = 0; i < diagonals.length; i++) {
for (let j = 0; j < diagonals[i].length; j++) {
if (this.currentMatrix[y][x] === 1 &&
(diagonals[i].filter(el => el.value === 1).length > 1) &&
(diagonals[i].findIndex(el => el.value === 0) !== -1)) {
let positionArr = diagonals[i].filter(el => el.value === 0)[0].position.reverse()
return { isWinning: true, positionToWatch: positionArr }
}
}
}
}
}
},
endGame (whoWon) {
this.end = true
switch (whoWon) {
case '1': {
this.status = 'You won! :)'
break
}
case '2': {
this.status = 'Machine won! :('
break
}
case '3': {
this.status = "It's a draw!"
break
}
}
},
rebootGame () {
this.end = false
this.status = 'In progress'
this.currentMatrix = [[0, 0, 0], [0, 0, 0], [0, 0, 0]]
}
}
}
</script>
<style lang="scss">
.tictactoe {
max-width: 300px;
display: flex;
justify-content: center;
align-items: center;
margin: 0 auto;
height: 100vh;
flex-direction: column;
.board {
.row {
padding: 1em 0;
border-bottom: solid 1px black;
width: fit-content;
&:last-of-type {
border: none;
}
.cell {
margin: 0 1em;
width: 2em;
height: 2em;
border-right: solid 1px black;
position: relative;
font-size: 1em;
&:active, &:focus {
border: none;
outline: none;
}
&:after {
content: "";
width: 1px;
height: 67px;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
position: absolute;
top: -20px;
background: black;
left: 45px;
}
&:last-of-type {
&:after {
visibility: hidden;
}
}
}
}
}
.status {
margin-top: 2em;
border-top: solid 1px green;
color: green;
width: 100%;
text-align: center;
padding: 1em;
}
}
</style>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment