i am writing a simple simulator of spilling eggs in а pan with the flood fill algorithm in C. So the pan is a char matrix, and with '#' are his walls,'.' means that the place is empty and 'O' that it has a egg that will spill.
That is an example of what that program should do.
10 10
..##......
.#O.#.....
.#..#..#..
..##..#.#.
.......#..
..#####...
..#...#...
..#...##..
...##..#..
....####..
⇨
..##......
.#OO#.....
.#OO#..#..
..##..#.#.
.......#..
..#####...
..#***#...
..#***##..
...##**#..
....####..
i have written that:
#include <stdio.h>
void food_fill(int,int,char [1000][1000],int,int,char);
int main(){
int row,col,rows,cols;
scanf("%d %d",&rows,&cols);
getchar();
char matrix [rows][cols];
for(row = 0;row < rows;row++){
for(col = 0;col < cols;col++){
scanf("%c",&matrix[row][col]);
}
getchar();
}
int foodX=0,foodY=0;
char foodChar='s';
for(row=0;row<rows;row++){
for(col = 0;col < cols;col++){
if(matrix[row][col] == 'O'){
foodX = row;
foodY = col;
foodChar = matrix[row][col];
}
}
}
food_fill(rows,cols,matrix,foodX,foodY,foodChar);
for(row = 0;row < rows;row++){
for(col = 0;col <cols;col++){
printf("%c",matrix[row][col]);
}
printf("\n");
}
return 0;
}
void food_fill(int rows,int cols,char matrix[rows][cols],int foodX,int foodY,char foodChar){
int r=rows,c=cols;
if(matrix[foodX][foodY] == '#')return;
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
matrix[foodX][foodY] = foodChar;
food_fill(r,c,matrix,foodX+1,foodY,foodChar);
food_fill(r,c,matrix,foodX-1,foodY,foodChar);
food_fill(r,c,matrix,foodX,foodY+1,foodChar);
food_fill(r,c,matrix,foodX,foodY-1,foodChar);
}
It is not completed yet but the food_fill() function resulted in segmentation fault and i don't know why.
if(matrix[foodX][foodY] == '#')return;
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
Order is wrong. As a result you are accessing invalid indices. Giving you segmentation fault. Correct one would be
if(foodX < 0 || foodX >= rows || foodY < 0 || foodY >= cols)return;
if(matrix[foodX][foodY] == '#')return;
Also there are bugs on many levels.
You are having an infinite loop due to repetitive similar calls.
int dx[]={1,0,-1,0};
int dy[]={0,1,0,-1};
void food_fill(int rows,int cols,char matrix[][cols],int foodX,int foodY,char foodChar){
matrix[foodX][foodY] = foodChar;
for(int i=0;i<4;i++){
if( foodX+dx[i]>=0 && foodX+dx[i]<rows && foodY+dy[i] >=0 && foodY+dy[i]<cols && matrix[foodX+dx[i]][foodY+dy[i]] != '#' && matrix[foodX+dx[i]][foodY+dy[i]]!=foodChar){
food_fill(rows,cols,matrix,foodX+dx[i],foodY+dy[i],foodChar);
}
}
}
The main condition change is
if( foodX+dx[i]>=0 && foodX+dx[i]<rows && foodY+dy[i] >=0 && foodY+dy[i]<cols && matrix[foodX+dx[i]][foodY+dy[i]] != '#' && matrix[foodX+dx[i]][foodY+dy[i]]!=foodChar){
Related
I've a matrix with size 7x7 that represents a game board. When a player makes a move, the program has to check the positions around the coordinates where the piece is, in order to detect another piece aside.
I use this function:
int check_position(COORDINATES coordinates, char board[7][7]) {
int result = -1;
if (board[coordinates.x][coordinates.y] != 'O' && board[coordinates.x-1][coordinates.y] != 'O' && board[coordinates.x][coordinates.y-1] != 'O' && board[coordinates.x+1][coordinates.y] != 'O' && board[coordinates.x][coordinates.y+1] != 'O' && board[coordinates.x-1][coordinates.y-1] != 'O' && board[coordinates.x+1][coordinates.y+1] != 'O' && board[coordinates.x-1][coordinates.y+1] != 'O' && board[coordinates.x+1][coordinates.y-1] != 'O') {
result = 1;
}
return result;
}
The first parameter are the coordinates of the player's piece as a struct, with members x and y. The second parameter is the board array.
The if statement doesn't work to well, and I don't know which alternative can I take.
Can you help me? Thanks!
You forgot about your coordinates overflowing at the borders. You can either test for this, or:
Hint: Make the array two rows and columns larger than the board and fill the border with "empty" marker. The active board will the have coordinates 1...7 This way your coordinates cannot wrap (1 - 1 and 7 + 1 are still within the array) and you do not have to care about the borders.
Note: If you just want to return a boolean value, it would be better to use stdbool.h and return a bool result. That way, the caller can directly use that function as a condition:
#include <stdbool.h>
...
bool check_position(COORDINATES coordinates, const char board[9][9]) {
int x = coordinates.x - 1
for ( int xc = 0 ; xc < 3 ; xc++ ) {
int y = coodinates.y - 1;
for ( int yc = 0 ; yc < 3 ; yc++ ) {
if ( board[x][y] != '0' )
return true;
y++;
}
x++;
}
return false;
}
Note: as you only need one one non-empty field, you can terminate instantly if you found one. That is identical to the multiple conditions. Of course, that also works for your original int result.
Note2: I modified the type of board to being const, as it is not changed inside the function.
You could also solve the edge overflow like this. Edit improved after discussion with #Olaf
#define BOARD 7
int check_position(COORDINATES coordinates, char board[BOARD][BOARD]) {
int result = -1;
int left = coordinates.x == 0 ? 0 : coordinates.x - 1;
int top = coordinates.y == 0 ? 0 : coordinates.y - 1;
int right = coordinates.x == BOARD-1 ? coordinates.x : coordinates.x + 1;
int bottom = coordinates.y == BOARD-1 ? coordinates.y : coordinates.y + 1;
if (board[left] [top] != 'O' &&
board[coordinates.x][top] != 'O' &&
board[right] [top] != 'O' &&
board[left] [coordinates.y] != 'O' &&
board[coordinates.x][coordinates.y] != 'O' &&
board[right] [coordinates.y] != 'O' &&
board[left] [bottom] != 'O' &&
board[coordinates.x][bottom] != 'O' &&
board[right] [bottom] != 'O' && )
{
result = 1;
}
return result;
}
Hey guys so Im trying to do a homework and I cant find the fatal error on my program all day long.Let me explain :
Firstly,you give the number of rows,col then the cells of the array (only "." for free spaces and "*" for mines, all in one row without spaces) then the crashing happens.
main(){
int i,col,row,count,N,M,j;
char **p;
printf("Give number of rows\n");
scanf("%d",&N);
printf("Give number of columns\n");
scanf("%d\n",&M);
p=malloc(N*sizeof(char *)); //Saving room for the array
if (p==NULL)
return -1;
for (i=0;i < N ; ++i){
p[i] = malloc (M * sizeof(char));
if (*(p+i) == NULL)
return -1;
}
for (i=0; i< N;++i){
for ( j = 0 ; j < M ;++j)
scanf("%c",&p[i][j]); //Insert "*" for mines and the rest with "."
}
for (row=1; row<= N;++row){ //Here the things get messy
for ( col = 1 ; col <= M ;++col){
if(p[row][col]=='.'){
count = 0 ;
if(p[row][col+1]=='*' && col < M)
count=count+1;
if(p[row][col-1]=='*' && col > 1)
count=count+1;
if(p[row+1][col]=='*' && row < N)
count=count+1;
if(p[row-1][col]=='*' && row > 1)
count=count+1;
if(p[row+1][col+1]=='*' && (row < N && col < M))
count=count+1;
if(p[row+1][col-1]=='*' && (row < N && col > 1))
count=count+1;
if(p[row-1][col+1]=='*' && ( row > 1 && col < M))
count=count+1;
if(p[row-1][col-1]=='*' && ( row > 1 && col > 1))
count=count+1;
printf("%d ", count);
}
printf("* ");
}
printf("\n");
}
printf("\n");
for (i=0; i< N;++i){
for ( j = 0 ; j < M ;++j)
printf("%c ",p[i][j]);
printf("\n");
}
for (i = 0 ; i <N ; ++i)
free(p[i]);
free(p);
}
Firstly, here's what I did to debug (actually I saw the problem in the code and just verified this way, but this will be useful to you).
Add #include <stdio.h> and #include <stdlib.h> at the head of the file.
gcc -Wall -O0 -g x.c -o x to compile with debug and no optimisation.
I then used following to run within gdb:
gdb x
...
(gdb) run
Starting program: /home/amb/so/x
warning: no loadable sections found in added symbol-file system-supplied DSO at 0x7ffff7ffa000
Give number of rows
1
Give number of columns
1
.
Program received signal SIGSEGV, Segmentation fault.
0x00000000004007d4 in main () at x.c:25
25 if(p[row][col]=='.'){
(gdb) print row
$1 = 1
(gdb) print col
$2 = 1
(gdb)
See how in less than 10 seconds it showed me where the error was?
You have two problems:
for (row=1; row<= N;++row){ //Here the things get messy
for ( col = 1 ; col <= M ;++col){
if(p[row][col]=='.'){
The SEGV appears here as you access p[N][M], but the indices of p can only go from 0 to N-1 and 0 to M-1 respectively. This loop should probably read:
for (row=0; row < N;++row){ //Here the things get messy
for ( col = 0 ; col < M ;++col){
if(p[row][col]=='.'){
(note change to start at row=0, and row < N not row <= M and similarly for col).
The second problem you have is to do with what to do at the edges:
Lines like this:
if (p[row][col-1]=='*' && col > 1)
count=count+1;
should have the col > 1 condition first so they don't evaluate the array element unless the condition is true. Also, as col goes 0..M-1, you want
if ((col > 0) && (p[row][col-1]=='*'))
count=count+1;
Note I've put in some brackets to avoid any ambiguity.
The same applies when looking at the other edges:
if (p[row][col+1]=='*' && col < M)
count=count+1;
should be:
if ((col < M-1) && (p[row][col+1]=='*'))
count=count+1;
That should get you going. But learn to use a debugger.
I'm having a problem where I am wanting to go through an array and check that only positive numbers have been entered. I know that it is possible to use isDigit from ctype.h but I'd rather construct something myself. The way I think it is possible, is to iterate through each element of the array and see if the value stored there is between 0 and 9, but it isn't working. This is my code so far:
char testArray[11] = {'0'};
printf("Enter a string no longer than 10 chars");
scanf("%s", testArray);
int x;
int notanumber = 0;
for (x = 0; x < 11; x++) {
if ((testArray[x] < 0) || (testArray[x] > 9)) {
notanumber++;
}
}
printf("%i", notanumber);
It is not working because 0 and 9 are integers not characters.
Change your if condition to
if((testArray[x] >= '0') || (testArray[x] <= '9')){ ... }
to check the digits from 0 to 9.
this line
if((testArray[x] < 0) || (testArray[x] > 9)){
should be replaced by
if((testArray[x] < '0') || (testArray[x] > '9')){
I am having issues creating a loop that checks to see if 5 variables are between the variables 10 and 50. I believe I have set up the correct coding, but I am getting an error saying that I cannot convert an int to a bool. Here is what I currently have:
string userName = "";
int v1, v2, v3, v4, v5 = 0;
float avg;
float variance;
Console.WriteLine("What is your name?");
userName = Console.ReadLine();
Console.WriteLine();
int i = 1;
while (i <= 5)
{
int InputCheck = 0;
Console.WriteLine("Please input a number {0} between 10 and 50;", i);
InputCheck = Convert.ToInt32(Console.ReadLine());
if (InputCheck >= 10 && InputCheck <= 50)
{
if (i >= 10 && i <= 50)
i++;
if (i != 1)
{
InputCheck = v1;
}
if (i != 2)
{
InputCheck = v2;
}
if (i == 3)
{
InputCheck = v3;
}
if (i == 4)
{
InputCheck = v4;
}
if (i == 5)
{
InputCheck = v5;
}
if (InputCheck < 10 || InputCheck > 50)
{
Console.WriteLine("The number you entered is either to high or to low please re-enter a number:");
}
}
Any help would be greatly appreciated.
I'm not 100% sure, but I think your error comes from this line:
Console.WriteLine("Please input a number {0} between 10 and 50;", i);
You are giving an int 'i', where it expects a boolean.
Maybe this will help: http://msdn.microsoft.com/en-us/library/70x4wcx1.aspx?cs-save-lang=1&cs-lang=vb#code-snippet-2
As for the rest of your code:
Calamar888 is correct, the first if statement you are using for 'i'
will never evaluate as true.
Also, the ifs that follow ( if(i !=1),
etc) will evaluate to true more than once, overwriting values that
you have already saved ( i != 1 when i = 2, 3, 4, or 5).
Inside those if statements you are changing the value of 'InputCheck', not saving it.
You should consider using arrays to make your program shorter
Your else "if (InputCheck < 10 || InputCheck > 50)" should not be inside the first if, it will never be true
Assuming that you declare:
int v[5]; /* creates array v[0], v[1], ... v[4] */
int i = 0;
while (i<=4){
/* internal code */
}
Something like this should work:
/* internal code */
if (InputCheck >= 10 && InputCheck <= 50)
{
v[i] = InputCheck;
i++;
}
else if (InputCheck < 10 || InputCheck > 50)
{
Console.WriteLine("The number you entered is either to high or to low please re-enter a number:");
}
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?
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;
}
}