Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

JavaScript Object-Oriented JavaScript: Challenge Adding the Game Logic Build the checkForWin() Method

My tested version of the checkForWin() method

/**
     * Checks if the active players wins when the token is dropped.
     * @return {boolean} Returns true if the player wins, otherwise false.
     */
    checkForWin(target) {
        const player_id = this.activePlayer.id;
        const spaces = this.board.spaces;
        const n_cols = this.board.cols;
        const n_rows = this.board.rows;
        const t_x = target.x;
        const t_y = target.y;

        // Checks the Horizontal line
        let sum = 1;
        for (let i of [-3, -2, -1, 1, 2, 3]) {
            if (t_x + i >= 0 && t_x + i <= n_cols - 1) {
                if ((spaces[t_x + i][t_y].owner !== null) && (spaces[t_x + i][t_y].owner.id === player_id)) {
                    sum += 1;
                    if (sum >= 4) {
                        return true;
                    }
                } else {
                    sum = 1;
                }
            }
        }


        // Checks the Vertical line
        sum = 1;
        for (let i of [-3, -2, -1, 1, 2, 3]) {
            if (t_y + i >= 0 && t_y + i <= n_rows - 1) {
                if ((spaces[t_x][t_y + i].owner !== null) && (spaces[t_x][t_y + i].owner.id === player_id)) {
                    sum += 1;
                    if (sum >= 4) {
                        return true;
                    }
                } else {
                    sum = 1;
                }
            }
        }

        // Check the diagonal line
        // a) Bottom Left - Top right
        sum = 1;
        for (let i of [-3, -2, -1, 1, 2, 3]) {

            if (t_x + i >= 0 && t_x + i <= n_cols - 1 && t_y + i >= 0 && t_y + i <= n_rows - 1) {
                if (
                    (spaces[t_x + i][t_y + i].owner !== null) &&
                    (spaces[t_x + i][t_y + i].owner.id === player_id)
                ) {
                    sum += 1;
                    if (sum >= 4) {
                        return true;
                    }
                } else {
                    sum = 1;
                }
            }

        }


        // b) Top left - Bottom right
        sum = 1;
        for (let i of [-3, -2, -1, 1, 2, 3]) {
            if (t_x + i >= 0 && t_x + i <= n_cols - 1 && t_y - i >= 0 && t_y - i <= n_rows - 1) {
                if (
                    (spaces[t_x + i][t_y - i].owner !== null) &&
                    (spaces[t_x + i][t_y - i].owner.id === player_id)
                ) {
                    sum += 1;
                    if (sum >= 4) {
                        return true;
                    }
                } else {
                    sum = 1;
                }
            }
        }

        return false;
    }

This method is tested and seems that it can work properly without checking all spaces on the board. I'd appreciate any feedback on this and let me know if you have ideas to make it better!

I really liked your use of the for...of loop. I had done something similar, but just looped from -3 to 3, which had an irrelevant check on the current token.

Your check on the vertical line could be improved a little. It doesn't need to check backwards/up because there will never be a token above the last dropped token. So you could change

        // Checks the Vertical line
        sum = 1;
        for (let i of [-3, -2, -1, 1, 2, 3]) {

to

        // Checks the Vertical line
        sum = 1;
        for (let i of [1, 2, 3]) {

One other thing is that I'm unsure of the comparison of the owner.id with the player_id. Is there a reason for doing that instead of just comparing the Player object with spaces[t_x + i][t_y + i].owner against target.owner? I think that might be an extra, unnecessary step you could remove.

1 Answer

Simon Coates
Simon Coates
8,481 Points

What I tried was

    //I think this was meant to returns space or undefined
    getNext(current, displacement){        
        let col = this.board.spaces[current.x + displacement.x];
        if(col) {
            return col[current.y + displacement.y];  
        }
    }
    getInvertedDirection(direction){
        return { 'x': direction.x * -1,
        'y': direction.y * -1};
    }

    checkForWin(dropSpace){
        let currentOwner = this.activePlayer.activeToken.owner;

        let hasWon = false;

        let directions = [{ 'x': 1, 'y': 0}, 
         { 'x': 0, 'y': 1},
         { 'x': -1, 'y': 1},
         { 'x': 1, 'y': 1}
        ];
        for(let i = 0; i< directions.length; i++)
        {
            let direction = directions[i];              
            //count forward
            let nextSpace = dropSpace;
            let count = 1;
            for(let i = 0; i< 3; i++){                
                nextSpace = this.getNext(nextSpace, direction);
                if(nextSpace && nextSpace.owner === currentOwner) {
                    count++;
                } else {
                    break;
                }               
            }

            //count back
            direction = this.getInvertedDirection(direction);
            nextSpace = dropSpace;            
            for(let i = 0; i< 3; i++){                
                nextSpace = this.getNext(nextSpace, direction);
                if(nextSpace && nextSpace.owner === currentOwner) {
                    count++;
                } else {
                    break;
                }               
            }

            if(count >= 4){
                hasWon = true;
                break;
            }            
        }

        if(hasWon){
            console.log("you have won");
        }        
    }

I haven't really tested it, but I think it's probably doing something similar to your approach. I could also shorten it so that the code for walking forward (and back) while counting is in its own method. The final code would hopefully read well.