0

I tried to use the 'this' keyword in other methods in my class but the value is undefined.

class TicTacToe {
    /**
     *Tic Tac Toe
   */
    constructor() {
        this.gameState = [ '', '', '', '', '', '', '', '', '' ];
        this.currentPlayer = 'X';
        this.gameActive = true;
        console.log('constructing now');  
    }

    /**
     *
     * @param {function} clickedCellEvent
     */
    handleCellClick(clickedCellEvent) {
        // Will save the clcicked element in a variable for use
        const clickedCell = clickedCellEvent.target;
        //Identifies the cells location on the grid
        const clickedCellIndex = parseInt(
            clickedCell.getAttribute('data-cell-index')
        );

        // Checks to see if the cell is played already or if the game is over
        // If so the click is ignored
        if (this.gameState[clickedCellIndex] !== '' || ! this.gameActive) {
            return;
        }

        // Once we get the cell index and run our check,
        // We update the gamestate and pass the turn

        this.handleGameStateUpdate(clickedCell, clickedCellIndex);
        this.handleResult();
    }

    /**
     * Updates the gamestate array and the html grid
     * @param  {function} clickedCell
     * @param  {function} clickedCellIndex
     */
    handleGameStateUpdate(clickedCell, clickedCellIndex) {
        // With this handler we will update the game state and the UI
        this.gameState[clickedCellIndex] = this.currentPlayer;
        clickedCell.innerHTML = this.currentPlayer;
    }

    /**
     * Changes the player turn
     */
    handelPlayerChange() {
        this.currentPlayer = this.currentPlayer === 'X' ? 'O' : 'X';
    }

    /**
     * Check to see if the game has ended after each turn
     */
    handelResult() {
        let roundWon = false;
        const roundDraw = !this.gameState.includes('');
        const winConditions = [
            [ 0, 1, 2 ],
            [ 3, 4, 5 ],
            [ 6, 7, 8 ],
            [ 0, 3, 6 ],
            [ 1, 4, 7 ],
            [ 2, 5, 8 ],
            [ 0, 4, 8 ],
            [ 2, 4, 6 ]
        ];

        for (let i = 0; i <= 7; i++) {
            const winCondition = winConditions[i];
            const a = this.gameState[winCondition[0]];
            const b = this.gameState[winCondition[1]];
            const c = this.gameState[winCondition[2]];

            if (a === '' || b === '' || c === '') {
                continue;
            }

            if (a === b && b === c) {
                roundWon = true;
                break;
            }
        }
        if (roundWon) {
            this.gameActive = false;

            return;
        }


        if (roundDraw) {
            this.gameActive = false;

            return;
        }

        this.handelPlayerChange();
    }


    /**
     * Restarts the game
     */
    handelRestartGame() {
        this.gameActive = true;
        this.currentPlayer = 'X';
        this.gameState = [ '', '', '', '', '', '', '', '', '' ];
        document.querySelectorAll('.cell')
            .forEach(cell => {
                cell.innerHTML = '';
            });
    }

}

const ttt = new TicTacToe();


/**
 * event listener for cell clicks on the html grid
 * @param  {String} .cell
 */
document.querySelectorAll('.cell').forEach(cell => cell.addEventListener('click', ttt.handleCellClick));

/**
 * event listener for game restart button
 * @param  {String} .game--restart
 */
document.querySelector('.game--restart').addEventListener('click', ttt.handelRestartGame);
.game--container {
    display: grid;
    grid-template-columns: repeat(3, auto);
    width: 306px;
    margin: 50px auto;
}
.cell {
    font-family: "Permanent Marker", cursive;
    width: 100px;
    height: 100px;
    box-shadow: 0 0 0 1px #333333;
    border: 1px solid #333333;
    cursor: pointer;
line-height: 100px;
    font-size: 60px;
}
  <h1 class="game--title"> Tic Tac Toe</h1>
  <div class="game--container">
      <div data-cell-index="0" class="cell"></div>
      <div data-cell-index="1" class="cell"></div>
      <div data-cell-index="2" class="cell"></div>
      <div data-cell-index="3" class="cell"></div>
      <div data-cell-index="4" class="cell"></div>
      <div data-cell-index="5" class="cell"></div>
      <div data-cell-index="6" class="cell"></div>
      <div data-cell-index="7" class="cell"></div>
      <div data-cell-index="8" class="cell"></div>
    <button class="game--restart">Restart Game</button>
  </div>
  <script src="script.js"></script>

https://codepen.io/donovanandrews300/pen/dyoBKjV?editors=1010

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
  • 1
    Either turn your class methods into fat-arrow syntax, which binds them automatically, or bind them in the constructor. They will have access at that point. EG `handleCellClick(clickedCellEvent) {` becomes `handleCellClick = clickedCellEvent => {`; or `this.handleCellClick = this.handleCellClick.bind(this)` in the constructor. – Derek Apr 05 '20 at 23:45
  • 1
    Also, you wrote "handle" wrong half a dozen times, but not consistently. – ASDFGerte Apr 05 '20 at 23:47
  • You have an answer in the comments, and the linked duplicate explains it all in detail. – Jamiec Apr 06 '20 at 07:46

0 Answers0