Reputation: 1487
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...
Here it is:
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++;
}
the **#**
are ship sizes.
the 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?
Upvotes: 0
Views: 1317
Reputation: 33283
The problem is with how you determine location and direction for the ship.
I would do like this:
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;
}
}
Upvotes: 1