I have segmentation fault while calling upon the recalling function "OpenCell", It doesn't want to continue no matter what. I know it's a logical mistake I just haven't figured it out yet and I am too new to C to be able to solve this on my own.
P.S the code as you can see is quite unfinished, I just want to be able to continue but I won't be able if I don't get past this point.
I've tried placing some "printf's" inside the 'OpenCell' to see where it stalls. As it turned out it dumps the core upon the call of the function. Nothing else happens. here's the code:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <string.h>
void PrintMinefield(int row, int col, int ***CPUminefield, int ***playerminefield, int ***emptyminefield);
void OpenCell(int MineSum, int row, int col,int ***CPUminefield,int ***playerminefield,int ***emptyminefield);
void MarkCell(int ***playerminefield);
void return_array(int ***a, int ***b, int Wdth, int Hgt);
void freeArray(int **a, int Hgt);
int main(void)
{
int Hgt, Wdth, MineSum,i,j,mines=0,X,Y,count=0; //count still unused
int **CPUminefield;
int **playerminefield;
int **emptyminefield;
double prcntg=1; //1 = 100%
char ch[50];
char diff[50];
//Welcoming Messages//
printf("Welcome to the Minesweeper, please insert the dimensions of the field to start the game.\nThe values are Height x Width (Max Dimensions are: 30x30 and Minimum are: 5x5)\n");
while(1)
{
scanf("%d%d",&Hgt,&Wdth);
if ((Hgt > 30) && (Wdth <= 30))
{
printf("The Height you set exceeds the program limits, please insert the dimensions again\n");
continue;
}
else if ((Wdth > 30) && (Hgt <= 30))
{
printf("The Width you set exceeds the program limits, please insert the dimensions again\n");
continue;
}
else if ((Wdth > 30) && (Hgt > 30))
{
printf("Both dimensions you set exceed the program limits, please insert them again\n");
continue;
}
else if (((Wdth < 5) && (Wdth >= 0)) || ((Hgt < 5) && (Hgt >= 0)))
{
printf("Can't insert values less than bare minimum ones, please insert valid values\n");
continue;
}
else if ((Wdth < 0) || (Hgt < 0))
{
printf("Can't insert negative values, insert positive values only!\n");
continue;
}
else
break;
}
fflush(stdin);
printf("Type in the difficulty level:\n Easy (10%% mines)\n Medium (15%% mines)\n Hard (20%% mines)\n Impossible (25%% mines)\n");
while(1)
{
scanf("%s", diff);
if ((strcmp(diff, "Easy") != 0) && (strcmp(diff, "easy") != 0) && (strcmp(diff, "Medium") != 0) && (strcmp(diff, "medium") != 0) && (strcmp(diff, "Hard") != 0) && (strcmp(diff, "hard") != 0) && (strcmp(diff, "Impossible") != 0) && (strcmp(diff, "impossible") != 0))
{
printf("Wrong Input, Try Again\n");
continue;
}
else
break;
}
fflush(stdin);
if ((strcmp(diff, "Easy") == 0) || (strcmp(diff, "easy") == 0))
prcntg = 0.1;
else if ((strcmp(diff, "Medium") == 0) || (strcmp(diff, "medium") == 0))
prcntg = 0.15;
else if ((strcmp(diff, "Hard") == 0) || (strcmp(diff, "hard") == 0))
prcntg = 0.2;
else if ((strcmp(diff, "Impossible") == 0) || (strcmp(diff, "impossible") == 0))
prcntg = 0.25;
//Mines Calculation//
MineSum = Hgt*Wdth*prcntg; //Ligo Douelai edw meta//
//Minefield Calculation//
return_array(&playerminefield, &CPUminefield, Wdth, Hgt);
emptyminefield = (int **) malloc (Hgt * sizeof(int*));
printf(" ");
for(i=0; i<Wdth; i++)
{
if(i<9)
printf(" %d ", i+1);
else
printf("%d ", i+1);
}
printf("\n");
for(i=0; i<Wdth; i++)
{
if(i==0)
printf(" ");
printf("---"); /* length of - */
}
printf("\n");
for (i=0;i<Hgt;i++)
{
emptyminefield[i]=(int*) malloc (Wdth * sizeof(int));
if (i<9)
printf(" %d| ", i+1);
else
printf("%d| ", i+1);
for (j=0;j<Wdth;j++)
{
emptyminefield[i][j]='#';
printf(" %c ",emptyminefield[i][j]);
}
printf("\n");
}
printf("\n");
//Placing Mines//
srand(time(NULL));
for (i=0;i<Hgt;i++)
{
for (j=0;j<Wdth;j++)
{
playerminefield[i][j] = emptyminefield[i][j] = CPUminefield[i][j] = '.';
}
}
while (mines < MineSum)
{
i= rand()%(Hgt); //WARNING
j= rand()%(Wdth); //
if (CPUminefield[i][j] != '@')
{
CPUminefield[i][j] = '@';
playerminefield[i][j] = CPUminefield[i][j];
mines++;
}
}
for (i=0;i<Wdth;i++)
{
for (j=0;j<Hgt;j++)
{
if(CPUminefield[i][j] != '@')
{
CPUminefield[i][j] = 0;
}
if((CPUminefield[i-1][j] == '@') && CPUminefield[i][j] != '@') //North
{
CPUminefield[i][j]++;
}
if((CPUminefield[i+1][j] == '@') && CPUminefield[i][j] != '@') //South
{
CPUminefield[i][j]++;
}
if((CPUminefield[i][j+1] == '@') && CPUminefield[i][j] != '@') //East
{
CPUminefield[i][j]++;
}
if((CPUminefield[i][j-1] == '@') && CPUminefield[i][j] != '@') //West
{
CPUminefield[i][j]++;
}
if((CPUminefield[i-1][j+1] == '@') && CPUminefield[i][j] != '@') //North-East
{
CPUminefield[i][j]++;
}
if((CPUminefield[i-1][j-1] == '@') && CPUminefield[i][j] != '@') //North-West
{
CPUminefield[i][j]++;
}
if((CPUminefield[i+1][j+1] == '@') && CPUminefield[i][j] != '@') //South-East
{
CPUminefield[i][j]++;
}
if((CPUminefield[i+1][j-1] == '@') && CPUminefield[i][j] != '@') //South-West
{
CPUminefield[i][j]++;
}
}
}
//Game Menu//
printf(" Choose your move(s):\n");
printf(" open : Opens the selected square\n");
printf(" mark : Marks the selected square\n");
printf(" cheat : Reveals the information about the square\n");
printf(" exit : Self explanatory\n");
while(1)
{
scanf("%s", ch);
if((strcmp(ch, "open") != 0) && (strcmp(ch, "mark") != 0) && (strcmp(ch, "cheat") != 0) && (strcmp(ch, "exit") != 0) && (strcmp(ch, "Open") != 0) && (strcmp(ch, "Mark") != 0) && (strcmp(ch, "Cheat") != 0) && (strcmp(ch, "Exit") != 0)) //String Comparisent//
{
if (strlen(ch) > 10)
{
printf("Woah! Did your cat run over your keyboard? The input is too long, Try Again\n"); //Easter Egg//
continue;
}
printf("Wrong Input, Try Again\n");
continue;
}
else
break;
}
fflush(stdin);
if ((strcmp(ch, "exit") == 0) || strcmp(ch, "Exit") == 0)
{
printf("Goodbye!\n");
exit(0);
}
// Function to printt out the minefield// P,S Edw ta paretisa kai to evala function giati den mborousa allo me to loop debugging...
OpenCell(MineSum,Hgt,Wdth,&CPUminefield,&playerminefield,&emptyminefield);
PrintMinefield(Hgt,Wdth,&CPUminefield,&playerminefield,&emptyminefield);
// Last Step, Clearing Memmory //
freeArray(playerminefield,Hgt);
freeArray(CPUminefield,Hgt);
freeArray(emptyminefield,Hgt);
return 0;
}
void return_array(int ***arr1, int ***arr2, int Wdth, int Hgt)
{
int i;
*arr1 = (int **) malloc (Hgt * sizeof(int *));
for (i=0;i<Hgt;i++)
{
(*arr1)[i] = (int*) malloc (Wdth * sizeof(int));
}
*arr2 = (int **) malloc (Hgt * sizeof(int *));
for (i=0;i<Hgt;i++)
{
(*arr2)[i] = (int*) malloc (Wdth * sizeof(int));
}
}
void PrintMinefield(int row, int col, int ***CPUminefield, int ***playerminefield, int ***emptyminefield)
{
int i,j;
printf(" ");
for(i=0; i<col; i++)
{
if(i<9)
printf(" %d ", i+1);
else
printf("%d ", i+1);
}
printf("\n");
for(i=0; i<col; i++)
{
if(i==0)
printf(" ");
printf("---"); /* length of - */
}
printf("\n");
for (i=0;i<row;i++)
{
if (i<9)
printf(" %d| ", i+1);
else
printf("%d| ", i+1);
for (j=0;j<col;j++)
{
if ((*emptyminefield)[i][j] == '#')
{
printf(" %c ",(*playerminefield)[i][j]);
}
else if ((*CPUminefield)[i][j] == 0)
{
(*emptyminefield)[i][j] = '.';
printf(" %c ",(*emptyminefield)[i][j]);
}
else
{
printf(" %d ",(*emptyminefield)[i][j]);
}
}
printf("\n");
}
printf("\n");
}
void OpenCell(int MineSum, int row, int col,int ***CPUminefield,int ***playerminefield,int ***emptyminefield)
{
int j,i,count=0,sum=0,X,Y;
if (count != 0)
{
PrintMinefield(row,col,CPUminefield,playerminefield,emptyminefield);
count++;
printf("Test\n");
}
for (i=0;i<row;i++)
{
for (j=0;j<col;j++)
{
if ((*emptyminefield)[i][j] == (*CPUminefield)[i][j])
sum++;
}
printf("Test\n");
}
if( sum == ((row * col) - MineSum))
{
printf("Wow!, You Won! Congratulations.\n"); // Na teleiwsw edw //
exit(0);
}
printf("Test\n");
printf("Give X and Y values for 'Open' command, seperated by a comma\n");
while(1){
scanf("%d,%d",&X,&Y);
fflush(stdin);
if ((X < 1) || (X > (row+1)) || (Y < 1) || (Y > (col+1)))
{
printf("Incorrect Values and/or incorrect input method, Try Again\n");
continue;
}
else
break;
}
printf("Test\n");
//ADD X++;
//ADD Y--;
if ((*CPUminefield)[X][Y] == '@')
{
printf("You've Hit Mine! You Lost :(...\n");
exit(0); // Na teleiwsw edw //
}
if ((*emptyminefield)[X][Y] != '#')
{
printf("Already Opened Cell, Give New Values\n");
PrintMinefield(row,col,CPUminefield,playerminefield,emptyminefield);
}
else
{
(*emptyminefield)[X][Y] = (*CPUminefield)[X][Y];
if ((*CPUminefield)[X][Y] == 0)
{
if((*CPUminefield)[X-1][Y] == 0) //North check for segmentation core dumped
{
(*emptyminefield)[X-1][Y] = (*CPUminefield)[X-1][Y];
}
if((*CPUminefield)[X+1][Y] == 0) //South
{
(*emptyminefield)[X+1][Y] = (*CPUminefield)[X+1][Y];
}
if((*CPUminefield)[X][Y+1] == 0 ) //East
{
(*emptyminefield)[X][Y+1] = (*CPUminefield)[X][Y+1];
}
if((*CPUminefield)[X][Y-1] == 0 ) //West
{
(*emptyminefield)[X][Y-1] = (*CPUminefield)[X][Y-1];
}
if((*CPUminefield)[X-1][Y+1] == 0 )//North-East
{
(*emptyminefield)[X-1][Y+1] = (*CPUminefield)[X-1][Y+1];
}
if((*CPUminefield)[X-1][Y-1] == 0 )//North-West
{
(*emptyminefield)[X-1][Y-1] = (*CPUminefield)[X-1][1];
}
if((*CPUminefield)[X+1][Y+1] == 0 )//South-East
{
(*emptyminefield)[X-1][Y+1] = (*CPUminefield)[X-1][Y+1];
}
if((*CPUminefield)[X+1][Y-1] == 0 )//South-West
{
(*emptyminefield)[X+1][Y-1] = (*CPUminefield)[X+1][Y-1];
}
}
OpenCell(MineSum,row,col,CPUminefield,playerminefield,emptyminefield);
}
}
void freeArray(int **a, int Hgt)
{
int i;
for(i=0;i<Hgt;i++)
{
free(a[i]);
}
free(a);
}
You have multiple statements in your code which cause Undefined Behavior. You access elements out of boundaries multiple times.
One example is CPUminefield[i - 1][j]
. What if i
is 0? You access some data you don't own. Same goes with j - 1
. And you also have the same kind of error at i + 1
, or j + 1
, when they are Wdth - 1
or Hgt - 1
, because you will access the element at index Wdth
or again Hgt
which are again out of boundaries, just in the opposite direction. All of this results in UB.
I didn't exactly look at what you use these loops for because well it's not commented and I am lazy. But you might just want to ensure you access valid elements for each of this lines. Just add something like the following code for i
and j
each time you access something with eiter +1 or -1:
if (i > 0 && i < Wdth - 1)
// only now acces data with either "- 1" or "+ 1"
You need to change this in your main()
function and in OpenCell()
.