Skip to content

Instantly share code, notes, and snippets.

@omaraflak
Last active September 2, 2017 12:06
Show Gist options
  • Save omaraflak/3f4c3d61e0de390bd920b86f0473ffc1 to your computer and use it in GitHub Desktop.
Save omaraflak/3f4c3d61e0de390bd920b86f0473ffc1 to your computer and use it in GitHub Desktop.
Minesweeper in C for Windows
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <time.h>
#include <stdbool.h>
char **board;
char **displayedBoard;
const char BOMB = 'X';
const char EMPTY = 'E';
const char DISCOVERED = 'D';
const char FLAG = 'F';
bool allocateMemory(int width, int height)
{
int i;
if ((displayedBoard = malloc(width * sizeof(char*))) != NULL){
for(i=0 ; i<width ; i++){
if ((displayedBoard[i] = malloc(height * sizeof(char*))) == NULL){
return false;
}
}
}
if ((board = malloc(width * sizeof(char*))) != NULL){
for(i=0 ; i<width ; i++){
if ((board[i] = malloc(height * sizeof(char*))) == NULL){
return false;
}
}
}
return true;
}
void freeMemory(int width)
{
int i;
for(i=0 ; i<width ; i++)
{
free(board[i]);
free(displayedBoard[i]);
}
free(board);
free(displayedBoard);
}
void generateRandomCoordinates(int *x, int *y, int width, int height)
{
*x = rand()%width;
*y = rand()%height;
}
void generateBoardData(int width, int height, int bombs)
{
int i,j,x,y;
// generate bombs
for(i=0 ; i<bombs ; i++){
generateRandomCoordinates(&x, &y, width, height);
board[x][y] = BOMB;
}
// set numbers
int counter;
for(i=0 ; i<width ; i++){
for(j=0 ; j<height ; j++){
counter=0;
if(board[i][j]!=BOMB){
for(x=-1 ; x<2 ; x++){
for(y=-1 ; y<2 ; y++){
if(x!=0 || y!=0){
if(i+x>=0 && i+x<width && j+y>=0 && j+y<height){
if(board[i+x][j+y]==BOMB){
counter++;
}
}
}
}
}
if(counter!=0){
board[i][j]=counter+48;
}
else{
board[i][j]=EMPTY;
}
}
displayedBoard[i][j] = '.';
}
}
}
void discoverSurroundingBoxes(int x, int y, int width, int height)
{
board[x][y]=DISCOVERED;
displayedBoard[x][y]=DISCOVERED;
int i;
// search left
if(x>0)
{
for(i=x-1 ; i>=0 ; i--)
{
if(board[i][y]==EMPTY && board[i][y]!=BOMB && board[i][y]!=FLAG){
discoverSurroundingBoxes(i,y,width,height);
}
else if(board[i][y]!=BOMB && board[i][y]!=DISCOVERED && board[i][y]!=EMPTY && board[i][y]!=FLAG && board[i+1][y]==DISCOVERED){
displayedBoard[i][y] = board[i][y];
}
else{
break;
}
}
}
// search right
if(x<width-1)
{
for(i=x+1 ; i<width ; i++)
{
if(board[i][y]==EMPTY && board[i][y]!=BOMB && board[i][y]!=FLAG){
discoverSurroundingBoxes(i,y,width,height);
}
else if(board[i][y]!=BOMB && board[i][y]!=DISCOVERED && board[i][y]!=EMPTY && board[i][y]!=FLAG && board[i-1][y]==DISCOVERED){
displayedBoard[i][y] = board[i][y];
}
else{
break;
}
}
}
// search top
if(y>0)
{
for(i=y-1 ; i>=0 ; i--)
{
if(board[x][i]==EMPTY && board[x][i]!=BOMB && board[x][i]!=FLAG){
discoverSurroundingBoxes(x,i,width,height);
}
else if(board[x][i]!=BOMB && board[x][i]!=DISCOVERED && board[x][i]!=EMPTY && board[x][i]!=FLAG && board[x][i+1]==DISCOVERED){
displayedBoard[x][i] = board[x][i];
}
else{
break;
}
}
}
// search bottom
if(y<height-1)
{
for(i=y+1 ; i<height ; i++)
{
if(board[x][i]==EMPTY && board[x][i]!=BOMB && board[x][i]!=FLAG){
discoverSurroundingBoxes(x,i,width,height);
}
else if(board[x][i]!=BOMB && displayedBoard[x][i]!=DISCOVERED && board[x][i]!=EMPTY && board[x][i]!=FLAG && board[x][i-1]==DISCOVERED){
displayedBoard[x][i] = board[x][i];
}
else{
break;
}
}
}
}
void printBoard(int width, int height, int cursorX, int cursorY)
{
int i,j;
for(i=0 ; i<height ; i++){
for(j=0 ; j<width ; j++){
printf("%c ", displayedBoard[j][i]);
}
printf("\n");
if(i==cursorY){
for(j=0 ; j<width ; j++){
if(j==cursorX){
printf("-");
break;
}
else
printf(" ");
}
printf("\n");
}
}
}
void refreshScreen(int width, int height, int cursorX, int cursorY)
{
system("cls");
printBoard(width, height, cursorX, cursorY);
}
bool hasWinned(int width, int height, int bombs)
{
int i, j, discoveredBoxes=0;
for(i=0 ; i<width ; i++)
{
for(j=0 ; j<height ; j++)
{
if(displayedBoard[i][j]==DISCOVERED || (displayedBoard[i][j]!='.' && displayedBoard[i][j]!=FLAG)){
discoveredBoxes++;
}
}
}
return discoveredBoxes==width*height-bombs;
}
bool saveGame(const char* filename, int width, int height, int bombs)
{
int i,j;
FILE *file = fopen(filename, "w+");
if(file==NULL){
return false;
}
fprintf(file, "%d\n%d\n%d\n", width, height, bombs);
for(i=0 ; i<width ; i++){
for(j=0 ; j<height ; j++){
fprintf(file, "%d\n", board[i][j]);
fprintf(file, "%d\n", displayedBoard[i][j]);
}
}
fclose(file);
return true;
}
bool loadGame(const char* filename, int *width, int *height, int *bombs)
{
int i,j,x;
FILE *file = fopen(filename, "r");
if(file==NULL){
return false;
}
fscanf(file, "%d", width);
fscanf(file, "%d", height);
fscanf(file, "%d", bombs);
if(!allocateMemory(*width, *height)){
return false;
}
for(i=0 ; i<*width ; i++){
for(j=0 ; j<*height ; j++){
fscanf(file, "%d", &x);
board[i][j]=x;
fscanf(file, "%d", &x);
displayedBoard[i][j]=x;
}
}
fclose(file);
return true;
}
int main()
{
srand(time(NULL));
int WIDTH, HEIGHT, BOMBS;
bool gameFinished=false;
int code=0, choice=0;
int cursorX=0, cursorY=0;
char c;
/***************
GAME MENU
***************/
printf("###################################################\n");
printf("################ Minesweeper ####################\n");
printf("###################################################\n");
printf("###### 1 - Easy 8x8 10 bombs ##########\n");
printf("###### 2 - Medium 15x15 45 bombs ##########\n");
printf("###### 3 - Hard 20x20 80 bombs ##########\n");
printf("###### 4 - Custom game ##########\n");
printf("###### 5 - Resume Saved Game ##########\n");
printf("###################################################\n");
printf("###################################################\n\n");
printf("Choose: ");
scanf("%d", &choice);
if(choice==5){
if(loadGame("game", &WIDTH, &HEIGHT, &BOMBS)){
refreshScreen(WIDTH, HEIGHT, cursorX, cursorY);
}
else{
gameFinished=true;
code=1;
}
}
else {
if(choice==4){
bool isOk = false;
while(!isOk){
printf("Board width : ");
scanf("%d", &WIDTH);
printf("Board height : ");
scanf("%d", &HEIGHT);
printf("Bombs : ");
scanf("%d", &BOMBS);
if(WIDTH>0 && WIDTH<=100 && HEIGHT>0 && HEIGHT<=100 && BOMBS<WIDTH*HEIGHT){
isOk=true;
}
else{
printf("\n/!\\ Width and Height must be smaller or equal to 100.\nThe number of bombs must be smaller than the total amount of rows.\n\n");
}
}
}
else if(choice==3){
WIDTH=20;
HEIGHT=20;
BOMBS=80;
}
else if(choice==2){
WIDTH=15;
HEIGHT=15;
BOMBS=45;
}
else{
WIDTH=8;
HEIGHT=8;
BOMBS=10;
}
if(allocateMemory(WIDTH, HEIGHT)){
generateBoardData(WIDTH, HEIGHT, BOMBS);
refreshScreen(WIDTH, HEIGHT, cursorX, cursorY);
}
else{
gameFinished=true;
code=1;
}
}
/***************
GAME LOOP
***************/
while (!gameFinished)
{
if (kbhit())
{
c = getch();
if(c==75){ // left
cursorX=cursorX==0?0:cursorX-1;
}
else if(c==72){ // up
cursorY=cursorY==0?0:cursorY-1;
}
else if(c==77){ // right
cursorX=cursorX==WIDTH-1?cursorX:cursorX+1;
}
else if(c==80){ // down
cursorY=cursorY==HEIGHT-1?cursorY:cursorY+1;
}
else if(c=='f'){ // "f" for flag
displayedBoard[cursorX][cursorY] = FLAG;
}
else if(c==' '){ // space
c = board[cursorX][cursorY];
if(c==BOMB){
displayedBoard[cursorX][cursorY] = board[cursorX][cursorY];
gameFinished=true;
code=2;
}
else if(c==EMPTY){
discoverSurroundingBoxes(cursorX, cursorY, WIDTH, HEIGHT);
}
else{
displayedBoard[cursorX][cursorY] = board[cursorX][cursorY];
}
}
else if(c=='q'){
gameFinished=true;
printf("\nWould you like to save the game ? (Y/n) ");
c = getch();
if(c=='Y' || c=='y' || c==13){
if(saveGame("game", WIDTH, HEIGHT, BOMBS)){
code=4;
}
else{
code=1;
}
}
else{
code=0;
}
}
refreshScreen(WIDTH, HEIGHT, cursorX, cursorY);
if(hasWinned(WIDTH, HEIGHT, BOMBS)){
gameFinished=true;
code=3;
}
}
}
freeMemory(WIDTH);
if(code==1){
printf("\nError happened...\n");
}
else if(code==2){
printf("\nYou lost !\n");
}
else if(code==3){
printf("\nYou winned !\n");
}
else if(code==4){
printf("\nGame saved !\n");
}
printf("Press any key to exit\n");
getch();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment