I'm recreating the classic Tic Tac Toe using HTML, CSS, and JS.
I've got the game to run successfully for a single match but functionality seems to have some errors after creating a New Game option. After clicking new game, the winner message will pop up every time a player marks a square.
The game-checking algorithm is inside of the gameBoard variable and named checkWin. It's called inside of displayController after updating the view.
Pictures showing issue:
Working normally aside from winning message popping up before showing final X placement (bottom-left)
ISSUE: After clicking new-game, I click a single square and the winning message pops up.
let counter = 0;
let gameBoard = (function() {
// 'use strict';
let Board = ["", "", "", "", "", "", "", "", ""];
let winningCombinations = [
[0, 1, 2],
[3, 4, 5],
[6, 7, 8],
[0, 3, 6],
[1, 4, 7],
[2, 5, 8],
[0, 4, 8],
[2, 4, 6]
]
// has array
return {
Board: Board,
clickSquare: function(player) {
document.querySelectorAll('td').forEach(item => {
item.addEventListener('click', event => {
// console.log(item.id.replace('_',''));
player.markSquare(item.id.replace('_', ''));
})
});
},
checkWin: function() {
return winningCombinations.some(combination => {
return combination.every(index => {
return Board[index] === "X"
}) || combination.every(index => {
return Board[index] === "O"
})
})
}
}
})();
let displayController = (function() {
'use strict';
function updateView(square) {
console.log(square);
document.querySelector("#_" + square).textContent = gameBoard.Board[square];
if (gameBoard.checkWin() && counter % 2 === 0) {
alert("Player One Wins!");
} else if (gameBoard.checkWin() && counter % 2 !== 0) {
alert("Player Two Wins!");
} else if (counter == 8) {
alert("TIE!");
}
counter++;
}
return {
updateView: updateView
}
})();
function createPlayer(name) {
return {
name: name,
markSquare(square) {
if (gameBoard.Board[square] === "") {
if (counter % 2 === 0) {
gameBoard.Board[square] = "X";
} else {
gameBoard.Board[square] = "O";
}
displayController.updateView(square);
}
}
}
}
function gameFlow() {
let player1 = createPlayer("Phil");
gameBoard.clickSquare(player1);
let resetGame = document.querySelector("button");
resetGame.addEventListener('click', function() {
for (let i = 0; i <= 8; i++) {
document.querySelector("#_" + i).textContent = "";
}
gameBoard.Board = ["", "", "", "", "", "", "", "", ""];
counter = 0;
});
}
gameFlow();
body {
margin: 0;
font-family: 'Nunito', sans-serif;
}
h1 {
text-align: center;
}
#playerNames {
margin: auto;
align-items: center;
justify-content: center;
display: flex;
}
input {
width: 170px;
height: 40px;
font-size: 30px;
margin: 0 30px 0 30px;
}
button {
width: 100px;
height: 100px;
font-size: 30px;
border-radius: 50%;
background-color: yellow;
}
table {
margin: auto;
}
td {
width: 190px;
height: 190px;
text-align: center;
font-size: 100px;
}
tr td:nth-of-type(2) {
border-left: 2px solid black;
border-right: 2px solid black;
}
tr:nth-of-type(2) td {
border-top: 2px solid black;
border-bottom: 2px solid black;
}
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="TicTac.css">
<link href="https://fonts.googleapis.com/css2?family=Nunito&display=swap" rel="stylesheet">
</head>
<body>
<h1><b>Tic Tac Toe</b></h1>
<div id="playerNames">
<input id="pOne" placeholder="Player One" type="text">
<button>New Game</button>
<input id="pTwo" placeholder="Player Two" type="text">
</div>
<div>
<table>
<tr>
<td id="_0"></td>
<td id="_1"></td>
<td id="_2"></td>
</tr>
<tr>
<td id="_3"></td>
<td id="_4"></td>
<td id="_5"></td>
</tr>
<tr>
<td id="_6"></td>
<td id="_7"></td>
<td id="_8"></td>
</tr>
</table>
</div>
<script src="TicTac.js"></script>
</body>
</html>
winningCombinations
thing is just lazy. Surely, you can find a better way to check for a win. – ElectricShadow