C language minesweeper game

The code is completed in a project and divided into three .c.h files (game.c, game.h, main.c)
and debugged by running in Clion software.

/General idea/
The main function main.c is a large frame (menu, minesweeper board Initialization, random function generates mines, players clear mines)
game.h function declaration (some function declarations except main function and game function)
game.c function Implementation (implementation of some functions except main function and game function)

/game.c实现/

① First initialize the minesweeper board (use two character arrays of the same size as the minesweeper board
1. Store mines 2. Display the minesweeper board to the player. In order to avoid traversing There is an out-of-bounds access in , the board size is set to 11*11, mines are arranged in the size of 9*9, and the player is also shown to 9< a i=4>9 size. Equivalent to hiding the first and last rows, the first and last columns.) 1 The chessboard is initialized to 0 2 The chessboard is initialized to *
*

②After initializing the chessboard, display the chessboard
③Random function generates mines and stores them in the first character array
④Player minesweeper implementation includes: Player Enter whether the coordinate position is mine. If the coordinates are not mines, are there mines in the surrounding circle? When the coordinates are not mines and there are no mines around, recursion is used to display these coordinates as empty.

The following are some function implementations:

//Determine how many mines are around (get the mine number information at eight positions in a circle except the input coordinates.
For characters, a certain character -'0' is Integer. Eight coordinates minus eight '0's are the number of mines in the eight coordinates)

//判断周围多少雷,返回雷数
int BombNumber(char mine[ROWS][COLS],int row,int col){
    
    

    return mine[row -1][col-1] + mine[row - 1][col] + mine[row - 1][col+1] + \
            mine[row][col-1] + mine[row][col+1] + \
            mine[row+1][col - 1] + mine[row+1][col] + mine[row+1][col+1] -8*'0';
}

Originally, when the coordinates entered by the player were not mines, and the eight surrounding coordinates were not mines, I wanted to list the nine coordinates in the function and save them as empty before displaying them. But in the learning video, it is mentioned that recursion can be used to present a blank chessboard. I looked up other people's code online and learned how to use recursion to render a chessboard.

//假设是3*3的棋盘
	        show[row - 1][col - 1] = ' ';//第一行
            show[row - 1][col] = ' ';
            show[row - 1][col + 1] = ' ';
            show[row][col - 1] = ' ';//第二行
            show[row][col] = ' ';
            show[row][col + 1] = ' ';
            show[row + 1][col - 1] = ' ';//第三行
            show[row + 1][col] = ' ';
            show[row + 1][col + 1] = ' ';

Recursively present a chessboard
//The recursive idea in this code is 1. The coordinate is not a mine 2. The eight surrounding coordinates are not a mine either
Loop through the coordinates entered by the player nine times to determine whether each coordinate is legal and has no mines and is not displayed to the player
After the coordinates meet the conditions, the function to determine whether there are mines in a circle is called. If the loop If there is no thunder in a circle of a certain coordinate, it will enter the recursive function again, and then loop through the coordinates of the coordinate to continue the above process. If the coordinates do not meet the conditions, the recursion will end and the else statement will be entered until the nine loops are completed.

void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col){
    
    
    int i=0,j=0,flag=0;
    show[row][col] = ' ';
    for(i=row-1;i<=row+1;i++) {
    
    
        for (j = col-1; j <=col+1; j++) {
    
    
            if((i>0&&i<=ROW)&&(j>0&&j<=COL)&&(mine[i][j]!='1')&&(show[i][j]=='*')) {
    
    
                flag = BombNumber(mine, i, j);//判断一圈是否是雷,返回的是雷的数量
                if(!flag)
                    BlankBoard(mine,show,i,j);//递归
                else
                    show[i][j]=flag+'0';//将得到的非0的雷数放到展示给玩家的棋盘里
            }
        }
    }
}

//Players perform core operations of the game

void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
    
    
    char array[5]="\0";//使用字符串接收玩家输入的信息
    int x,y,flag=0,win=0;

    while(win<(row*col-Bomb))
    //展示给玩家的坐标数量<整个棋盘的非雷坐标数就进入循环
    //直到玩家看到的非*坐标数量已经是所有非雷坐标
    {
    
    
        printf("玩家输入坐标,坐标形式为:x,y\n");
        gets(array);
        x=array[0]-'0';//字符-'0'为整数
        y=array[2]-'0';
        if((x>=1&&x<=ROW)&&(y>=1&&y<=COL)&&(show[x][y])=='*')//坐标合法且没有显示给玩家
        {
    
    
            if(mine[x][y]=='1')//在存储雷的棋盘中'1'代表是雷
            {
    
    
                printf("很遗憾,该坐标中放了雷,玩家被炸死");
                printf("雷分布如下:\n");
                Display(mine,ROW,COL);//显示存储雷的棋盘
                break;}
            else{
    
    
                flag=BombNumber(mine, x, y);//判断该坐标周围一圈是否是雷
                if(flag>0){
    
    //周围一圈有雷
                show[x][y]=flag+'0';
                Display(show,ROW,COL);}
                else{
    
    
                    BlankBoard(mine,show,x,y);
                    Display(show,ROW,COL);}
               winwin=Showboard(show,ROW,COL);}//判断展示给玩家的坐标数
        }
        else
            printf("坐标无效,请重新输入\n");
    }
    if(win==(row*col-Bomb)){
    
    
        printf("恭喜玩家排雷成功!\n");
        Display(mine,ROW,COL);
    }
}

//The following is the complete code (I have never played a normal minesweeper game, so my understanding of winning and losing in minesweeper games may not be correct, but the general idea is fine)

//main.c


#include"game.h"

//初版扫雷

// 显示菜单
void menu(){
    
    
    printf("*********1.game***0.退出*********\n");
    printf("*********输入数字进行选择***********\n");
}
//游戏核心
//使用两个字符数组1->存放雷信息 2->用于输出到屏幕
//使用随机函数放置雷
//玩家排雷

void game() {
    
    
    char Mine [ROWS][COLS]={
    
    0};
    char Show [ROWS][COLS]={
    
    0};;
    //数组初始化
    Init(Mine,ROWS,COLS,'0');
    Init(Show,ROWS,COLS,'*');
    //显示
    //Display(Mine,ROWS,COLS);//显示初始化的雷棋盘
    Display(Show,ROWS,COLS);//显示玩家棋盘
    SetBomb(Mine,ROW,COL);//随机生成雷
    //Display(Mine,ROW,COL);//显示雷棋盘
    StartBomb(Mine,Show,ROW,COL);//玩家进行扫雷
}

int main()
{
    
    
    setbuf(stdout,NULL);//及时输出缓冲区内容
    int number=0;
    srand((unsigned int )time(NULL));//时间戳帮助生成棋盘上的随机坐标

    do{
    
    
        menu();
        scanf("%d",&number);
        getchar();//玩家输入的坐标使用字符串输入的,所以此时需要用getchar取走\n
        switch(number)
        {
    
    
            case 1:
                game();
                break;
            case 0:
                printf("正在退出\n");
                break;
            default:
                printf("选择错误,重新输入\n");
                break;
        }
    }while(number);

}


//game.h

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<time.h>

#define ROW 9
#define COL 9

#define ROWS (ROW+2)
#define COLS (COL+2)

#define Bomb 10

#ifndef TEXT1_GAME_H
#define TEXT1_GAME_H

void Init(char board[ROWS][COLS],int rows,int cols,char set);
void Display(char board[ROWS][COLS],int row,int col);
void SetBomb(char board[ROWS][COLS],int row,int col);
void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
int  BombNumber(char mine[ROWS][COLS],int row,int col);
void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col);
int Showboard(char board[ROWS][COLS],int row,int col);
#endif

//game.c

#include"game.h"

//初始化
void Init(char board[ROWS][COLS],int rows,int cols,char set){
    
    
    int i=0,j=0;
    for(i=0;i<ROWS;i++){
    
    
        for(j=0;j<COLS;j++)
            board[i][j]=set;
    }
}

//显示函数
void Display(char board[ROWS][COLS],int row,int col)
{
    
    
    int i=0,j=0;
    //打印列数
    for(i=0;i<=COL;i++)
        printf("%d|",i);
    printf("\n");
    for(i=1;i<=ROW;i++){
    
    
        printf("%d|",i);//打印行数
        for(j=1;j<=COL;j++)
            printf("%c ",board[i][j]);
        printf("\n");
    }
}

//放置炸弹
void SetBomb(char board[ROWS][COLS],int row,int col)
{
    
    

  int numberBomb=1;
  while(numberBomb<=Bomb)
  {
    
    
      int x=(rand()%ROW)+1;
      int y=(rand()%COL)+1;
          if(board[x][y]=='0') {
    
    
              board[x][y] = '1';
              numberBomb++;}
  }
}

void StartBomb(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col)
{
    
    
    char array[5]="\0";
    int x,y,flag=0,win=0;

    while(win<(row*col-Bomb))
    {
    
    
        printf("玩家输入坐标,坐标形式为:x,y\n");
        gets(array);
        x=array[0]-'0';
        y=array[2]-'0';
        if((x>=1&&x<=ROW)&&(y>=1&&y<=COL)&&(show[x][y])=='*')
        {
    
    
            if(mine[x][y]=='1')
            {
    
    
                printf("很遗憾,该坐标中放了雷,玩家被炸死");
                printf("雷分布如下:\n");
                Display(mine,ROW,COL);
                break;}
            else{
    
    
                flag=BombNumber(mine, x, y);
                if(flag>0){
    
    
                show[x][y]=flag+'0';
                Display(show,ROW,COL);
                }
                else{
    
    
                    BlankBoard(mine,show,x,y);
                    Display(show,ROW,COL);}
               }
            win=Showboard(show,ROW,COL);
        }
        else
            printf("坐标无效,请重新输入\n");
    }
    if(win==(row*col-Bomb)){
    
    
        printf("恭喜玩家排雷成功!\n");
        Display(mine,ROW,COL);
    }
}

//判断周围多少雷
int BombNumber(char mine[ROWS][COLS],int row,int col){
    
    

    return mine[row -1][col-1] + mine[row - 1][col] + mine[row - 1][col+1] + \
            mine[row][col-1] + mine[row][col+1] + \
            mine[row+1][col - 1] + mine[row+1][col] + mine[row+1][col+1] -8*'0';
}

//1.该坐标不是雷 2.周围的八个坐标也不是雷
void BlankBoard(char mine[ROWS][COLS],char show[ROWS][COLS],int row,int col){
    
    
    int i=0,j=0,flag=0;
    show[row][col] = ' ';
    for(i=row-1;i<=row+1;i++) {
    
    
        for (j = col-1; j <=col+1; j++) {
    
    
            if((i>0&&i<=ROW)&&(j>0&&j<=COL)&&(mine[i][j]!='1')&&(show[i][j]=='*')) {
    
    
                flag = BombNumber(mine, i, j);
                if(!flag)
                    BlankBoard(mine,show,i,j);
                else
                    show[i][j]=flag+'0';
/*          show[row - 1][col - 1] = ' ';
            show[row - 1][col] = ' ';
            show[row - 1][col + 1] = ' ';
            show[row][col - 1] = ' ';
            show[row][col] = ' ';
            show[row][col + 1] = ' ';
            show[row + 1][col - 1] = ' ';
            show[row + 1][col] = ' ';
            show[row + 1][col + 1] = ' ';*/

            }
        }
    }
}


int Showboard(char board[ROWS][COLS],int row,int col){
    
    
    int i=0,j=0,number=0;
    for(i=1;i<=row;i++){
    
    
        for(j=1;j<=col;j++){
    
    
            if(board[i][j]!='*')
                number++;
        }
    }
    return number;
}

Insert image description here

Guess you like

Origin blog.csdn.net/ainuliba/article/details/134866385