Gana condiciones para un juego similar a Connect-4

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 << "============\n";

    while(row < rowincrement)
    {

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

preguntado el 08 de enero de 11 a las 22:01

Is this homework? What have you tried? -

Its not homework, but basically I have over 50 if statements saying if row[0] == row[1] && row[2], then... but I still don't have all the combinations and I know there must be a better way. -

3 Respuestas

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;
}

Entonces puedes escribir

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.

¡Espero que esto ayude!

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

Respondido 01 Abr '18, 08:04

How would I know the starting position if the numbers are randomly generated? - Frozen Wasteland

The idea is that you'd put this in a loop trying all start positions. When this function returns true, you know that you have the start position and can stop looping. The fact that the numbers are random shouldn't make much of a difference here. - templatetypedef

Don't those diagonals both check the same orientation? I mean, bottom left to top right is the same as top right to bottom left, just from a different starting point. I think you need to fix the x-step and use opposite y-steps (or vice-versa). - Grossvogel

para el registro:

Creo que quieres decir

for(i = 0; i < 5; i++)
{
    board[row][i] = rand()%5 + 1; 
    cout << board[row][i] << " ";
}

And since others posted Code, here is how I would do it :

for(int i = 0 ; i < 8 ; i++)
{
    for(int j = 0 ; j < 3 ; j++)
    {

        if( ((board[i][j] == board[i][j+1]) && (board[i][j+1] == board[i][j+2])))
            std::cout << "Found a horizontal match on " << i << " " << j << std::endl;

        if((board[i][j] == board[i+1][j]) && (board[i+1][j] == board[i+2][j]))
            std::cout << "Found a vertical match on " << i << " " << j << std::endl;
    }
}

Respondido el 09 de enero de 11 a las 01:01

I think this should work ; If any one point out the mistake, I would be happy to correct.

for( int row = 0; row<8 ; ++row )
{
    bool outerLoopBreakFlag = false ;
    for( int col=0 ; col<3; ++col )
    {
         // check for the winning conditions
         // i.e., board[row][col] == board[row][col+1] == board[row][col+2]
         //       board[row][col] == board[row+1][col] == board[row+2][col]
         //       if any one is satisfied, set the outerLoopBreakFlag to true
         else
             break ;
    }
    if( outerLoopBreakFlag == true )
        break ;
}              

Respondido el 09 de enero de 11 a las 02:01

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.