Search code examples
javascripthoveraddeventlistenertic-tac-toe

In my tic tac toe, I want Event Listener on box to change color on hover only when game is not over


I used hover on element box that i did by (event listener "mouse enter and mouse leave") that changes color on mouse enter and changes back to normal when mouse leave(red when x turn and blue when o turn) only when game is not over.But my script changes the colors on hover even when the game is over and i dont want that.

Here is my code:

// The if statement if (boxes[a].innerText) checks if the innerText property of the DOM element at index a in the boxes array is truthy. If it is truthy, then the condition in the if statement will be evaluated as true and the code inside the if block will be executed.

// The innerText property of a DOM element is a string that represents the text content of the element. If the element has no text content, the innerText property will be an empty string. An empty string is considered a falsy value in JavaScript, so the condition if (boxes[a].innerText) will be evaluated as false if the innerText property of the element at index a is an empty string.

// The purpose of this if statement is to check if the element at index a has been clicked by a player (i.e., if it has a value of "X" or "O"). If it has not been clicked, the innerText property will be an empty string and the condition will be evaluated as false, causing the code inside the if block to be skipped. If the element at index a has been clicked, the innerText property will be a non-empty string and the condition will be evaluated as true, allowing the code inside the if block to be executed.


boxes = Array.from(document.getElementsByClassName("boxes"))
reset = document.getElementById("restart_btn")
wintext = document.getElementById("winning_text")

const X_text = "X"
const O_text = "O"
let current_player = X_text



const startgame = () => {
  
  if ((playerhaswon() == false) || (checkDraw() == false)){ 
  // mouse oper aye to red ya green , jayga to normal colour
  boxes.forEach(box =>
    {box.addEventListener("mouseenter", () => {
      
      box.style.backgroundColor = current_player==X_text?"rgb(215 175 175)":"rgb(175 215 193)"
    })
    
  }
    
    )
  boxes.forEach(box=>{
    box.addEventListener("mouseleave",()=>{
      box.style.backgroundColor = "rgb(222, 238, 225)"
    })
  })}

  
  




  boxes.forEach(box => {
    




    box.addEventListener("click", e => {


      if (playerhaswon() === false) {// agr player nahi jeeta to click kr sakty hain

        const id = e.target.id;// id lelo uski 0,1 ,2 etc

        if (e.target.innerText === "") { //agr kahli ha

          e.target.style.color = current_player == X_text ? "red" : "green"
          e.target.innerText = current_player; //uskay andr x ya o




          if (playerhaswon() !== false) {//is doraan agr jeet jaye to yeh karo

            wintext.innerHTML = `${current_player} has won`;
            let winning_blocks = playerhaswon();// player has won wala function 3 id return karay ga
            for (const num of winning_blocks) { // winnig block ma 3 blocks ki id ha
              boxes[num].style.backgroundColor = current_player == X_text?"rgb(215 175 175)":"rgb(175 215 193)";// un 3 blocks ka colour change 

            }
          } else if (checkDraw()) {// draw ha to draw likh do
            wintext.innerHTML = "Draw!";
          } else {// agr na jeeta hain na draw hain to ,, x ko o ma tabdel kar do ya o ko x ma
            current_player =
              current_player == X_text ? O_text : X_text;
          }
        }
      }

    });
  });
  
};

const winning_combos = [ // in teen jgah par x hua to jeet jaye ga
  [0, 1, 2],
  [3, 4, 5],
  [6, 7, 8],
  [0, 3, 6],
  [1, 4, 7],
  [2, 5, 8],
  [0, 4, 8],
  [2, 4, 6]
];


function playerhaswon() {// kab  jeetay  ga is trah pata chalay ga
  for (const condition of winning_combos) { // winning comb ma se [a,b,c] no. letay jau
    let [a, b, c] = condition;
    if (// agr box ka a th element likha hua hai aur box kay b th aur c th element k brabar ha
      boxes[a].innerText &&
      (boxes[a].innerText == boxes[b].innerText &&
        boxes[a].innerText == boxes[c].innerText)
    ) {
      return [a, b, c];// to unhay return krdo kyuki yehi element ma  x ya o same hai.
    }
  }
  return false; // agr aisa nahi ha matlabgame jaari hai
}
// let hover_thing;
// if ((playerhaswon()!==false)&& (checkDraw() == true)){
//     let hover_thing = true
// }

function checkDraw() {
  // Check if any cell on the board is empty
  for (let i = 0; i < 9; i++) {
    if (boxes[i].innerText === "") {
      return false;// agr khali hai matlab abhi draw nahi hua to false bhej do
    }
  }

  // Check if no player has won the game
  if (playerhaswon() === false) {
    return true;
  }

  // Otherwise, the game is not a draw
  return false;
}

function resetit() {// sab kuch reset kardo
  boxes.forEach(box => {
    box.innerHTML = "";
    box.style.backgroundColor = "";
  });
  current_player = X_text;
  wintext.innerHTML = "Tic Tac Toe";
}

reset.addEventListener("click", () => resetit());
// if (hover_thing == true){
//     document.getElementsByTagName("style")[0].innerHTML =
//     ".boxes:hover { background-color: initial; }";
// }

startgame();

I tried to condition hover only when game is not over. ::

if ((playerhaswon() == false) || (checkDraw() == false)){ 
  // mouse oper aye to red ya green , jayga to normal colour
  boxes.forEach(box =>
    {box.addEventListener("mouseenter", () => {
      
      box.style.backgroundColor = current_player==X_text?"rgb(215 175 175)":"rgb(175 215 193)"
    })
    
  }
    
    )
  boxes.forEach(box=>{
    box.addEventListener("mouseleave",()=>{
      box.style.backgroundColor = "rgb(222, 238, 225)"
    })
  })}

Solution

  • The problem is that you check whether the game is over at the wrong moment (and in the wrong way). It concerns the following statement:

    if ((playerhaswon() == false) || (checkDraw() == false)){ 
    

    This is executed when the game starts, not when the user moves the mouse. So that is the wrong moment to execute it.

    Secondly, this condition checks whether no player has won yet OR there is no draw. But logically, this condition is always true. Because if a player has won, then still it is no draw, and when it is a draw then no player has won. The || should be a &&, as you want both playerhaswon() and checkDraw() to be false at the same time. Alternatively, you can invert the condition, and when that is true, exit the function (which is what I will do in below snippet).

    So, correct that condition in either way and move it inside the mouseenter and mouseleave event handlers.

    For the click event handler you have done it almost right, but the check for a draw is missing there, so that must be added.

    Here is a correction (I added some HTML to make it work):

    const boxes = Array.from(document.getElementsByClassName("boxes"))
    const reset = document.getElementById("restart_btn")
    const wintext = document.getElementById("winning_text")
    
    const X_text = "X"
    const O_text = "O"
    let current_player = X_text
    
    const startgame = () => {  
      // mouse oper aye to red ya green, jayga to normal colour
      boxes.forEach(box => {
        box.addEventListener("mouseenter", () => {
          if (playerhaswon() || checkDraw()) return; 
          box.style.backgroundColor = current_player==X_text?"rgb(215 175 175)":"rgb(175 215 193)";
        });
      });
      boxes.forEach(box=>{
        box.addEventListener("mouseleave",()=>{
          if (playerhaswon() || checkDraw()) return; 
          box.style.backgroundColor = "rgb(222, 238, 225)"
        });
      });
    
      boxes.forEach(box => {
        box.addEventListener("click", e => {
          if (playerhaswon() || checkDraw()) return; // agr player nahi jeeta to click kr sakty hain
          const id = e.target.id;// id lelo uski 0,1 ,2 etc
          if (e.target.innerText === "") { //agr kahli ha
            e.target.style.color = current_player == X_text ? "red" : "green"
            e.target.innerText = current_player; //uskay andr x ya o
            if (playerhaswon() !== false) {//is doraan agr jeet jaye to yeh karo
              wintext.innerHTML = `${current_player} has won`;
              let winning_blocks = playerhaswon();// player has won wala function 3 id return karay ga
              for (const num of winning_blocks) { // winnig block ma 3 blocks ki id ha
                boxes[num].style.backgroundColor = current_player == X_text?"rgb(215 175 175)":"rgb(175 215 193)";// un 3 blocks ka colour change 
              }
            } else if (checkDraw()) {// draw ha to draw likh do
              wintext.innerHTML = "Draw!";
              e.target.style.backgroundColor = "rgb(222, 238, 225)";
            } else {// agr na jeeta hain na draw hain to ,, x ko o ma tabdel kar do ya o ko x ma
              current_player =
                current_player == X_text ? O_text : X_text;
            }
          }
        });
      });  
    };
    
    const winning_combos = [ // in teen jgah par x hua to jeet jaye ga
      [0, 1, 2],
      [3, 4, 5],
      [6, 7, 8],
      [0, 3, 6],
      [1, 4, 7],
      [2, 5, 8],
      [0, 4, 8],
      [2, 4, 6]
    ];
    
    
    function playerhaswon() {// kab  jeetay  ga is trah pata chalay ga
      for (const condition of winning_combos) { // winning comb ma se [a,b,c] no. letay jau
        let [a, b, c] = condition;
        if (// agr box ka a th element likha hua hai aur box kay b th aur c th element k brabar ha
          boxes[a].innerText &&
          (boxes[a].innerText == boxes[b].innerText &&
            boxes[a].innerText == boxes[c].innerText)
        ) {
          return [a, b, c];// to unhay return krdo kyuki yehi element ma  x ya o same hai.
        }
      }
      return false; // agr aisa nahi ha matlabgame jaari hai
    }
    // let hover_thing;
    // if ((playerhaswon()!==false)&& (checkDraw() == true)){
    //     let hover_thing = true
    // }
    
    function checkDraw() {
      // Check if any cell on the board is empty
      for (let i = 0; i < 9; i++) {
        if (boxes[i].innerText === "") {
          return false;// agr khali hai matlab abhi draw nahi hua to false bhej do
        }
      }
      // Check if no player has won the game
      if (playerhaswon() === false) {
        return true;
      }
      // Otherwise, the game is not a draw
      return false;
    }
    
    function resetit() {// sab kuch reset kardo
      boxes.forEach(box => {
        box.innerHTML = "";
        box.style.backgroundColor = "";
      });
      current_player = X_text;
      wintext.innerHTML = "Tic Tac Toe";
    }
    
    reset.addEventListener("click", () => resetit());
    // if (hover_thing == true){
    //     document.getElementsByTagName("style")[0].innerHTML =
    //     ".boxes:hover { background-color: initial; }";
    // }
    
    startgame();
    table { border-collapse: collapse; margin: 10px 0 10px 0 }
    table td { border: 1px solid; width: 25px; text-align: center; }
    tr { height: 25px; v-align: middle }
    .boxes { background-color: rgb(222, 238, 225) }
    <div id="winning_text">Tic Tac Toe</div>
    <table>
    <tr><td class="boxes"></td><td class="boxes"></td><td class="boxes"></td></tr>
    <tr><td class="boxes"></td><td class="boxes"></td><td class="boxes"></td></tr>
    <tr><td class="boxes"></td><td class="boxes"></td><td class="boxes"></td></tr>
    </table>
    <button id="restart_btn">Restart</button>