Search code examples
javascriptconstructortic-tac-toetypescript

javascript - updating tic tac toe board


i'm trying to create a basic tic tac toe game in vanilla javascript using an object constructor. for every new game i want to create a new instance of the tic tac toe board (e.g. var game = new TicTacToe()). this will be a 2 player game, and every time a play wants to put their respective marker on the board, they would invoke that object instance (game.play(spot)) that takes a parameter of the slot on the board they want to take. the turns alternate between each player (i made a counter so that odd turns would be X and even would be O)

i'm having a problem with actually placing any markers on the board, it doesnt seem that my board is changing whatsoever whenever i invoke game.play

// basic requirements
// var game = new TicTacToe();
// game.play(3) // 1 - 9
// keep track of if it's x or o's turn
// if someone wins, don't allow any more moves
// display winner
// display tie if neither player wins
// game.showBoard() 
// show the board 
// 1 2 3
// 4 5 6
// 7 8 9

// create an object constructor 
function TicTacToe() {
  //instance of TicTacToe board
  this.TicTacToe = TicTacToe;
  // creates a matrix (array with 3 subarrays
  // creates a new board instance 
  this.newBoard = [
      // creates a matrix (array with 3 subarrays
      // each subarray will have 3 indices
      [1, 2, 3],
      [4, 5, 6],
      [7, 8, 9]
    ];
    this.currentBoard = this.newBoard;
  // declares players and their respective symbols
  // each player has separate variable so the winner can be declared at the end
  // and score can be recorded
  this.player1 = 'X';
  this.player2 = 'O';
  // this.currentPlayer;
  this.gameOver = false;
  // keeps track of turns
  this.turn = 1;
}

// create createBoard method
// creates a new Board whenever new instance of TicTacToe is created


  TicTacToe.prototype.boardState = function() {
    this.currentBoard;
  };

//  play method
TicTacToe.prototype.play = function(spot) {
  this.state = this.currentBoard;
  console.log(this.state);

  //what spot stands for
  if(spot === 1){
    this.boardSlot = this.state[0][0]
    console.log(this.boardSlot)
  } else if (spot === 2) {
    this.boardSlot = this.state[0][1]
    console.log(this.boardSlot)
  } else if (spot === 3) {
    this.boardSlot = this.state[0][2]
    console.log(this.boardSlot)
  } else if (spot === 4) {
    this.boardSlot = this.state[1][0]
    console.log(this.boardSlot)
  } else if (spot === 5) {
    this.boardSlot = this.state[1][1]
    console.log(this.boardSlot)
  } else if (spot === 6) {
    this.boardSlot = this.state[1][2]
    console.log(this.boardSlot)
  } else if (spot === 7) {
    this.boardSlot = this.state[2][0]
    console.log(this.boardSlot)
  } else if (spot === 8) {
    this.boardSlot = this.state[2][1]
    console.log(this.boardSlot)
  } else if (spot === 9) {
    this.boardSlot = this.state[2][2]
    console.log(this.boardSlot)
  }

  console.log(this.newBoard);

  //checks to see if spot chosen is valid or taken
  //return true if passes both tests
  var isValid = function() {
    // can only choose spots 1-9
    // create error if other number chosen
    if (spot < 1 || spot > 9) {
      return 'incorrect input, must choose between 1 and 9'
    }
    //checks to see if slot is taken
    // a) check if spot is available
    else if(typeof this.boardSlot !== number){
      console.log('please try another slot, this one is taken');
    }
    return true;
  }



  function setMark () {
    if(isValid === true){
          // keeps track of current player
    // if turn is odd, player is X
  if (this.turn % 2 !== 0) {
    this.currentPlayer = this.player1;
    this.boardSlot.pop().push('X');
    this.turn++
  }
  // if even, player is O
  else {
    this.currentPlayer = this.player2;
    this.boardSlot.pop().push('O');
    this.turn++
  }
    }
  }

//b) a player has won (has 3 repeating letters either vertically, horizontally, diagonally)
  function checkWin() {
    if(this.state[0][0] === 'X' && this.state[0][1] === 'X' && this.state[0][2] === 'X'){
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][0] === 'X' && this.state[1][0] === 'X' && this.state[2][0] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[1][0] === 'X' && this.state[1][1] === 'X' && this.state[1][2] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[2][0] === 'X' && this.state[2][1] === 'X' && this.state[2][2] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][0] === 'X' && this.state[1][1] === 'X' && this.state[2][2] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][2] === 'X' && this.state[1][1] === 'X' && this.state[2][0] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][1] === 'X' && this.state[1][1] === 'X' && this.state[2][1] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'   
    } else if(this.state[0][2] === 'X' && this.state[1][2] === 'X' && this.state[2][2] === 'X') {
      this.gameOver = true;
      return 'Player 1 wins!'  
    } else if(this.state[0][0] === 'O' && this.state[0][1] === 'O' && this.state[0][2] === 'O'){
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][0] === 'O' && this.state[1][0] === 'O' && this.state[2][0] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[1][0] === 'O' && this.state[1][1] === 'O' && this.state[1][2] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[2][0] === 'O' && this.state[2][1] === 'O' && this.state[2][2] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][0] === 'O' && this.state[1][1] === 'O' && this.state[2][2] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][2] === 'O' && this.state[1][1] === 'O' && this.state[2][0] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'
    } else if(this.state[0][1] === 'O' && this.state[1][1] === 'O' && this.state[2][1] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'   
    } else if(this.state[0][2] === 'O' && this.state[1][2] === 'O' && this.state[2][2] === 'O') {
      this.gameOver = true;
      return 'Player 1 wins!'  
    }
  }

// c) if all the spots are filled
 // turns can only go up to 9
// console log that the players have tied
// if either a or b occur, console log the game is over
// no more moves accepted

if(this.turns === 9) {
  this.gameOver = true
  return "Cat's game! Both players have tied"
} else if (this.gameOver === true) {
  return "This game is over. Please start another."
}


}

var game = new TicTacToe();
game.play(9);
game.play(4);


Solution

  • The problem is that you are declaring some functions in the play function, but you are not calling them, so the board is never changed. Aside from that, when you do this this.boardSlot = this.state[0][0] you lose the reference to the array and if you reassign it, it won't change the array. And if you declare the functions like setMark, isValid inside play, they won't share the same this. I modified your code a little bit to have something working, you can take a look below.

    // basic requirements
    // var game = new TicTacToe();
    // game.play(3) // 1 - 9
    // keep track of if it's x or o's turn
    // if someone wins, don't allow any more moves
    // display winner
    // display tie if neither player wins
    // game.showBoard()
    // show the board
    // 1 2 3
    // 4 5 6
    // 7 8 9
    
    // create an object constructor
    function TicTacToe() {
        //instance of TicTacToe board
        this.TicTacToe = TicTacToe;
        // creates a matrix (array with 3 subarrays
        // creates a new board instance
        this.newBoard = [
            // creates a matrix (array with 3 subarrays
            // each subarray will have 3 indices
            [1, 2, 3],
            [4, 5, 6],
            [7, 8, 9]
        ];
        this.currentBoard = this.newBoard;
        // declares players and their respective symbols
        // each player has separate variable so the winner can be declared at the end
        // and score can be recorded
        this.player1 = 'X';
        this.player2 = 'O';
        // this.currentPlayer;
        this.gameOver = false;
        // keeps track of turns
        this.turn = 1;
    }
    
    // create createBoard method
    // creates a new Board whenever new instance of TicTacToe is created
    
    TicTacToe.prototype.boardState = function() {
        this.currentBoard;
    };
    
    
    //checks to see if spot chosen is valid or taken
    //return true if passes both tests
    TicTacToe.prototype.isSlotValid = function(row, col) {
      //checks to see if slot is taken
      // a) check if spot is available
      if (typeof this.currentBoard[row][col] != 'number') {
          console.log('please try another slot, this one is taken');
          return false;
      }
    
      return true;
    }
    
    TicTacToe.prototype.setMark = function(row, col) {
        if (this.isSlotValid(row, col) === true) {
            // keeps track of current player
            // if turn is odd, player is X
            if (this.turn % 2 !== 0) {
                this.currentPlayer = this.player1;
                this.currentBoard[row][col] = 'X';
                this.turn++
            }
            // if even, player is O
            else {
                this.currentPlayer = this.player2;
                this.currentBoard[row][col] = 'O';
                this.turn++
            }
        }
    }
    
    TicTacToe.prototype.checkWin = function() {
        if (this.state[0][0] === 'X' && this.state[0][1] === 'X' && this.state[0][2] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][0] === 'X' && this.state[1][0] === 'X' && this.state[2][0] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[1][0] === 'X' && this.state[1][1] === 'X' && this.state[1][2] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[2][0] === 'X' && this.state[2][1] === 'X' && this.state[2][2] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][0] === 'X' && this.state[1][1] === 'X' && this.state[2][2] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][2] === 'X' && this.state[1][1] === 'X' && this.state[2][0] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][1] === 'X' && this.state[1][1] === 'X' && this.state[2][1] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][2] === 'X' && this.state[1][2] === 'X' && this.state[2][2] === 'X') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][0] === 'O' && this.state[0][1] === 'O' && this.state[0][2] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][0] === 'O' && this.state[1][0] === 'O' && this.state[2][0] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[1][0] === 'O' && this.state[1][1] === 'O' && this.state[1][2] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[2][0] === 'O' && this.state[2][1] === 'O' && this.state[2][2] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][0] === 'O' && this.state[1][1] === 'O' && this.state[2][2] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][2] === 'O' && this.state[1][1] === 'O' && this.state[2][0] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][1] === 'O' && this.state[1][1] === 'O' && this.state[2][1] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        } else if (this.state[0][2] === 'O' && this.state[1][2] === 'O' && this.state[2][2] === 'O') {
            this.gameOver = true;
            console.log('Player 1 wins!');
        }
    }
    
    //  play method
    TicTacToe.prototype.play = function(spot) {
        this.state = this.currentBoard;
    
        var row = Math.floor((spot - 1) / 3);
        var col = (spot - 1) % 3;
    
        this.setMark(row, col);
        console.log(this.currentBoard);
    
        //b) a player has won (has 3 repeating letters either vertically, horizontally, diagonally)
        this.checkWin();
    
        // c) if all the spots are filled
        // turns can only go up to 9
        // console log that the players have tied
        // if either a or b occur, console log the game is over
        // no more moves accepted
    
        if (this.turns === 9) {
            this.gameOver = true
            console.log("Cat's game! Both players have tied");
        } else if (this.gameOver === true) {
            console.log("This game is over. Please start another.");
        }
    
    
    }
    
    var game = new TicTacToe();
    game.play(9);
    game.play(4);