Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Win conditions for a connect-4 like game

Tags:

c++

arrays

I have an 5x10 array that is populated with random values 1-5. I want to be able to check when 3 numbers, either horizontally, or vertically, match. I can't figure out a way to do this without writing a ton of if statements.

Here is the code for the randomly populated array


int i;
int rowincrement = 10;
int row = 0;
int col = 5;
int board[10][5];
int randomnum = 5;


int main(int argc, char * argv[])
{
    srand(time(NULL));

    cout &lt&lt "============\n";

    while(row &lt rowincrement)
    {

        for(i = 0; i &lt 5; i++)
        {
            board[row][col] = rand()%5 + 1; 
            cout &lt&lt board[row][col] &lt&lt " ";
        }
        cout &lt&lt endl;
        cout &lt&lt "============\n";
        row++;
    }
    cout &lt&lt endl;
    return 0;
}

like image 739
finfet Avatar asked Dec 01 '25 08:12

finfet


1 Answers

Suppose that you have some particular starting point (x, y) and you're curious if there's three equal numbers in a row that start at this point. Let's consider just the case where you're looking in the horizontal direction. Then one way to do this (ignoring bounds-checking) would be like this:

bool IsHorizontalMatch(int x, int y) {
    /* Get the value of the start position. */
    const int startValue = board[x][y];

    /* Confirm the two values after it match. */
    for (int i = 1; i < 3; ++i)
        if (board[x + i][y] != startValue)
            return false;

    /* If we got here, then they all match! */
    return true;
}

You could similarly write a function like this for checking vertically:

bool IsVerticalMatch(int x, int y) {
    /* Get the value of the start position. */
    const int startValue = board[x][y];

    /* Confirm the two values after it match. */
    for (int i = 1; i < 3; ++i)
        if (board[x][y + i] != startValue)
            return false;

    /* If we got here, then they all match! */
    return true;
}

And finally, one for the diagonals:

bool IsDiagonalDownMatch(int x, int y) {
    /* Get the value of the start position. */
    const int startValue = board[x][y];

    /* Confirm the two values after it match. */
    for (int i = 1; i < 3; ++i)
        if (board[x + i][y + i] != startValue)
            return false;

    /* If we got here, then they all match! */
    return true;
}

bool IsDiagonalUpMatch(int x, int y) {
    /* Get the value of the start position. */
    const int startValue = board[x][y];

    /* Confirm the two values after it match. */
    for (int i = 1; i < 3; ++i)
        if (board[x + i][y - i] != startValue)
            return false;

    /* If we got here, then they all match! */
    return true;
}

This works, but it's just not very elegant; all three of these functions look very similar! Fortunately, you can rewrite all of them in terms of a single unifying function. The idea is this - if you'll notice, all three functions work by having some "step size" defined indicating what direction you move. In the horizontal case, the step is (+1, +0), in the vertical case it's (+0, +1), and in the diagonal it's (+1, +1) or (+1, -1). Given this, you can write one function to check if three values match in a line:

bool IsLinearMatch(int x, int y, int stepX, int stepY) {
    /* Get the value of the start position. */
    const int startValue = board[x][y];

    /* Confirm the two values after it match. */
    for (int i = 1; i < 3; ++i)
        if (board[x + i * stepX][y + i * stepY] != startValue)
            return false;

    /* If we got here, then they all match! */
    return true;
}

You can then write

bool IsLineStartingAt(int x, int y) {
    return (IsLinearMatch(x, y, 1,  0) ||  // Horizontal
           IsLinearMatch(x, y, 0,  1)  ||  // Vertical
           IsLinearMatch(x, y, 1,  1)  ||  // Diagonal Down
           IsLinearMatch(x, y, 1, -1));    // Diagonal Up
}

Given this primitive, you can check for all possible matches by just iterating over all possible starting points.

Hope this helps!

EDIT: Thanks to commenters for helping to fix my silly bugs. :-)

like image 84
templatetypedef Avatar answered Dec 03 '25 20:12

templatetypedef



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!