0

Been trying to build a TicTacToe game and I've been having some trouble with a restart button. First, I had some problems with removing an Event Listener but now that that is somewhat fixed my function just gets auto clicked straight away.

I have a big function that gets called immediately to get the game started where I set up my empty array to put the X's and O's, where I loop through an array to add event listeners and the functions that get called by the event listener.

I had some issues with scope, where I would start looping through an array and then on each element/box, add an eventListener. When I tried to remove the eventListener from somewhere else, it would just throw a Reference Error. Now with the code below, the restart button works, however both when the page loads and also when I click on restart, all the events fire off immediately.

function getReady(){ **// gets the game started and what restartButton fires when it gets clicked**


**// Has a game been played? If yes, then try and remove event listeners**
**// boxes is a nodelist with all 9 boxes that are clicked**

    if(gameOver){
        boxes.forEach(box => box.removeEventListener('click', mainLogic));
    }

    function mainLogic(i, mainArray){
        let sign = checkState(); // the correct mark (X, O) gets assigned to sign
        boxes[i].textContent = sign; // the mark appears on screen
        mainArray[i] = sign; // the mark goes into an array
        checkGame(sign, mainArray); // checks whether the game is over
    }

    for(let i = 0; i < boxes.length; i++){
        boxes[i].addEventListener('click', mainLogic(i, mainArray), {once: true})
    }
}

The other option I did which had a problem with the scope and throws an uncaught referenceError is the one below. However, what is quite confusing is that if I were to declare:

var mainLogic;

Then the restart button would work, however every "box", that wasn't clicked "last round", gets clicked twice which gives someone 2 and possible more turns. So, if I play: X [top left, middle left, bottom left] and O[top middle, middle middle] then X wins.

However when I click restart and the board gets restarted and I play top right, then O appears on the box even though X should because it clicks twice. If I were to click on something that was clicked last game, then it only fires once and the correct mark appears.

function getReady(){

   if(gameOver){ 
        boxes.forEach(box => { 
            box.removeEventListener('click', mainLogic);
            box.textContent = '';
        })
    }

   for(let i = 0; i < boxes.length; i++){
        boxes[i].addEventListener('click', function mainLogic(){
            //
        }, {once: true}) // once true makes it so it can only get clicked once
    }
}
CookieJar
  • 1
  • 2
  • `boxes[i].addEventListener('click', mainLogic(i, mainArray), { once: true })` doesn’t work because `mainLogic(i, mainArray)` isn’t a function. Note that in your second snippet, `function mainLogic(){`…`}` is not a function declaration in this context, so `mainLogic` won’t be in scope at `box.removeEventListener('click', mainLogic);`. – Sebastian Simon Nov 29 '22 at 14:29
  • But isn’t the mainLogic(i, mainArray) part of “boxes[i].addEventListener('click', mainLogic(i, mainArray), {once: true})” a function invocation? And doesn’t the removeEventListener method require the type of event and also the function that gets called which in this case which is mainLogic? Am I misunderstanding this? – CookieJar Nov 29 '22 at 22:06
  • See [What is the difference between a function call and function reference?](/q/15886272/4642212). `mainLogic(i, mainArray)` is syntactically a function invocation, but the important thing is its _value_, not its syntax. The value can be easily checked with `console.log(mainLogic(i, mainArray));`. [`removeEventListener`](//developer.mozilla.org/en/docs/Web/API/EventTarget/removeEventListener) needs the exact same function reference as in [`addEventListener`](//developer.mozilla.org/en/docs/Web/API/EventTarget/addEventListener); arrow functions, `function`, `.bind`, etc. create new functions. – Sebastian Simon Nov 29 '22 at 22:49

0 Answers0