Skip to content

Instantly share code, notes, and snippets.

@matiasmicheletto
Created January 5, 2023 20:45
Show Gist options
  • Save matiasmicheletto/f64bfb3d9e9cd18171856930557e16bf to your computer and use it in GitHub Desktop.
Save matiasmicheletto/f64bfb3d9e9cd18171856930557e16bf to your computer and use it in GitHub Desktop.
Minimalist tic tac toe game in JS
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Tic Tac Toe</title>
<meta name="description" content="Tic Tac Toe game">
<meta name="author" content="Matias Micheletto">
</head>
<body>
<style>
#game {
margin: 0 auto;
}
#reset {
position: absolute;
left: 50%;
-ms-transform: translate(-50%, 50%);
transform: translate(-50%, 50%);
}
.cell {
border: 1px solid black;
width: 100px;
height: 100px;
text-align: center;
text-transform: uppercase;
font-family: Arial, Helvetica, sans-serif;
}
</style>
<table id="game"></table>
<button id="reset" onclick="startGame()">Reiniciar!</button>
<script type="text/javascript">
class GameLogic {
constructor() {
this.board = [
['', '', ''],
['', '', ''],
['', '', '']
];
this.lastMove = '';
this.running = true;
this.moveCounter = 0;
}
_didWin(p){
let cCounter, d1Counter = 0, d2Counter = 0;
for(let row = 0; row < 3; row++){
// All row equal
if(this.board[row].every(el => el === p)){
return true;
}
// All column equal
cCounter = 0;
for(let col = 0; col < 3; col++){
if(this.board[col][row] === p)
cCounter++;
}
if(cCounter === 3){
return true;
}
// Diagonal 1 equal
if(this.board[row][row] === p){
d1Counter++
}
// Diagonal 2 equal
if(this.board[row][2-row] === p){
d2Counter++
}
}
if(d1Counter === 3 || d2Counter === 3){
return true;
}
return false;
}
onMove(x, y, p) {
if(!this.running){
return {
success: false,
message: "Game ended!"
};
}
if(this.board[x][y] === ''){
if(p){
if(this.lastMove !== p){
this.board[x][y] = p;
this.lastMove = p;
}else{
return {
success: false,
message: "Same player!"
};
}
}else{
this.lastMove = this.lastMove === "x" ? "o" : "x";
this.board[x][y] = this.lastMove;
}
}else{
return {
success: false,
message: "Cell already in use!"
}
}
this.moveCounter++;
if(this._didWin(this.lastMove)){
this.running = false;
return {
success: true,
cellValue: this.lastMove,
winner: true
}
}
if(this.moveCounter === 9){
this.running = false;
return {
success: true,
cellValue: this.lastMove,
tie: true
}
}
return {
success: true,
cellValue: this.lastMove
}
}
}
class TicTacToeGame{
constructor(elementId) {
const gl = new GameLogic();
const board = document.getElementById(elementId);
board.innerHTML = "";
for(let row = 0; row < 3; row++){
const tr = document.createElement("tr");
for(let col = 0; col < 3; col++){
const td = document.createElement("td");
td.className = "cell";
td.id = `${row}-${col}`;
td.onclick = () => {
const result = gl.onMove(row, col);
if(result.success){
td.innerHTML = result.cellValue;
if(result.winner){
setTimeout(() => {
console.log(result.cellValue + " wins!");
window.alert(result.cellValue + " wins!");
}, 100);
}
if(result.tie){
setTimeout(() => {
console.log("Tie!");
window.alert("Tie!");
}, 100);
}
}else{
console.warn(result.message);
window.alert(result.message);
}
}
tr.appendChild(td);
}
board.appendChild(tr);
}
}
}
const startGame = () => {
const game = new TicTacToeGame("game");
}
startGame();
</script>
</body>
</html>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment