Reputation: 148
I have been stuck on this task for a long time now, so I thought it was about time to ask for some help. I am making a game of battle ship and I am currently writing a function where the ships are randomly placed on the 10 x 10 grid. I have this completed, but my problem is when they overlap.
I cannot figure out a way to get coordinates where they don't overlap with a previously randomly placed ship. In my current code I am trying to figure out a way to make it so that if a coordinate overlaps it will loop the ship over again until it has the right amount of cells that do not overlap with any other ship. I am writing in a 3 file format, so I will include the needed code from each file.
In the function, the up down left or right is random, so in the battle ship I have direction = 0 so that I am only working with up
Here is the header file
typedef struct game_board
{
int board[10][10];
int row;
int col;
char symbol;
}Game_Board;
Game_Board initalize_game_board(Game_Board *player);
//Game_Board manually_place_ships_on_board(Game_Board *player);
Game_Board randomlly_place_ships_on_board(Game_Board *player);
Main
Game_Board person, computer;
int who_goes_first = 0;
person.symbol = '~';
person.row = 10;
person.col = 10;
computer.symbol = '-';
computer.row = 10;
computer.col = 10;
welcome_screen(outfile);
printf("Player 1\n");
initalize_game_board(&person);
printf("\nPlayer 2\n");
initalize_game_board(&computer);
who_goes_first = select_who_starts_first();
//manually_place_ships_on_board(&person);
randomlly_place_ships_on_board(&computer);
The function. I am only including the first 2 ship for redundancy reasons
int direction = 0, i = 0, cell_row = 0, cell_col = 0;
//Carrier
printf("CARRIER\n");
direction = rand() % 4;
printf("Direction: %d\n", direction);
player->symbol = 'c';
if (direction == 0) // up
{
cell_row = rand() % 10;
if (cell_row <= 4)
{
cell_row += 4;
}
cell_col = rand() % 10;
for (i = 0; i < 5; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("UP: Row:%d Col:%d\n", cell_row, cell_col);
cell_row -= 1;
}
}
else if (direction == 1) // down
{
cell_row = rand() % 6;
cell_col = rand() % 10;
for (i = 0; i < 5; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("DOWN: Row:%d Col:%d\n", cell_row, cell_col);
cell_row += 1;
}
}
else if (direction == 2) // left
{
cell_row = rand() % 10;
cell_col = rand() % 10;
if (cell_col <= 4)
{
cell_col += 4;
}
for (i = 0; i < 5; i++)
{
player->board[cell_row][cell_col] = player->symbol;
cell_col -= 1;
printf("LEFT: Row:%d Col:%d\n", cell_row, cell_col);
}
}
else if (direction == 3) // right
{
cell_row = rand() % 10;
cell_col = rand() % 6;
for (i = 0; i < 5; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("RIGHT: row:%d Col:%d\n", cell_row, cell_col);
cell_col += 1;
}
}
//Battle Ship
printf("BATTLE SHIP\n");
direction = rand() % 4;
printf("Direction: %d\n", direction);
player->symbol = 'b';
if (direction == 0) // up
{
cell_row = rand() % 10;
if (cell_row <= 3)
{
cell_row += 3;
}
cell_col = rand() % 10;
for (i = 0; i < 4; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("UP: Row:%d Col:%d\n", cell_row, cell_col);
cell_row -= 1;
}
}
else if (direction == 1) // down
{
cell_row = rand() % 7;
cell_col = rand() % 10;
for (i = 0; i < 4; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("DOWN: Row:%d Col:%d\n", cell_row, cell_col);
cell_row += 1;
}
}
else if (direction == 2) // left
{
cell_row = rand() % 10;
cell_col = rand() % 10;
if (cell_col <= 3)
{
cell_col += 3;
}
for (i = 0; i < 4; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("LEFT: Row:%d Col:%d\n", cell_row, cell_col);
cell_col -= 1;
}
}
else if (direction == 3) // right
{
cell_row = rand() % 10;
cell_col = rand() % 7;
for (i = 0; i < 4; i++)
{
player->board[cell_row][cell_col] = player->symbol;
printf("RIGHT: row:%d Col:%d\n", cell_row, cell_col);
cell_col += 1;
}
}
I have tried a combination of do while, while and for loops to try and get the ship to reset, but I can just not figure out a way to make this work
I could really use some guidance or a step in the right direction in order to fix this task. Thanks so much in advance!
Upvotes: 0
Views: 371
Reputation: 443
I like Joud's answer. In addition, make a "ship" struct with name and length fields. Then you can have an array of ships and in a for loop pass each ship to function:
loop(i) //pseudocode
{
randomlly_place_ship_on_board(&computer, &ship[i])
}
...
randomlly_place_ship_on_board(Game_Board *player, Ship * sh)
{
// Only takes care of one ship, sh.
// Call isAvailableCells to determine placement, like
while (!isAvailableCells...)
// re-attempt placement
}
Pseudocode may help. Check the gameboard->board for if that cell is available or not.
Upvotes: 1
Reputation: 437
The reason why you are getting overlap is because when you place your second ship, at no point do you check to see if the randomly generated cell (in terms of row and column) is actually vacant. That is, when you call rand() for your battle ship you never check to see if the column or row you get (and the neighboring ones, depending on the direction of the ship) are actually vacant or whether they are already in use by your carrier.
A simply approach would be to implement a function that checks whether the randomly generated cell is adequate or not. A possible signature would be something like:
int isAvailableCell(int cell, int direction, int ship_length);
This function takes the cell that was randomly generated, the direction of your ship and the length of your ship and it would check whether all "ship_length" cells (that is, the number of cells that the ship needs to fit in) starting from "cell" in "direction" are available. This merely involves checking whether your 2D vector has a non zero element in those cells (because you populate them when placing a ship).
If the cell is not adequate, then you need to call rand() again. Obviously, this is a brute force approach that is extremely inefficient because you might end up generating an inadequate cell multiple times but I would assume that at this point, you are not worrying about performance.
Also, A lot of the code is redundant, you can encapsulate placing a ship in a function. It will make your life much easier and your code look cleaner. Hope this helps and good luck!
Upvotes: 1