Commit e9cec6d

Ansari <ansari_official@yahoo.com>
2024-06-24 17:49:40
005
1 parent b51e795
005.MiniMax/index.html
@@ -21,6 +21,36 @@
             <h2>005.MiniMax</h2>
             <p class="modal__p">
             <ul>
+                <li>An unbeatable Tic-Tac-Toe game which uses the concept of
+                    <span style="color:var(--lightGold)">
+                        MiniMax Algorithm
+                    </span>
+                </li>
+                <li>
+                    It is a decision rule used for minimizing the possible loss for a
+                    <span style="color:var(--lightGold)">
+                        worst case scenario.
+                    </span>
+                </li>
+                <li>
+                    The algorithm considers
+                    <span style="color:var(--lightGold)">
+                        all possible moves
+                    </span>
+                    that can be made by the computer and human (optimal moves).
+                </li>
+                <li>
+                    Then it concludes the best move for the computer player by
+                    <span style="color:var(--lightGold)">
+                        minimizing the maximum loss.
+                    </span>
+                </li>
+                <li>
+                    Refer to
+                    <a href="https://en.wikipedia.org/wiki/Minimax" target="_blank" style="color:var(--lightGold)">
+                        MiniMax Algorithm
+                    </a>
+                </li>
             </ul>
             </p>
         </div>
@@ -30,6 +60,7 @@
     <h1>MiniMax</h1>
     <p id="tooltip"></p>
     <div class="grid">
+        <div id="strikeline" class="strike-line"></div>
         <div class="cell" data-value="1"></div>
         <div class="cell" data-value="2"></div>
         <div class="cell" data-value="3"></div>
005.MiniMax/script.js
@@ -1,6 +1,9 @@
 // Initial game state setup
 let currentPlayer = Math.random() < 0.5 ? "X" : "O";
 let isGameOver = false;
+let winningIndexes = [];
+let winningStrike = "";
+const tooltip = document.getElementById("tooltip");
 const GameState = {
     X: -10,
     O: 10,
@@ -25,6 +28,13 @@ function checkWinner(player) {
 
     // Check diagonals
     if (diag1_check || diag2_check) {
+        if (diag1_check) {
+            winningIndexes = [0, 4, 8];
+            winningStrike = "backward";
+        } else {
+            winningIndexes = [2, 4, 6];
+            winningStrike = "forward";
+        }
         return true;
     }
 
@@ -33,6 +43,13 @@ function checkWinner(player) {
         const rows_check = board[i].every(cell => cell === player);
         const cols_check = board.every(row => row[i] === player);
         if (rows_check || cols_check) {
+            if (rows_check) {
+                winningIndexes = [i * 3, i * 3 + 1, i * 3 + 2];
+                winningStrike = `vertical.row${i}`
+            } else {
+                winningIndexes = [i, i + 3, i + 6];
+                winningStrike = `horizontal.col${i}`
+            }
             return true;
         }
     }
@@ -105,7 +122,7 @@ function machinePlays() {
             if ((currentPlayer === "O" && score > bestScore) || (currentPlayer === "X" && score < bestScore)) {
                 bestScore = score;
                 bestMoves = [{ i, j }];
-            }else{
+            } else if (score === bestScore) {
                 bestMoves.push({ i, j });
             }
         }
@@ -123,11 +140,30 @@ function machinePlays() {
     }
 }
 
+function changeColorForWinnerIndexes(indexes) {
+    indexes.forEach(index => {
+        document.querySelector(`.cell[data-value="${index + 1}"]`).style.color = "var(--gold)";
+    });
+    winningStrike.split(".").forEach(cls => {
+        document.getElementById("strikeline").classList.add(cls);
+    });
+    console.log(winningStrike);
+}
+
 function checkGameOver() {
-    if (checkWinner(currentPlayer) || checkTie()) {
+    if (checkWinner(currentPlayer)) {
+        changeColorForWinnerIndexes(winningIndexes);
+        tooltip.textContent = `Press F5 to play again.`;
+        isGameOver = true;
+        return true;
+    }
+
+    if (checkTie()) {
+        tooltip.textContent = "It's a tie!.\nPress F5 to play again.";
         isGameOver = true;
+        return true;
     }
-    return isGameOver;
+    return false;
 }
 
 // User makes a move by clicking a cell
@@ -147,4 +183,10 @@ document.querySelectorAll(".cell").forEach(cell => {
 if (currentPlayer === "O") {
     console.log("AI starts the game!");
     machinePlays();
-}
\ No newline at end of file
+}
+
+document.addEventListener("keydown", event => {
+    if (event.key === "F5") {
+        window.location.reload();
+    }
+});
\ No newline at end of file
005.MiniMax/style.css
@@ -1,8 +1,9 @@
 .grid{
     display: grid;
+    position: relative;
     grid-template-columns: repeat(3, 1fr);
     grid-gap: 1px;
-    margin-top: 50px;
+    margin-top: 20px;
     height: 300px;
     width: 300px;
     background-color: white;
@@ -10,6 +11,7 @@
 }
 
 .cell{
+    position: relative;
     display: flex;
     justify-content: center;
     align-items: center;
@@ -20,5 +22,82 @@
 }
 
 #tooltip{
+    margin-top: 20px;
     color: var(--gold);
+}
+
+.strike-line{
+    position: absolute;
+    border: 3px solid var(--gold);
+    height: 100%;
+    background-color: var(--gold);
+    opacity: 0.5;
+    z-index: 1;
+    visibility: hidden;
+}
+
+.strike-line.horizontal, .strike-line.vertical, .strike-line.forward, .strike-line.backward{
+    animation: strike 0.5s ease;
+}
+
+.strike-line.horizontal{
+    rotate: 0deg;
+    margin-left: 47px;
+    visibility: visible;
+}
+
+.strike-line.horizontal.col0{
+    left: 0;
+}
+
+.strike-line.horizontal.col1{
+    left: 100px;
+}
+
+.strike-line.horizontal.col2{
+    left: 200px;
+}
+
+.strike-line.vertical{
+    rotate: 90deg;
+    margin-top: 50px;
+    left: 150px;
+    visibility: visible;
+}
+
+.strike-line.vertical.row0{
+    top: -150px;
+}
+
+.strike-line.vertical.row1{
+    top: -50px;
+}
+
+.strike-line.vertical.row2{
+    top: 50px;
+}
+
+.strike-line.forward{
+    height: 130%;
+    top: -50px;
+    left: 150px;
+    rotate: 45deg;
+    visibility: visible;
+}
+
+.strike-line.backward{
+    height: 130%;
+    top: -40px;
+    left: 150px;
+    rotate: -45deg;
+    visibility: visible;
+}
+
+@keyframes strike{
+    0%{
+        transform: scale(0);
+    }
+    100%{
+        transform: scale(1);
+    }
 }
\ No newline at end of file
index.html
@@ -14,7 +14,7 @@
 <body class="h-screen flex items-center justify-center bg-black flex flex-col font-black">
 
     <!-- Warning Modal Section  -->
-    <input class="modal-state" id="warning" type="checkbox"/>
+    <input class="modal-state" id="warning" type="checkbox" />
     <div class="modal">
         <div class="modal__inner">
             <h2 style="text-align: center;">101 - Warning</h2>
@@ -32,6 +32,7 @@
         <a href="./002.TOTP/" class="opacity-75 hover:opacity-100 hover:text-yellow-400">002.TOTP</a>
         <a href="./003.3n+1/" class="opacity-75 hover:opacity-100 hover:text-yellow-400">003.3n+1</a>
         <a href="./004.Maze-Runner/" class="opacity-75 hover:opacity-100 hover:text-yellow-400">004.Maze-Runner</a>
+        <a href="./005.MiniMax/" class="opacity-75 hover:opacity-100 hover:text-yellow-400">005.MiniMax</a>
     </div>
 </body>