diff --git a/README.md b/README.md index 26ba3f0..58ad916 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ # TicTacToe -A basic TicTacToe game. +A basic TicTacToe game, 2 players or against an impossible to win against AI. ## Technologies @@ -13,10 +13,12 @@ For the CSS, I am using Sass because it extends the functionalities and capabili ## Algorithms -Loops to check which player won +MiniMax to make the AI choose which move will it choose. + +Loops to check which player won. --- ### What comes now? -I wanna change the look and make the win button become a pop-up +Better UI diff --git a/index.html b/index.html index cc15808..dd94ae6 100644 --- a/index.html +++ b/index.html @@ -8,7 +8,18 @@
- +
+

TicTacToe

+ + +
+
+

Difficulity

+ + + + +
@@ -20,6 +31,7 @@
+
diff --git a/src/index.js b/src/index.js index 20bbf9a..d6763a0 100644 --- a/src/index.js +++ b/src/index.js @@ -1,19 +1,88 @@ import "./style.scss"; +let level; let COOP = false; let aiFirst = false; +let board = [ + ["", "", ""], + ["", "", ""], + ["", "", ""], +]; + +const levels = { + easy: 1, + medium: 3, + hard: 6, + impossible: 9, +}; + let player = true; let HUMAN = player ? "X" : "O"; let AI = player ? "O" : "X"; const buttons = document.querySelectorAll(".btn"); const end = document.querySelector("#end"); +const grid = document.querySelector(".board"); +const start = document.querySelector(".start"); +const choice = document.querySelector(".choice"); -let board = [ - ["", "", ""], - ["", "", ""], - ["", "", ""], -]; +const single = document.querySelector("#single"); +const multi = document.querySelector("#coop"); + +single.addEventListener("click", () => { + COOP = false; + start.setAttribute("style", "display:none"); + choice.setAttribute("style", "display: grid"); +}); +const easyBtn = document.querySelector("#easy"); +easyBtn.addEventListener("click", () => { + choice.setAttribute("style", "display:none"); + grid.setAttribute("style", "display: grid"); + level = levels.easy; +}); + +const mediumBtn = document.querySelector("#medium"); +mediumBtn.addEventListener("click", () => { + choice.setAttribute("style", "display:none"); + grid.setAttribute("style", "display: grid"); + level = levels.medium; +}); + +const hardBtn = document.querySelector("#hard"); +hardBtn.addEventListener("click", () => { + choice.setAttribute("style", "display:none"); + grid.setAttribute("style", "display: grid"); + level = levels.hard; +}); + +const impossibleBtn = document.querySelector("#impossible"); +impossibleBtn.addEventListener("click", () => { + choice.setAttribute("style", "display:none"); + grid.setAttribute("style", "display: grid"); + level = levels.impossible; +}); + +multi.addEventListener("click", () => { + COOP = true; + start.setAttribute("style", "display:none"); + grid.setAttribute("style", "display: grid"); +}); + +end.addEventListener("click", () => { + board = [ + ["", "", ""], + ["", "", ""], + ["", "", ""], + ]; + buttons.forEach((button) => { + button.innerHTML = ""; + button.disabled = false; + }); + grid.setAttribute("style", "display: none"); + start.setAttribute("style", "display:grid"); + end.setAttribute("style", "display: none"); + end.innerHTML = ""; +}); function emptyPlaces(state) { let places = []; @@ -57,6 +126,16 @@ buttons.forEach((button) => { drawOnBoard(); if (gameOverAll(board)) { disableAll(); + if (evaluate(board) > 0) { + end.innerHTML = `${HUMAN} WON`; + } else { + end.innerHTML = `${AI} WON`; + } + end.setAttribute("style", "display:grid"); + } + if (emptyPlaces(board).length == 0) { + end.setAttribute("style", "display:grid"); + end.innerHTML = "DRAW"; } }); }); @@ -139,7 +218,11 @@ function aiTurn() { x = Math.trunc(Math.random() * 3); y = Math.trunc(Math.random() * 3); } else { - move = minimax(board, emptyPlaces(board).length, AI); + let depth = emptyPlaces(board).length; + if (depth > level) { + depth = level; + } + move = minimax(board, depth, AI); x = move[0]; y = move[1]; } diff --git a/src/style.scss b/src/style.scss index 7d39ea7..ad0a6b0 100644 --- a/src/style.scss +++ b/src/style.scss @@ -14,8 +14,7 @@ main { align-items: center; } .board { - position: relative; - display: grid; + display: none; grid-template-columns: repeat(3, 1fr); aspect-ratio: 1/1; .btn { @@ -25,7 +24,33 @@ main { } } +.start { + display: grid; + place-items: center; + gap: 1rem; + grid-template-columns: repeat(2, 1fr); +} +.start h1 { + grid-column: span 2; +} +.start button { + padding: 1rem; +} +.choice { + display: none; + grid-template-columns: repeat(4, 1fr); + gap: 1rem; + place-items: center; +} +.choice h2 { + grid-column: span 4; +} +.choice button { + padding: 1em; +} + #end { + display: none; padding: 1rem; font-size: clamp(16px, 5vmin, 100vw); }