javascriptreactjsalgorithmothello

Othello valid move algorithm doesn't work javascript


I'm trying to code an Othello game, and now I'm trying to code the algorithm that does return the valid positions. I started by retrieving the directions of the empty squares where there's a black or white stone right next to it, but my code doesn't run. I don't know if I did something wrong but it seems that when I launch the program, the code runs slow because the algorithm is overkill. What can I do for that?

Here's my Code(By the way, I use React.js):

Here's the data structure of the square array:

history: [{
                squares: [
                    Array(8).fill(null),
                    Array(8).fill(null),
                    Array(8).fill(null),
                    [null,null,null,'black','white',null,null,null],
                    [null,null,null,'white','black',null,null,null],
                    Array(8).fill(null),
                    Array(8).fill(null),
                    Array(8).fill(null)
                ]
            }],

The Algorithm(for now, just returns the squares that have a stone right next to it(up, up & right , down, left, etc.)):

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

        // Get all the empty spaces
        const emptySpaces  = []
        for (var row=1;row<squares.length-1;row++) {
            for (var col=1;col<squares[row].length-1;col++) {
                if (!squares[row][col]) {
                    emptySpaces.push([row,col])
                }
            }
        }

        const cordAndDirs = []

        for (var sp=0;sp<emptySpaces.length;sp++) {
            const element = emptySpaces[sp]
            const elObject = {
                coordinates: element,
                directions: []
            }
            if (element === [0,0])
            {
                // Check down
                if (squares[1][0]) {
                    const downEls = []
                    for (var i=1;i<squares.length;i++) {
                        downEls.push([i,0])
                    }
                    elObject.directions.push(downEls)
                }
                // Check down right (diagonal)
                if (squares[1][1]) {
                    const drEls = []
                    for (var i=1;i<squares.length;i++) {
                        drEls.push([i,i])
                    }
                    elObject.directions.push(drEls)
                }
                // Check right
                if (squares[0][1]) {
                    const rightEls = []
                    for (var i=1;i<squares.length;i++) {
                        rightEls.push([0,i])
                    }
                    elObject.directions.push(rightEls)
                }
            }
            else if (emptySpaces[sp] === [0,7])
            {
                // Check down
                if (squares[1][7]) {
                    const downEls = []
                    for (var i=1;i<squares.length;i++) {
                        downEls.push([i,7])
                    }
                    elObject.directions.push(downEls)
                }
                // Check down left (diagonal)
                if (squares[1][6]) {
                    const drEls = []
                    for (var i=1;i<squares.length;i++) {
                        drEls.push([i,7 - i])
                    }
                    elObject.directions.push(drEls)
                }
                // Check left
                if (squares[0][6]) {
                    const leftEls = []
                    for (var i=1;i<squares.length;i++) {
                        leftEls.push([0,7 - i])
                    }
                    elObject.directions.push(leftEls)
                }
            }
            else if (emptySpaces[sp] === [7,0])
            {
                // Check up
                if (squares[6][0]) {
                    const upEls = []
                    for (var i=1;i<squares.length;i++) {
                        upEls.push([7 - i,0])
                    }
                    elObject.directions.push(upEls)
                }
                // Check up right
                if (squares[6][1]) {
                    const urEls = []
                    for (var i=1;i<squares.length;i++) {
                        urEls.push([7 - i,i])
                    }
                    elObject.directions.push(urEls)
                }
                // Check right
                if (squares[7][1]) {
                    const rightEls = []
                    for (var i=1;i<squares.length;i++) {
                        rightEls.push([7,i - 1])
                    }
                    elObject.directions.push(rightEls)
                }
            }
            else if (emptySpaces[sp] === [7,7])
            {
                //Check up
                if (squares[6][7]) {
                    const upEls = []
                    for (var i=1;i<squares.length;i++) {
                        upEls.push([7 - i,7])
                    }
                    elObject.directions.push(upEls)
                }
                // Check up left
                if (squares[6][6]) {
                    const ulEls = []
                    for (var i=1;i<squares.length;i++) {
                        ulEls.push([7 - i,7 - i])
                    }
                    elObject.directions.push(ulEls)
                }
                // Check left
                if (squares[7][6]) {
                    const leftEls = []
                    for (var i=1;i<squares.length;i++) {
                        leftEls.push([7,7 - i])
                    }
                    elObject.directions.push(leftEls)
                }
            }
            else
            {
                const crdsY = emptySpaces[sp][0]
                const crdsX = emptySpaces[sp][1]
                //Check up
                if (squares[crdsY - 1][crdsX]) {
                    const upEls = []
                    var i = 1
                    while (crdsY - i >= 0) {
                        upEls.push([crdsY - i,crdsX])
                        i++;
                    }
                    elObject.directions.push(upEls)
                }

                // Check up right
                if (squares[crdsY - 1][crdsX + 1]) {
                    const urEls = []
                    var i = 1
                    while (crdsY - i >= 0 && crdsX + i <= 7) {
                        urEls.push([crdsY - i,crdsX + i])
                        i++;
                    }
                    elObject.directions.push(urEls)
                }
                // Check right
                if (squares[crdsY][crdsX + 1]) {
                    const rightEls = []
                    var i = 1
                    while (crdsX + i <= 7) {
                        rightEls.push([crdsY,crdsX + i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check down right
                if (squares[crdsY + 1][crdsX + 1]) {
                    const rightEls = []
                    var i = 1
                    while (crdsY + i <= 7 && crdsX + i <= 7) {
                        rightEls.push([crdsY + i,crdsX + i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check down
                if (squares[crdsY + 1][crdsX]) {
                    const rightEls = []
                    var i = 1
                    while (crdsY + i <= 7) {
                        rightEls.push([crdsY + i,crdsX])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check down left
                if (squares[crdsY + 1][crdsX - 1]) {
                    const rightEls = []
                    var i = 1
                    while (crdsY + i <= 7 && crdsX - i >= 0) {
                        rightEls.push([crdsY + i,crdsX - i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check left
                if (squares[crdsY][crdsX - 1]) {
                    const rightEls = []
                    var i = 1
                    while (crdsX - i >= 0) {
                        rightEls.push([crdsY,crdsX - i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check up left
                if (squares[crdsY  - 1][crdsX - 1]) {
                    const rightEls = []
                    var i = 1
                    while (crdsY - i >= 0 && crdsX - i >= 0) {
                        rightEls.push([crdsY - i,crdsX - i])
                    }
                    elObject.directions.push(rightEls)
                }
                
            }

            if (elObject.directions.length === 0) {
                continue
            } else {
                cordAndDirs.push(elObject)
            }
        }

        return cordAndDirs
    }

And this is where I'm trying to implement it:

render() {
        const history = this.state.history
        const current = history[this.state.stepNumber]

        // Return the game scene here
        return (
            <div className="master-container">
                <GameBoard squares={current.squares} onClick={(row,col) => {
                    const elems = this.checkMoveValidity(this.state.blackIsNext)
                    console.log(elems)
                }}/>
            </div>
        )
    }

By the way, I checked whether the command has reached to the elements inside the GameBoard component. It does not have any problem, the problem occurred when I implemented the algorithm.


Solution

  • I did it. It was quite simple though, I even simplified the code a bit. I forgot to add i++; to the last while loop, I was stuck forever, and then I had to handle the borders so that I don't get an error. For example, I can't //Check up when the upper border squares have no squares beneath them.

    This is how I changed the conditional statements:

    for (var sp=0;sp<emptySpaces.length;sp++) {
                const element = emptySpaces[sp]
                const elObject = {
                    coordinates: element,
                    directions: []
                }
                    
                // You apply the same methods for all the other squares here (can't use constant numbers in 'squares' now...)
                const crdsY = emptySpaces[sp][0]
                const crdsX = emptySpaces[sp][1]
                var i;
                //Check up
                if (crdsY !== 0 && squares[crdsY - 1][crdsX]) {
                    const upEls = []
                    i = 1
                    while (crdsY - i >= 0) {
                        upEls.push([crdsY - i,crdsX])
                        i++;
                    }
                    elObject.directions.push(upEls)
                }
    
                // Check up right
                if (crdsX !== 7 && crdsY !== 0 && squares[crdsY - 1][crdsX + 1]) {
                    const urEls = []
                    i = 1
                    while (crdsY - i >= 0 && crdsX + i <= 7) {
                        urEls.push([crdsY - i,crdsX + i])
                        i++;
                    }
                    elObject.directions.push(urEls)
                }
                // Check right
                if (crdsX !== 7 && squares[crdsY][crdsX + 1]) {
                    const rightEls = []
                    i = 1
                    while (crdsX + i <= 7) {
                        rightEls.push([crdsY,crdsX + i])
                        i++;
                    }
                        elObject.directions.push(rightEls)
                }
                // Check down right
                if (crdsX !== 7 && crdsY !== 7 && squares[crdsY + 1][crdsX + 1]) {
                    const rightEls = []
                    i = 1
                    while (crdsY + i <= 7 && crdsX + i <= 7) {
                        rightEls.push([crdsY + i,crdsX + i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check down
                if (crdsY !== 7 && squares[crdsY + 1][crdsX]) {
                    const rightEls = []
                    i = 1
                    while (crdsY + i <= 7) {
                        rightEls.push([crdsY + i,crdsX])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check down left
                if (crdsY !== 7 && crdsX !== 0 && squares[crdsY + 1][crdsX - 1]) {
                    const rightEls = []
                    i = 1
                    while (crdsY + i <= 7 && crdsX - i >= 0) {
                        rightEls.push([crdsY + i,crdsX - i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check left
                if (crdsX !== 0 && squares[crdsY][crdsX - 1]) {
                    const rightEls = []
                    i = 1
                    while (crdsX - i >= 0) {
                        rightEls.push([crdsY,crdsX - i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                // Check up left
                if (crdsX !== 0 && crdsY !== 0 && squares[crdsY  - 1][crdsX - 1]) {
                    const rightEls = []
                    i = 1
                    while (crdsY - i >= 0 && crdsX - i >= 0) {
                        rightEls.push([crdsY - i,crdsX - i])
                        i++;
                    }
                    elObject.directions.push(rightEls)
                }
                
    
                if (elObject.directions.length !== 0) {
                    cordAndDirs.push(elObject)
                }
    

    And also I changed the the game board onClick property a bit like this:

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