How to add minimax algorithm to my tic tac toe game in js?

56 Views Asked by At

having issues implementing minimax code, the other codes I came across seemed hard to grasp, can someone tell me how to integrate algorithm into my app? I tried creating board for empty spaces define human/computer function, run the code on the turn fun, but yeah I created a hot mess, and used my git log to rewind, heres my code

I low key feel the issue lies in the structure of my app manifested in the lack of board variable, emptyspaces functions, minimax logic , or in the way I am integrating my logic with my other functions ,

const x_class = "x";
const circle_class = "circle";
const cellElement = document.querySelectorAll("[data-cell]");
const winningMessageElement = document.getElementById("winningMessage");
const winningCombination = [
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6],
];
const board = document.getElementById("board");
let circleTurn;
const winningTextMessageElement = document.querySelector(
  "[data-winning-message-text]"
);

const reStartButton = document.getElementById("restartButton");
const optionX = document.getElementById("optionx");
const optionO = document.getElementById("optiono");
const submitBtn = document.getElementById("submitButton");
const selection_X = document.getElementById("xOption");
const selection_O = document.getElementById("oOption");
const startForm = document.getElementById("startForm");

optionX.addEventListener("click", optionHandler);
optionO.addEventListener("click", optionHandler);
submitBtn.addEventListener("click", submitHandler);
reStartButton.addEventListener("click", startGame);

function optionHandler(e) {
  optionX.classList.remove("optionButtonStyle2");
  optionX.classList.add("optionButtonStyle");
  optionO.classList.remove("optionButtonStyle2");
  optionO.classList.add("optionButtonStyle");
  e.currentTarget.classList.remove("optionButtonStyle");
  e.currentTarget.classList.add("optionButtonStyle2");
}

function submitHandler(e) {
  e.preventDefault();
  if (selection_O.checked) {
    circleTurn = true;
    startForm.classList.add("hide");
    board.classList.add("show");
  } else if (selection_X.checked) {
    circleTurn = false;
    startForm.classList.add("hide");
    board.classList.add("show");
  } else {
    alert("please select an option");
  }
  startGame();
}

function startGame() {
  cellElement.forEach((cell) => {
    cell.classList.remove(x_class);
    cell.classList.remove(circle_class);
    cell.removeEventListener("click", handleClick);
    cell.addEventListener("click", handleClick, { once: true });
  });
  setBoardHoverClass();

  winningMessageElement.classList.remove("show");
}

function handleClick(e) {
  const cell = e.target;
  const currentClass = circleTurn ? circle_class : x_class;
  placeMark(cell, currentClass);
  if (checkWin(currentClass)) {
    endGame(false);
  } else if (isDraw()) {
    endGame(true);
  } else {
    swapTurns();
    setBoardHoverClass();
  }
}
function isDraw() {
  return [...cellElement].every((cell) => {
    return (
      cell.classList.contains(x_class) || cell.classList.contains(circle_class)
    );
  });
}

function endGame(draw) {
  if (draw) {
    winningTextMessageElement.innerText = "Tie!";
  } else {
    winningTextMessageElement.innerText = `${circleTurn ? "O's" : "X's"} Win!`;
  }
  winningMessageElement.classList.add("show");
}

function placeMark(cell, currentClass) {
  cell.classList.add(currentClass);
}

function swapTurns() {
  circleTurn = !circleTurn;
}

function setBoardHoverClass() {
  board.classList.remove(x_class);
  board.classList.remove(circle_class);
  if (circleTurn) {
    board.classList.add(circle_class);
  } else {
    board.classList.add(x_class);
  }
}

function checkWin(currentClass) {
  return winningCombination.some((combination) => {
    return combination.every((index) => {
      return cellElement[index].classList.contains(currentClass);
    });
  });
}
*,
*::after,
*::before {
  box-sizing: border-box;
}

:root {
  --cell-size: 100px;
  --mark-size: calc(var(--cell-size) * 0.9);
}

body {
  margin: 0;
}

.formStyle {
  background-color: rgb(236, 226, 221);
  max-width: 30%;
  min-height: 50vh;
}

.hide {
  display: none;
}

.headerStyle {
  color: #10213b !important;
}

.optionButtonStyle {
  background-color: #10213b !important;
  padding: 10px 70px !important;
  color: white !important;
}

.optionButtonStyle:hover {
  background-color: #183867 !important;
}
.submitButton {
  background-color: #10213b !important;
  padding: 10px 30px !important;
}

.submitButton:hover {
  background-color: #183867 !important;
  padding: 10px 30px !important;
}

.optionButtonStyle2 {
  background-color: orange !important;
  padding: 10px 70px !important;
  color: #183867 !important;
  font-weight: 400 !important;
}

.boardStyle {
  background-image: linear-gradient(rgba(0, 0, 0, 0.7), rgba(0, 0, 0, 0.7)),
    url("image/tic-tac-toe_1706536926613.jpg");

  max-width: 100%;
  height: 100vh;
  background-size: cover;
  background-position: top left;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.board {
  display: /*grid;*/ none;
  justify-content: center;
  align-content: center;
  justify-items: center;
  align-items: center;
  grid-template-columns: repeat(3, auto);
}
.show {
  display: grid;
}

.cell {
  position: relative;
  min-width: var(--cell-size);
  height: var(--cell-size);
  border: 1px solid white;
  display: flex;
  justify-content: center;
  align-items: center;
  cursor: pointer;
}

.cell:first-child,
.cell:nth-child(2),
.cell:nth-child(3) {
  border-top: none;
}

.cell:first-child,
.cell:nth-child(4),
.cell:nth-child(7) {
  border-left: none;
}

.cell:nth-child(3),
.cell:nth-child(6),
.cell:nth-child(9) {
  border-right: none;
}
.cell:nth-child(7),
.cell:nth-child(8),
.cell:nth-child(9) {
  border-bottom: none;
}

.cell.x::before,
.cell.x::after,
.cell.circle::before,
.cell.circle::after {
  background-color: pink;
}

.board.x .cell:not(.x):not(.circle):hover::before,
.board.x .cell:not(.x):not(.circle):hover::after,
.board.circle .cell:not(.x):not(.circle):hover::before,
.board.circle .cell:not(.x):not(.circle):hover::after {
  background-color: pink;
}

.cell.x::before,
.cell.x::after,
.board.x .cell:not(.x):not(.circle):hover::before,
.board.x .cell:not(.x):not(.circle):hover::after {
  content: "";
  position: absolute;
  width: calc(var(--mark-size) * 0.15);
  height: var(--mark-size);
}

.cell.x::before,
.board.x .cell:hover::before {
  transform: rotate(45deg);
}
.cell.x::after,
.board.x .cell:hover::after {
  transform: rotate(-45deg);
}

.cell.circle::before,
.cell.circle::after,
.cell:not(.x):not(.circle):hover::before,
.cell:not(.x):not(.circle):hover::after {
  content: "";
  position: absolute;
  width: var(--mark-size);
  height: var(--mark-size);
  border-radius: 50%;
}

.cell.circle::before,
.board.circle .cell:not(.x):not(.circle):hover::before {
  width: var(--mark-size);
  height: var(--mark-size);
}
.cell.circle::after,
.board.circle .cell:not(.x):not(.circle):hover::after {
  width: calc(var(--mark-size) * 0.7);
  height: calc(var(--mark-size) * 0.7);
  background-color: /*white; #122b31;*/ #060f1d;
}

.cell.x,
.cell.circle {
  cursor: not-allowed;
}

.winning-message {
  display: none;
  position: fixed;
  top: 0;
  bottom: 0;
  right: 0;
  left: 0;
  background-color: rgba(0, 0, 0, 0.9);
  flex-direction: column;
  justify-content: center;
  align-items: center;
  color: pink;
  font-size: 5rem;
  margin: 0;
}

.winning-message button {
  font-size: 3rem;
  background-color: orange;
  border: 1px solid black;
  padding: 10px 70px; /* Combine the padding values into a single declaration */
  cursor: pointer;
  color: #081425;
}

.winning-message button:hover {
  background-color: #081425;
  color: pink;
  border-color: white;
  transition: background-color 0.2s ease-in, color 0.2s ease-in,
    border-color 0.3s ease-in;
}

.winning-message.show {
  display: flex;
}

@media screen and (min-width: 900px) and (max-width: 1379px) {
  .formStyle {
    background-color: rgb(236, 226, 221);
    max-width: 50%;
    min-height: 45vh;
  }

  .submitButton {
    background-color: #10213b !important;
    margin-bottom: 10px;
    padding-top: 10px;
  }

  .optionButtonStyle {
    margin-bottom: 10px;
  }
  .optionButtonStyle2 {
    margin-bottom: 10px;
  }
}

@media screen and (min-width: 500px) and (max-width: 899px) {
  .formStyle {
    background-color: rgb(236, 226, 221);
    max-width: 80%;
    min-height: 45vh;
    overflow: none;
  }

  .submitButton {
    background-color: #10213b !important;
    margin-bottom: 10px;
    padding-top: 10px;
  }

  .optionButtonStyle {
    margin-bottom: 10px;
  }
  .optionButtonStyle2 {
    margin-bottom: 10px;
  }
}

@media screen and (max-width: 499px) {
  .formStyle {
    background-color: rgb(236, 226, 221);
    max-width: 90%;
    min-height: 45vh;
  }

  .submitButton {
    background-color: #10213b !important;
    margin-bottom: 10px;
    padding-top: 10px;
    overflow: none;
  }

  .optionButtonStyle {
    margin-bottom: 10px;
    overflow: none;
  }
  .optionButtonStyle2 {
    margin-bottom: 10px;
    overflow: none;
  }

  :root {
    --cell-size: 60px;
    --mark-size: calc(var(--cell-size) * 0.9);
  }
  .winning-message {
    display: none;
    position: fixed;
    top: 0;
    bottom: 0;
    right: 0;
    left: 0;
    background-color: rgba(0, 0, 0, 0.9);
    flex-direction: column;
    justify-content: center;
    align-items: center;
    color: pink;
    font-size: 2rem;
    margin: 0;
  }

  .winning-message button {
    font-size: 1rem;
    background-color: orange;
    border: 1px solid black;
    padding: 10px 70px; /* Combine the padding values into a single declaration */
    cursor: pointer;
    color: #081425;
  }
}
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Tic Tac Toe</title>
    <link rel="stylesheet" href="style.css" />
    <script defer src="main.js"></script>
    <link
      href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css"
      rel="stylesheet"
      integrity="sha384-T3c6CoIi6uLrA9TneNEoa7RxnatzjcDSCmG1MXxSR1GAsXEV/Dwwykc2MPK8M2HN"
      crossorigin="anonymous"
    />
  </head>
  <body>
    <div class="boardStyle container-fluid">
      <div class="formStyle" id="startForm">
        <h1 class="text-center display-1 fw-medium headerStyle">Tic Tac Toe</h1>
        <form action="" class="text-center">
          <h2 class="text-center my-4 headerStyle">Choose a Symbol:</h2>
          <div class="mt-4">
            <label
              class="btn rounded-0 btn-lg optionButtonStyle mx-3"
              id="optionx"
            >
              <input
                type="radio"
                name="option"
                id="xOption"
                value="x"
                class="visually-hidden"
              />
              <span class="fw-medium display-6">X</span>
            </label>
            <label
              class="btn rounded-0 btn-lg optionButtonStyle mx-3"
              id="optiono"
            >
              <input
                type="radio"
                name="option"
                id="oOption"
                value="o"
                class="visually-hidden"
              />
              <span class="fw-medium display-6">O</span>
            </label>
          </div>
          <button
            class="btn btn-lg text-center rounded-0 text-white submitButton mt-5"
            id="submitButton"
          >
            Start Game
          </button>
        </form>
      </div>

      <div class="board" id="board">
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
        <div class="cell" data-cell></div>
      </div>
      <div class="winning-message" id="winningMessage">
        <div data-winning-message-text></div>
        <button class="btn btn-lg rounded-0" id="restartButton">Restart</button>
      </div>
    </div>

    <script
      src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js"
      integrity="sha384-C6RzsynM9kWDrMNeT87bh95OGNyZPhcTNXj1NW7RuBCsyN/o0jlpcV8Qyq46cDfL"
      crossorigin="anonymous"
    ></script>
  </body>
</html>

0

There are 0 best solutions below