Home > Software engineering >  how do i input my field values into the array in a tic tac toe game in order to set a win
how do i input my field values into the array in a tic tac toe game in order to set a win

Time:11-02

I am making a simple tic tac toe game in order to practice the module pattern and factory pattern. i have implemented event listeners on the fields to mark x and o. but i need the x's and o's to also go inside the board array in order to compare with the winning combinations array.

i need to ultimately be able to find the winner after.

//player factory function
const createPlayer = (name,marker) => {
    return {name,marker}
}

//gameboard object
const gameBoard = (() => {
   //create board array
    let board = []
    for (i=0; i<9; i  ) {
        board.push("")
    }


    //add event listeners on each field that will mark field and change player's turn state
    const fields = document.querySelectorAll(".field") 
    const nextTurn = document.querySelector(".message")

   
    let turn = 0
    
    fields.forEach((field) => {
        field.addEventListener('click',handleClick,{once:true})

        function handleClick() {
            
                if(turn %= 2) {
                    field.innerHTML = "O"
                    field.classList.toggle("marker")
                    nextTurn.innerHTML= "Player X's turn"}
                    
                    else {
                    field.innerHTML = "X"
                    field.classList.toggle("marker")
                    nextTurn.innerHTML= "Player O's turn"}
                    
                    turn   
    

        }
        
    })

    //restart game
    const restart = document.getElementById("restart-button")

    restart.addEventListener("click",clicke)

    function clicke() {
        const fields = document.querySelectorAll(".field").innerHTML=""
    }

    
        

    return {
        board, 
    }
})()

// game object
const game = (() => {

    //declare players
    const playerOne = createPlayer("player x", "x")
    const playerTwo = createPlayer("player o", "o")

    //starting point
    let activePlayer = playerOne
    let winnerDeclared = false
    let remainingSpots = 9

    //selectors
    let playerName = document.querySelector('.message') //alert next turn

    //winning conditons
    const winningConditons = [
        [0,1,2]
        [3,4,5]
        [6,7,8]
        [0,3,8]
        [1,4,7]
        [2,5,8]
        [0,4,8]
        [2,4,6]
    ];

    //check for winner
    function checkWinner() {

    }

    function declareTie(){
        playerName.innerHTML = "Its a tie!"
    }

    
}
)()
.gameboard{
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-gap: 5px;
}
.field{
    width: 150px;
    height: 150px;
    background-color:  #ededee;
    
}
  <div >
        <div >
            <div >
                Tic-Tac-Toe
            </div>
        </div>
        <div >
            <div >Player X's turn</div>
            <div >
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
            </div>
            <div >
                <button id="restart-button">Restart</button>
            </div>
   
        </div>
    </div>

CodePudding user response:

See the comments in the attached snipped - it should guide you

//player factory function
const createPlayer = (name,marker) => {
    return {name,marker}
}

//gameboard object
const gameBoard = (() => {
   //create board array
    let board = []
    for (i=0; i<9; i  ) {
        board.push("")
    }


    //add event listeners on each field that will mark field and change player's turn state
    const fields = document.querySelectorAll(".field") 
    const nextTurn = document.querySelector(".message")

   
    let turn = 0
    
    fields.forEach((field) => {
        field.addEventListener('click',handleClick,{once:true})

        function handleClick() {
            
                if(turn %= 2) {
                    field.innerHTML = "O"
                    field.classList.toggle("marker")
                    nextTurn.innerHTML= "Player X's turn"
                }
                else {
                    field.innerHTML = "X"
                    field.classList.toggle("marker")
                    nextTurn.innerHTML= "Player O's turn"
                }
                game.checkWinner(); // <- check winner after every move
                turn  ;
    

        }
        
    })

    //restart game
    const restart = document.getElementById("restart-button")

    restart.addEventListener("click",clicke)

    function clicke() {
        console.log('you had a mistake here - you need to iterate the fields', document.querySelectorAll(".field"));
        const fields = document.querySelectorAll(".field").forEach(field => 
            {
                field.innerHTML="";
                // you also need to add the event listeners again where needed - field.addEventListener('click', ...)
            }
        );
    }

    
        

    return {
        board, 
    }
})()

// game object
const game = (() => {

    //declare players
    const playerOne = createPlayer("player x", "x")
    const playerTwo = createPlayer("player o", "o")

    //starting point
    let activePlayer = playerOne
    let winnerDeclared = false
    let remainingSpots = 9

    //selectors
    let playerName = document.querySelector('.message') //alert next turn

    //winning conditons
    const winningConditons = [
        [0,1,2], // <- you forgot the commas here!
        [3,4,5],
        [6,7,8],
        [0,3,8],
        [1,4,7],
        [2,5,8],
        [0,4,8],
        [2,4,6]
    ];

    //check for winner
    function checkWinner() {
        console.log('do stuff here');
    }

    function declareTie(){
        playerName.innerHTML = "Its a tie!"
    }

    return { // <- you need to "export" a function to be able to use it
        checkWinner
    }
}
)()
.gameboard{
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-gap: 5px;
}
.field{
    width: 150px;
    height: 150px;
    background-color:  #ededee;
    
}
  <div >
        <div >
            <div >
                Tic-Tac-Toe
            </div>
        </div>
        <div >
            <div >Player X's turn</div>
            <div >
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
            </div>
            <div >
                <button id="restart-button">Restart</button>
            </div>
   
        </div>
    </div>

CodePudding user response:

I have added a function checkPlayerMeetsConditions() to check whether player meets the conditions.

const checkPlayerMeetsConditions = (boardNodes, targetPlayer) => {
  const currResult = [];
  //winning conditons
  const winningConditons = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  boardNodes.forEach(({
    innerHTML: val
  }, i) => {
    if (val === targetPlayer) {
      currResult.push(i);
    }
  });


  let isWinner = false;

  winningConditons.forEach((condition) => {
    const isMatched = condition.reduce((isMatched, currVal, i) => currResult[i] !== currVal ? false : isMatched, true);

    if (isMatched) {
      isWinner = true;
      return;
    }
  });

  return isWinner;
}

Additionally I have filled your checkWinner() function as:

//check for winner
const checkWinner = () => {

  const fields = document.querySelectorAll(".field");
  
  const isOWinner = checkPlayerMeetsConditions(fields, "O");
  const isXWinner = checkPlayerMeetsConditions(fields, "X");

  if (isOWinner && isXWinner) { // when tie
    document.querySelector(".message").innerHTML = "Game Tie";
  } else if (isOWinner) {
    document.querySelector(".message").innerHTML = "O is Winner";
  } else if (isXWinner) {
    document.querySelector(".message").innerHTML = "X is Winner";
  }

}

Here is the full working codes:

//player factory function
const createPlayer = (name, marker) => {
  return {
    name,
    marker
  }
}

const checkPlayerMeetsConditions = (boardNodes, targetPlayer) => {
  const currResult = [];
  //winning conditons
  const winningConditons = [
    [0, 1, 2],
    [3, 4, 5],
    [6, 7, 8],
    [0, 3, 6],
    [1, 4, 7],
    [2, 5, 8],
    [0, 4, 8],
    [2, 4, 6],
  ];

  boardNodes.forEach(({
    innerHTML: val
  }, i) => {
    if (val === targetPlayer) {
      currResult.push(i);
    }
  });


  let isWinner = false;

  winningConditons.forEach((condition) => {
    const isMatched = condition.reduce((isMatched, currVal, i) => currResult[i] !== currVal ? false : isMatched, true);

    if (isMatched) {
      isWinner = true;
      return;
    }
  });

  return isWinner;
}

//check for winner
const checkWinner = () => {

  const fields = document.querySelectorAll(".field");
  
  const isOWinner = checkPlayerMeetsConditions(fields, "O");
  const isXWinner = checkPlayerMeetsConditions(fields, "X");

  if (isOWinner && isXWinner) { // when tie
    document.querySelector(".message").innerHTML = "Game Tie";
  } else if (isOWinner) {
    document.querySelector(".message").innerHTML = "O is Winner";
  } else if (isXWinner) {
    document.querySelector(".message").innerHTML = "X is Winner";
  }

}

//gameboard object
const gameBoard = (() => {
  //create board array
  let board = []
  for (i = 0; i < 9; i  ) {
    board.push("")
  }


  //add event listeners on each field that will mark field and change player's turn state
  const fields = document.querySelectorAll(".field")
  const nextTurn = document.querySelector(".message")


  let turn = 0



  fields.forEach((field) => {
    field.addEventListener('click', handleClick, {
      once: true
    })

    function handleClick() {

      if (turn %= 2) {
        field.innerHTML = "O"
        field.classList.toggle("marker")
        nextTurn.innerHTML = "Player X's turn"
      } else {
        field.innerHTML = "X"
        field.classList.toggle("marker")
        nextTurn.innerHTML = "Player O's turn"
      }

      turn  

      checkWinner(); //check the winner


    }

  })

  //restart game
  const restart = document.getElementById("restart-button")

  restart.addEventListener("click", clicke)

  function clicke() {
    const fields = document.querySelectorAll(".field").innerHTML = ""; // This is not correct
  }


  return {
    board,
  }
})()

// game object
const game = (() => {

  //declare players
  const playerOne = createPlayer("player x", "x")
  const playerTwo = createPlayer("player o", "o")

  //starting point
  let activePlayer = playerOne
  let winnerDeclared = false
  let remainingSpots = 9

  //selectors
  let playerName = document.querySelector('.message') //alert next turn

  function declareTie() {
    playerName.innerHTML = "Its a tie!"
  }


})()
.gameboard{
    display: grid;
    grid-template-columns: repeat(3,1fr);
    grid-gap: 5px;
}
.field{
    width: 150px;
    height: 150px;
    background-color:  #ededee;
    
}
  <div >
        <div >
            <div >
                Tic-Tac-Toe
            </div>
        </div>
        <div >
            <div >Player X's turn</div>
            <div >
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
                <div ></div>
            </div>
            <div >
                <button id="restart-button">Restart</button>
            </div>
   
        </div>
    </div>

Hope it helps, cheers!

  • Related