Problemas con el juego de acorazado en C

So i've been trying to write a sink the battleship game in C. I already wrote a simple version with randomly generated booleans however i was not happy with ships being only one block in size and there were too many of them, but i digress.

Here i've wrote what i believe is a messy piece of code, and it works, sometimes...

Aquí es:

void generate_field(int *i, int *j, int n)
{
    *i=rand()%n;
    *j=rand()%n;
}
void map_gen(struct game *data,int n)
{
    int i,j,k,l;
    int return_value=0;

    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            data->tiles[i][j].ship=0;
            data->tiles[i][j].uncovered=0;
        }
    }

//    **4**
    generate_field(&k,&l,n);
    if(k==0 || k==1)
    {
        data->tiles[k][l].ship=4;
        data->tiles[k+1][l].ship=4;
        data->tiles[k+2][l].ship=4;
        data->tiles[k+3][l].ship=4;
        data->shipcount++;
    }
    else if(k==(n-1) || k==(n-2))
    {
        data->tiles[k][l].ship=4;
        data->tiles[k-1][l].ship=4;
        data->tiles[k-2][l].ship=4;
        data->tiles[k-3][l].ship=4;
        data->shipcount++;
    }
    else if(l==0 || l==1)
    {
        data->tiles[k][l].ship=4;
        data->tiles[k][l+1].ship=4;
        data->tiles[k][l+2].ship=4;
        data->tiles[k][l+3].ship=4;
        data->shipcount++;
    }
    else if(l==(n-1) || l==(n-2))
    {
        data->tiles[k][l].ship=4;
        data->tiles[k][l-1].ship=4;
        data->tiles[k][l-2].ship=4;
        data->tiles[k][l-3].ship=4;
        data->shipcount++;
    }
//    **3**
    do{
    generate_field(&k,&l,n);
    }while(data->tiles[k][l].ship!=0 && (data->tiles[k+1][l].ship!=0 || data->tiles[k-1][l].ship!=0 || data->tiles[k][l+1].ship!=0 || data->tiles[k][l-1].ship!=0) && (data->tiles[k+2][l].ship!=0 || data->tiles[k-2][l].ship!=0 || data->tiles[k][l+2].ship!=0 || data->tiles[k][l-2].ship!=0));
    if((k==0 || k==1) && (data->tiles[k+1][l].ship==0 && data->tiles[k+2][l].ship==0))
    {
        data->tiles[k][l].ship=3;
        data->tiles[k+1][l].ship=3;
        data->tiles[k+2][l].ship=3;
        data->shipcount++;
    }
    else if((k==(n-1) || k==(n-2)) && (data->tiles[k-1][l].ship==0 && data->tiles[k-2][l].ship==0))
    {
        data->tiles[k][l].ship=3;
        data->tiles[k-1][l].ship=3;
        data->tiles[k-2][l].ship=3;
        data->shipcount++;
    }
    else  if((l==0 || l==1) && (data->tiles[k][l+1].ship==0 && data->tiles[k][l+2].ship==0))
    {
        data->tiles[k][l].ship=3;
        data->tiles[k][l+1].ship=3;
        data->tiles[k][l+2].ship=3;
        data->shipcount++;
    }
    else if((l==(n-1) || l==(n-2)) && (data->tiles[k][l-1].ship==0 && data->tiles[k][l-2].ship==0))
    {
        data->tiles[k][l].ship=3;
        data->tiles[k][l-1].ship=3;
        data->tiles[k][l-2].ship=3;
        data->shipcount++;
    }
//    **2**
    do{
    generate_field(&k,&l,n);
    }while(data->tiles[k][l].ship!=0 && (data->tiles[k+1][l].ship!=0 || data->tiles[k-1][l].ship!=0 || data->tiles[k][l+1].ship!=0 || data->tiles[k][l-1].ship!=0));
    if((k==0 || k==1) && (data->tiles[k+1][l].ship==0))
    {
        data->tiles[k][l].ship=2;
        data->tiles[k+1][l].ship=2;
        data->shipcount++;
    }
    else if((k==(n-1) || k==(n-2)) && (data->tiles[k-1][l].ship==0))
    {
        data->tiles[k][l].ship=2;
        data->tiles[k-1][l].ship=2;
        data->shipcount++;
    }
    else if((l==0 || l==1) && (data->tiles[k][l+1].ship==0))
    {
        data->tiles[k][l].ship=2;
        data->tiles[k][l+1].ship=2;
        data->shipcount++;
    }
    else if((l==(n-1) || l==(n-2)) && (data->tiles[k][l-1].ship==0))
    {
        data->tiles[k][l].ship=2;
        data->tiles[k][l-1].ship=2;
        data->shipcount++;
    }

//    **1**
    do{
    generate_field(&k,&l,n);
    }while(data->tiles[k][l].ship!=0);
    data->tiles[k][l].ship=1;
    data->shipcount++;
}

los **#** are ship sizes.

los int n is the size of a dimension of the matrix array(i have two sizes:Normal which is 5x5 and large which is 8x8)

Anyway i know this could be written in a way simpler way and that it could actually work. The do-while loops are way too long and a lot of the times one or two my ships don't generate. I think it's because i somewhat limited their spawn by using(k==0 or k==n-1) stuff, however i have no idea what to do. Can anyone here give me some hints of how could have i written this differently and more compact and in a way in which it actually works right?

preguntado el 01 de febrero de 12 a las 14:02

You're a bit off-topic, I think. Try posting on revisión de código. -

The easiest way is probably to get a position at random, and try to place your ship there. If it doesn't work, try another random position. -

I would break it down differently. For each ship to place, I would first select the orientation (vertical, horizontal, or one of the diagonals -- if you allow that). Once the orientation is set, that gives you a range of coordinates for the, say, top-left corner of the rectangle containing the ship (for example, a 4-block horizontal ship can be placed at column 0 to n-4, row 0 to n-1). Select that. If the ship doesn't overlap ships already placed on the gird, you're golden -- mark it down. If it does, repeat from choosing the orientation. Do this for each ship. -

Write smaller functions that do one thing well such as placing a ship, picking a vertical or horizontal place based on ship size, checking if a place is occupied already, etc. -

1 Respuestas

The problem is with how you determine location and direction for the ship.

Me gustaría hacer esto:

void place_ship(struct game* data, int n, int shipsize)
{
    int x = 0, y = 0;  // Uesd for ship direction

    // Generate a direction
    if (rand()%2) {
        i=rand()%(n - shipsize + 1);
        j=rand()%n;
        x = 1;
        y = 0;
    } else {
        i=rand()%n;
        j=rand()%(n - shipsize + 1);
        x = 0;
        y = 1;
    }

    for (k = 0; k < shipsize; k++) {
        if (data->tiles[i + x * k][j + y * k].ship != 0) {
            // Space already occupied - retry!
            return place_ship(data, n, shipsize);
        }
    }
    for (k = 0; k < shipsize; k++) {
         data->tiles[i + x * k][j + y * k].ship = shipsize;
    }
}

Respondido 01 Feb 12, 18:02

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