Othello Game Switching Turns Doesn't Work in React.js

112 Views Asked by At

I'm working on an Othello game in React and I've already implemented the code to switch player turns. It does switch from one to another(between white and black). But if there's no move available for the upcoming player, the turn stays the same. I though I had it all done but now I came across to such a case when trying out the game, and although it does switch player turns regularly, my code does not consider keeping it the same when necessary. Do you know why? How can I solve it?

Here's my code:

Where I change it:

    setWinnerAndTurn() {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[this.state.stepNumber];
        const squares = current.squares.slice()

        const blackSquares = []
        const whiteSquares = []
        // Check for a winner
        for (var row=0;row<squares.length;row++) {
            for (var col=0;col<squares[row].length;col++) {
                if (squares[row][col] === 'black') {
                    blackSquares.push([row,col])
                } else if (squares[row][col] === 'white') {
                    whiteSquares.push([row,col])
                }
            }
        }

        // Debug
        //console.log(blackSquares)
        //console.log(whiteSquares)
        

        const total = [blackSquares,whiteSquares]
        const movesAvailable = [[],[]]
        for (var t=0;t<total.length;t++) {
            const currentArray = total[t]
            const returned = this.checkElementsAround(currentArray)
            for (var r=0;r<returned.length;r++) {
                movesAvailable[t].push(returned[r])
            }
        }

        // Debug
        console.log(movesAvailable)


        if (blackSquares.length + whiteSquares.length === squares.length * squares[0].length || (movesAvailable[0] === [] && movesAvailable[1] === [])) {
            // Declare a winner
            if (blackSquares.length !== whiteSquares.length) {
                this.setState({
                    winner: (blackSquares.length > whiteSquares.length) ? 'black' : 'white'
                })
            } else {
                this.setState({
                    winner: 'tie'
                })
            }
        } else {
            // Change turn
            if (movesAvailable[0] === []) {
                this.setState({
                    blackIsNext: false
                })
            } else if (movesAvailable[1] === []){
                this.setState({
                    blackIsNext: true
                })
            } else {
                this.setState({
                    blackIsNext: !this.state.blackIsNext
                })
            }
        }
    }

And where I call the function:

render() {
<GameBoard squares={current.squares} onClick={(row,col) => {
                    const elems = this.checkElementsAround(this.checkMoveValidity())
                    //console.log(elems)
                    for (let el=0;el<elems.length;el++) {
                        const turning = this.checkTurningStones(elems[el].directions)
                        if (turning.length !== 0) {
                            if (row === elems[el].coordinates[0] && col === elems[el].coordinates[1]) {
                                this.handleMove(row,col);
                                //console.log(turning)
                                for (var t=0;t<turning.length;t++) {
                                    this.handleMove(turning[t][0],turning[t][1])
                                }
                                this.setWinnerAndTurn()
                                break
                            }
                        }
                    }
                }}/>
}
1

There are 1 best solutions below

2
On BEST ANSWER

Solved the problem, but don't know how. That's strange...

Here's the Code:

setWinnerAndTurn() {
        const history = this.state.history.slice(0, this.state.stepNumber + 1);
        const current = history[this.state.stepNumber];
        const squares = current.squares.slice()

        const blackSquares = []
        const whiteSquares = []
        // Check for a winner
        for (var row=0;row<squares.length;row++) {
            for (var col=0;col<squares[row].length;col++) {
                if (squares[row][col] === 'black') {
                    blackSquares.push([row,col])
                } else if (squares[row][col] === 'white') {
                    whiteSquares.push([row,col])
                }
            }
        }
        
        const valids = this.checkElementsAround(this.checkEmptySpaces())

        // checkEmptySpaces returns all the empty spaces in the game
        // checkElementsAround returns all the objects in all directions if there's initially an element in that direction

        const movesAvailable = [0,0]

        for (var t=0;t<2;t++) {
            const isBlack = (t === 0) ? true : false
            for (var v=0;v<valids.length;v++) {
                const valid = valids[v]
                const turned = this.checkTurningStones(valid.directions,isBlack)
                if (turned.length !== 0) {
                    movesAvailable[t]++;
                }
            }
        }

        if (blackSquares.length + whiteSquares.length === squares.length * squares[0].length || (movesAvailable === [0,0])) {
            // Declare a winner
            if (blackSquares.length !== whiteSquares.length) {
                this.setState({
                    winner: (blackSquares.length > whiteSquares.length) ? 'black' : 'white'
                })
            } else {
                this.setState({
                    winner: 'tie'
                })
            }
        } else {
            // Change turn
            if (movesAvailable[0] === 0) {
                this.setState({
                    blackIsNext: false
                })
            } else if (movesAvailable[1] === 0){
                this.setState({
                    blackIsNext: true
                })
            } else {
                this.setState({
                    blackIsNext: !this.state.blackIsNext
                })
            }
        }
    }

Where I used it:

<div className="master-container">
                <GameBoard squares={current.squares} onClick={(row,col) => {
                    const elems = this.checkElementsAround(this.checkEmptySpaces())
                    for (let el=0;el<elems.length;el++) {
                        const turning = this.checkTurningStones(elems[el].directions, this.state.blackIsNext)
                        if (turning.length !== 0) {
                            turning.unshift([row,col])
                            if (row === elems[el].coordinates[0] && col === elems[el].coordinates[1]) {
                                this.handleMove(turning)
                                this.setWinnerAndTurn()
                                // Debug
                                console.log(history.length)
                                break
                            }
                        }                        
                    }
                }}/>

// handleMove -> You give an array of coordinates and it does turn them
// setWinnerAndTurn -> Our function
// checkTurningStones -> I give it the output of checkElementsAround as a parameter, it does return the elements that are to be turned upside down

Actually I know how I fixed it; the thing is that since most of my conditional statements depend on the values returned from some of my functions, when used inappropriately, some conditional statements would never return true. That's what I solved.