1

I am creating a Tic Tac Toe game using javascript's immediately invoked function element(IIFE). So far, I have managed to create the game board with CSS and HTML and have also managed to get game play that identifies the winner based on the sign. I have also been able to create a reset function. My problem however is that I cannot figure out how to program the logic to display a tie when none of the combinations are found. What often happens is whenever I try to program the logic for a tie, it displays tie on first click on the game board. Can someone please help me sort this out!

    const gameBoard = (() =>{        
        const sectors = document.querySelectorAll(".sector");
        
        let sector = Array.from(sectors);
        const winner = [
            [0,1,2],
            [3,4,5],
            [6,7,8],
            [0,3,6],
            [1,4,7],
            [2,5,8],
            [0,4,8],
            [2,4,6]
        ];

        let choice = "X"; 
                
        const gamePlay = () =>{
            const count = () => sector.forEach((val, index)=>{
                val.addEventListener('click',()=>{
                    if(val.textContent === choice){
                        index += 1;
                    }else{
                        index = 0;
                    }
                })
                
            })
            const move = () =>{                
                sector.forEach((mark)=>{
                    mark.addEventListener("click",()=>{
                        if(mark.textContent === ""){                                            
                        choice = choice === "X"?"O":"X";
                        mark.textContent = choice;
                        gameWinner();
                        }                                               
                    })
                })                
            }
            move()
            const resetGame = () =>{
                const reset = document.querySelector("#reset");
                reset.addEventListener('click',()=>{
                    sector.forEach((mark) =>{
                        mark.textContent = "";
                    })
                })
            }
            resetGame();           
            const gameWinner = () =>{
                winner.forEach((combo)=>{
                    let checkWinner = combo.every(idx =>
                        sector[idx].textContent === choice)
                    if(checkWinner){
                        alert(choice + " has won!");
                    }else if(count() <= winner.length && !checkWinner){
                        alert('tie');
                    }
                })                               
            }            
        }
        const players = (player1, player2, machine)=>{
            
        }
        return {gamePlay};       
    })();
    gameBoard.gamePlay();
<!DOCTYPE html>
<html lang="en">
    <head>
        <title>Tic-Tac-Toe</title>
        <script src="game.js" defer></script>
        <link rel="stylesheet" href="layout.css">
    </head>
    <body>
        <header id="title">Tic-Tac-Toe</header>
        <main>
            <!--<div id="playerSelection">
                <p>Select Your Mark</p>
                <button id="x">X</button><button id="o">O</button>
            </div>-->
            <div id="board">
                <div id = "one" class="sector"></div>
                <div id = "two" class="sector"></div>
                <div id = "three" class="sector"></div>
                <div id = "four" class="sector"></div>
                <div id = "five" class="sector"></div>
                <div id = "six" class="sector"></div>
                <div id = "seven"class="sector"></div>
                <div id = "eight" class="sector"></div>
                <div id = "nine" class="sector"></div>
            </div>
            <button id="reset">Reset</button>            
        </main>
    </body>
</html>
#title{
    display:flex;
    align-items: center;
    justify-content: center;
}
#board{
    display:grid;
    grid-template-columns: 100px 100px 100px;
    grid-template-rows: 100px 100px 100px;
    grid-gap:10px;
    background-color: darkblue;
    width:320px;
    height:320px;
}
.sector{
    background-color: cadetblue;
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: 50px;
}
#playerSelection{
    display:flex;
    flex-direction: column;
    justify-content: center;
}
main{
    display:flex;
    flex-direction:column;
    align-items: center;
    justify-content: center;
}
Reemy876
  • 13
  • 5
  • Please include the code that attempts to detect a tie. Readers need to see if it includes a count of moves since the game started, or counts the number of unmarked squares after each turn in order to work out what is wrong with it. – traktor Mar 05 '22 at 01:13
  • Hello traktor. I have since added a count function to try and trigger a tie alert in the gameWinner function. I have added this to the original code. – Reemy876 Mar 05 '22 at 19:25
  • why not create a list of possible move and check if there is a winning move in them ? you only have 82 possibilities after first player, so it's not to much to process i think – Gautier Logeot Mar 05 '22 at 20:43

1 Answers1

1

Some issues:

  • count is binding event listeners. It is not counting anything. Something gets done when these events are triggered (when clicked), but that is useless. The index increment will not have any effect as this variable is never used for anything other then incrementing and resetting. Finally, count() always returns undefined because that is what forEach is designed to return. Instead define a function boardIsFull:

    const boardIsFull = () => sector.every((val) => val.textContent != "");
    
  • gameWinner is calling count() for every combination. Surely the state of a tie is not dependent on which combo is being verified, so the check for a tie should only happen once. Here is how you could define this function:

    const gameWinner = () => {
        let checkWinner = winner.find((combo) => 
            combo.every(idx => sector[idx].textContent === choice)
        );
        if (checkWinner) {
            alert(choice + " has won!");
        } else if(boardIsFull()) {
            alert('tie');
        }
    };            
    

You should further improve your code to avoid that the game continues after a player has already made a winning combo.

You can then add more features, like an algorithm that calculates a move so you can play a "computer" opponent. See this answer for such an implementation.

trincot
  • 317,000
  • 35
  • 244
  • 286
  • 1
    Thank you trincot! This helped considerably. Now I can move on to adding other features as you had alluded to in your response. Thanks again! – Reemy876 Mar 05 '22 at 22:17