'Why does my event stop occuring after only one click?

I'm trying to make a tic tac toe game. The part where the computer choice is generated only occurs after one click, after that, no computer choice is generated.

For example, in the first picture, when I make the first move of placing an X in any of these boxes, a random O is displayed in another box which is what I intended.

But when I make the second move of placing an X on the middle box as shown in the second picture. No random O pops up in another box. The next moves I make also do not display a random O in other boxes.

For example, when I make the first move of placing an X in any of these boxes, a random O is displayed in another box which is what I intended.

But when I make the second move of placing an X on the middle box as shown in the picture. No random O pops up in another box. The next moves I make also do not display a random O in other boxes.

@import url('https://fonts.googleapis.com/css2?family=Koulen&family=VT323&display=swap');
@import url('https://fonts.googleapis.com/css2?family=Lobster&family=Signika+Negative:wght@400;500;600&display=swap');
* {
    margin: 0;
    padding: 0;
    box-sizing: border-box;
}

html, body {
    text-align: center;
    background-color: #1C2C54;
    color: #D175B7;
    font-family: 'Signika Negative', sans-serif;
}

main {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    gap: 20px;
    margin: auto;
    position: absolute;
    top: 50%;
    bottom: 50%;
    left: 50%;
    right: 50%;
    
}

h1 {
    font-family: 'VT323', monospace;
    font-size: 3rem;
}

.text-container {
    display: flex;
    flex-direction: column;
    width: 300px;
}

.grid-container {
    display: grid;
    grid-template-columns: auto auto auto;
    background-color: #4BC3B5;
    padding: 20px;
    
  }
  .grid-item {
    background-color: rgba(255, 255, 255, 0.8);
    border: 1px solid rgba(0, 0, 0, 0.8);
    padding: 30px;
    font-size: 30px;
    text-align: center;
    cursor: pointer;
  }

.button-container {
    display: flex;
    flex-direction: row;
    gap: 10px;
}

button {
    padding: 3px 20px;
    background-color: #4BC3B5;
    color: white;
    border: 3px solid #34a396;
    border-radius: 5px;
    cursor: pointer;
}

button:hover {
    background-color: #2c8d82;
    border: 3px solid #124640;
}

button:focus {
    background-color: #2c8d82;
    border: 3px solid #124640;
}

  .score-container {
      display: flex;
      flex-direction: column;
      gap: 10px;
      width: 300px;
      justify-content: center;
      color: white;
  }

  @media only screen 
  and (min-device-width: 768px) 
  and (max-device-width: 1190px) 
  and (orientation: portrait) 
  and (-webkit-min-device-pixel-ratio: 1) {
    button {
        font-size: 1.5rem;
        padding: 10px 25px;
    }
    .grid-container {
        padding: 40px;
        
      }
      .grid-item {
        padding: 40px;
        font-size: 2rem;
      }
  }

@media (min-width:1281px) {
    button {
        font-size: 2rem;
        padding: 10px 25px;
    }
    .grid-container {
        padding: 40px;
        
      }
      .grid-item {
        padding: 40px;
        font-size: 2rem;
      }
}
<!DOCTYPE html>
<html lang="en">
<head>
    <link rel="stylesheet" href="style.css">
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Tic Tac Toe</title>
</head>
<body>
    <main>
        <div class="text-container">
            <h1>Tic Tac Toe</h1>
        </div>
        <div class="grid-container">
            <div class="grid-item" id="grid1"></div>
            <div class="grid-item" id="grid2"></div>
            <div class="grid-item" id="grid3"></div>
            <div class="grid-item" id="grid4"></div>
            <div class="grid-item" id="grid5"></div>
            <div class="grid-item" id="grid6"></div>
            <div class="grid-item" id="grid7"></div>
            <div class="grid-item" id="grid8"></div>
            <div class="grid-item" id="grid9"></div>
        </div>
        <div class="button-container">
            <button id="x-el" onclick="selectX()">X</button>
            <button id="o-el" onclick="selectO()">O</button>
        </div>
        <div class="score-container">
            <p id="playerscore">Player Score:</p>
            <p id="compscore">Computer Score:</p>
        </div>
    </main>
    <script>
        // Grab the elements
        let xBtn = document.getElementById('x-el')
        let oBtn = document.getElementById('o-el')
        let playerScoreDisplay = document.getElementById('playerscore')
        let compScoreDisplay = document.getElementById('compscore')
        let x = 'X'
        let o = 'O'
        let userChoice;
        let computerChoice;

        // Grabbing individual boxes
        let box1 = document.getElementById('grid1');
        let box2 = document.getElementById('grid2');
        let box3 = document.getElementById('grid3');
        let box4 = document.getElementById('grid4');
        let box5 = document.getElementById('grid5');
        let box6 = document.getElementById('grid6');
        let box7 = document.getElementById('grid7');
        let box8 = document.getElementById('grid8');
        let box9 = document.getElementById('grid9');
        

        // Selecting x or o
        function selectX() {
            userChoice = x;
            computerChoice = o;
            alert('You selected X!');
            
        }
        function selectO() {
            userChoice = o;
            computerChoice = x;
            alert('You selected O!');
            
        }

 // using arrays to loop through divs
 function loopPositioning(array){
            const randomIndex = Math.floor(Math.random()* array.length);
            const item = array[randomIndex];
            return item;
           
        }
        const array = [1,2,3,4,5,6,7,8,9];
        const result = loopPositioning(array);
        console.log(result);

        // looping all divs
        let boxes = document.querySelectorAll('div.grid-item').forEach(box => {
            box.addEventListener('click', event => {
               if (userChoice === x) {
                    box.innerHTML = x;

                        if (result == 1) {
                box1.innerHTML = o;
                } else if (result == 2) {
                    box2.innerHTML = o;
                } else if (result == 3) {
                    box2.innerHTML = o;
                } else if (result == 4) {
                    box4.innerHTML = o;
                } else if (result == 5) {
                    box5.innerHTML = o;
                } else if (result == 6) {
                    box6.innerHTML = o;
                } else if (result == 7) {
                    box7.innerHTML = o;
                } else if (result == 8) {
                    box8.innerHTML = o;
                } else if (result == 9) {
                    box9.innerHTML = o;
                }
                    
                    
                } else if (userChoice === o) {
                    box.innerHTML = o;
                    if (result == 1) {
                box1.innerHTML = x;
                } else if (result == 2) {
                    box2.innerHTML = x;
                } else if (result == 3) {
                    box2.innerHTML = x;
                } else if (result == 4) {
                    box4.innerHTML = x;
                } else if (result == 5) {
                    box5.innerHTML = x;
                } else if (result == 6) {
                    box6.innerHTML = x;
                } else if (result == 7) {
                    box7.innerHTML = x;
                } else if (result == 8) {
                    box8.innerHTML = x;
                } else if (result == 9) {
                    box9.innerHTML = x;
                }
                    
                }
            })
        })

    </script>
</body>
</html>

How do I make the computer choice consistently pick a random box every time I place my move?



Solution 1:[1]

the problem with your code is you are calling the loopPositioning() only onces when the code enters execution. so, you need to call the function everytime when a box is cicked. here is your correct answer.

  <script>
        // Grab the elements
        let xBtn = document.getElementById('x-el')
        let oBtn = document.getElementById('o-el')
        let playerScoreDisplay = document.getElementById('playerscore')
        let compScoreDisplay = document.getElementById('compscore')
        let x = 'X'
        let o = 'O'
        let userChoice;
        let computerChoice;

        // Grabbing individual boxes
        let box1 = document.getElementById('grid1');
        let box2 = document.getElementById('grid2');
        let box3 = document.getElementById('grid3');
        let box4 = document.getElementById('grid4');
        let box5 = document.getElementById('grid5');
        let box6 = document.getElementById('grid6');
        let box7 = document.getElementById('grid7');
        let box8 = document.getElementById('grid8');
        let box9 = document.getElementById('grid9');
        
        const array = [1,2,3,4,5,6,7,8,9];
        var result;
        
        // Selecting x or o
        function selectX() {
            userChoice = x;
            computerChoice = o;
            alert('You selected X!');
            
        }
        function selectO() {
            userChoice = o;
            computerChoice = x;
            alert('You selected O!');
            
        }

 // using arrays to loop through divs
 function loopPositioning(array){
            const randomIndex = Math.floor(Math.random()* array.length);
            const item = array[randomIndex];
            return item;
           
        }
       
        console.log(result);

        // looping all divs
        let boxes = document.querySelectorAll('div.grid-item').forEach(box => {
            box.addEventListener('click', event => {
               if (userChoice === x) {
                    box.innerHTML = x;
                    result = loopPositioning(array);

                        if (result == 1) {
                box1.innerHTML = o;
                } else if (result == 2) {
                    box2.innerHTML = o;
                } else if (result == 3) {
                    box2.innerHTML = o;
                } else if (result == 4) {
                    box4.innerHTML = o;
                } else if (result == 5) {
                    box5.innerHTML = o;
                } else if (result == 6) {
                    box6.innerHTML = o;
                } else if (result == 7) {
                    box7.innerHTML = o;
                } else if (result == 8) {
                    box8.innerHTML = o;
                } else if (result == 9) {
                    box9.innerHTML = o;
                }
                    
                    
                }  if (userChoice === o) {
                result = loopPositioning(array);
                    box.innerHTML = o;
                    if (result == 1) {
                box1.innerHTML = x;
                } else if (result == 2) {
                    box2.innerHTML = x;
                } else if (result == 3) {
                    box2.innerHTML = x;
                } else if (result == 4) {
                    box4.innerHTML = x;
                } else if (result == 5) {
                    box5.innerHTML = x;
                } else if (result == 6) {
                    box6.innerHTML = x;
                } else if (result == 7) {
                    box7.innerHTML = x;
                } else if (result == 8) {
                    box8.innerHTML = x;
                } else if (result == 9) {
                    box9.innerHTML = x;
                }
                    
                }
            })
        })

    </script>

Now, as you can see the variable result have a value everytime a user clicked on the box. but i saw a bug on your code. you are not mark the visited box as visited before. So, even after you run this code you might see as the error you encountered before this is because it sets the innerHTML both x and 0 but modifies the previous visited boxes. So, you need to mark the visited box as marked.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1