Home > OS >  Javascript Tic Tac Toe Game does not display Tie whenever win combos are not chosen
Javascript Tic Tac Toe Game does not display Tie whenever win combos are not chosen

Time:03-06

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" ></div>
                <div id = "two" ></div>
                <div id = "three" ></div>
                <div id = "four" ></div>
                <div id = "five" ></div>
                <div id = "six" ></div>
                <div id = "seven"></div>
                <div id = "eight" ></div>
                <div id = "nine" ></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;
}

CodePudding user response:

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.

  • Related