C language game --- minesweeper

Program idea:
Multiple files to realize the basic functions of mine sweeping:
1) test.c : function test, function call;
2) game.h : include header file reference, function declaration;
3) game.c : function of each function realization.
The specific idea of ​​the function:
1. Initialization of the thunder disk: pay attention to the size of the actual thunder disk and the size of the displayed thunder disk;
2. The printing of the thunder disk: pay attention to the size of the displayed thunder disk;
3. Layout the thunder disk: When randomly distributing the thunder disk, Pay attention to the use of srand;
4. Count the number of mines: pay attention to the statistics of mines around the boundary coordinates;
5. Extended mine clearance: pay attention to the conditions of extended mine clearance
; Scope;

test.c

#define _CRT_SECURE_NO_WARNINGS 1 

#include<stdio.h>
#include"game.h"


void game()
{
    char mine[ROWS][COLS];                   //扫雷实际数组
    char show[ROWS][COLS];                  // 展示数组
    srand((unsigned int)time(NULL));       //  产生随机数
    init_mine(mine, ROWS, COLS);
    init_show(show, ROW, COL);
    set_mine(mine, ROW, COL,MINECOUNT);
    display(show, ROW, COL);           //打印雷盘
    play_game(mine, show);           //  主逻辑函数

}

void menu()
{
    printf("***********************\n");
    printf("*********1.piay********\n");
    printf("*********0.exit********\n");
    printf("***********************\n");
}

int main()
{
    int input = 0;
    do
    {
        menu();
        printf("请选择:>");
        scanf("%d", &input);
        switch (input)
        {
        case 1:
            game();
            break;
        case 0:
            break;
        default:
            printf("输入错误!");
        }
    } while (input);
    return 0;

}

game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include"game.h"

void init_mine(char mine[ROWS][COLS], int row, int col)  // 初始化雷盘
{
    int i = 0;
    int j = 0;
    for (i = 0; i < row; i++)
    {
        for (j = 0; j < col; j++)
        {
            mine[i][j] = '0';
        }
    }
}

void init_show(char show[ROWS][COLS], int row, int col) //初始化展示的雷盘
{
    int i = 0;
    int j = 0;
    for (i = 1; i <= row; i++)
    {
        for (j = 1; j <= col; j++)
        {
            show[i][j] = '*';
        }
    }
}

void set_mine(char mine[ROWS][COLS], int row, int col,int count)   // 随机布雷
{

    while (count)
    {
        int x = rand() % row + 1;
        int y = rand() % col + 1;
        mine[x][y] = '1';
        count--;

    }

}


void display(char arr[ROWS][COLS], int row, int col)  // 打印雷盘
{
    int i = 0;
    int j = 0;
    printf("  ");
    for (i = 1; i <= row; i++)
    {
        printf(" %d", i);
    }
    printf("\n");
    for (i = 1; i <= row; i++)
    {
        printf("%2d", i);
        for (j = 1; j <= col;j++)
        {
            printf(" %c", arr[i][j]);
        }
        printf("\n");
    }
}

void reset_mine(char mine[ROWS][COLS], int row, int col,int x,int y, int count) // 第一次踩到雷,重新布雷
{
    mine[x][y] = '0';

    while (count)
    {
        int i = rand() % row + 1;
        int j = rand() % col + 1;
        if ((mine[i][j] != '1') && i != x && j != y)
        {
            mine[i][j] = '1';
            count--;
        }
    }
}

int  get_minecount(char mine[ROWS][COLS], int i, int j)   //统计雷的个数
{
    return mine[i - 1][j] +
        mine[i - 1][j - 1] +
        mine[i][j - 1] +
        mine[i + 1][j - 1] +
        mine[i + 1][j] +
        mine[i + 1][j + 1] +
        mine[i][j + 1] +
        mine[i - 1][j + 1] - 8 * '0';
}

void expand(char mine[ROWS][COLS], int x, int y, char show[ROWS][COLS], int *p)    //扩展函数
{

    int i = -1;
    int j = -1;
    for (i = -1; i < 2; i++)      //边界
    {
        for (j = -1; j < 2; j++)
        {
            if (i != 0 || j != 0)      // 避免排到自己
            {
                if (x+i >= 1 && x+i <= ROW && y+j >= 1 && y+j <= COL)     //x y坐标是否合法
                {
                    if (show[x+i][y+j]=='*')
                    {

                        int count = get_minecount(mine, x+i, y+j);
                        if (count != 0)                                   
                        {
                            show[x+i][y+j] = count + '0';
                            (*p)++;
                        }
                        else
                        {
                            show[x+i][y+j] = '0';
                            (*p)++;
                            expand(mine, x+i, y+j, show, p);
                        }

                    }

                }
            }
        }
    }


}

// 主逻辑
void play_game(char mine[ROWS][COLS], char show[ROWS][COLS])
{
    int x = 0;
    int y = 0;
    int win = 0;        //统计排雷的个数
    int count = 0;     // 统计雷的个数
    while (win < ROW*COL - MINECOUNT)
    {
        printf("请输入坐标:>");
        scanf("%d %d", &x, &y);
        if (show[x][y] == count + '0')    //避免重复排雷
        {
            printf("已经排过雷\n");
        }
        if (x >= 1 && x <= ROW && y >= 1 && y <= COL)   //输入坐标是否合法
        {
            if (mine[x][y] == '1')
            {
                if (0 == win)      //为了游戏体验,第一次踩到雷,重新布雷
                {
                    reset_mine(mine, ROW, COL, x, y, 1);
                    display(mine, ROW, COL);
                    count = get_minecount(mine, x, y);
                    if (count == 0)
                    {
                        show[x][y] = '0';
                        win++;
                        expand(mine, x, y, show, &win);  //如果周围没有雷,进行扩展
                        display(show, ROW, COL);
                    }
                    else
                    {
                        show[x][y] = count + '0';
                        display(show, ROW, COL);
                    }
                }
                else
                {
                    printf("很遗憾,你被炸死了\n");
                    display(mine, ROW, COL);
                    break;
                }
            }
            else
            {
                count = get_minecount(mine, x, y);
                show[x][y] = count + '0';
                win++;
                expand(mine, x, y, show, &win);
                display(show, ROW, COL);
            }
        }

        else
        {
            printf("输入坐标不合法\n");
        }

    }
    if (win == ROW*COL - MINECOUNT)    
    {
        printf("排雷成功\n");
        display(mine, ROW, COL);
    }
}

game.h

#define _CRT_SECURE_NO_WARNINGS 1

#ifndef __GAME_H__
#define __GAME_H__


#define ROWS  ROW+2
#define COLS  COL+2
#define ROW   10
#define COL   10
#define MINECOUNT  10



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



void init_mine(char mine[ROWS][COLS], int row, int col);
void init_show(char show[ROWS][COLS], int row, int col);
void display(char arr[ROWS][COLS], int row, int col);
void set_mine(char mine[ROWS][COLS], int x, int y,int count);
void play_game(char mine[ROWS][COLS], char show[ROWS][COLS]);
int  get_minecount(char mine[ROWS][COLS], int i, int j);
void reset_mine(char mine[ROWS][COLS], int row, int col, int x, int y, int count);
void expand(char mine[ROWS][COLS], int x, int y, char show[ROWS][COLS], int *p);




#endif //__GAME_H__

Debug result:

Stepping on a thunder for the first time:
1) Random thunder array

write picture description here

2) The rearranged thunder array after stepping on the thunder

write picture description here

Killed by:

write picture description here

Repeat demining:

write picture description here

Demining failed:

write picture description here

In the above program, the method of initializing the thunder disk is not very brief, we can use the memset function to initialize, the specific code is as follows:

void init_mine(char mine[ROWS][COLS], int row, int col)   // 初始化雷盘
{
    memset(mine, '0', row*col*sizeof(mine[0][0]));
}

memset function:
1. void *memset(void *s,int c,size_t n)
Overall function: set the value of the first n bytes of the allocated memory space s to the value c.
2. Examples

#include<stdio.h>

int  main()
{
    char *s = "Golden Global View";
    clrscr();
    memset(s, 'G', 6);
    printf("%s", s);
    getchar();
    return 0;
}
  1. The memset() function is often used for memory space initialization.
    Such as:
    char str[100];
    memset(str,0,100);

  2. The profound connotation of memset(): it is used to set all a memory space to a certain character, generally used to initialize the defined string to ' ' or '/0'
    Example:
    char a[100];memset(a, '/0', sizeof(a));

    When realizing the function of mine clearance, the idea of ​​recursion is adopted. The specific idea is:
    pass the formal parameter win to the expand function. Each time mine clearance is performed, win counts once, and ends when win is greater than the number of grids without mines.

void expand(char mine[ROWS][COLS], int x, int y, char show[ROWS][COLS], int *p)     //扩展函数
{

    int i = -1;
    int j = -1;
    for (i = -1; i < 2; i++)    //边界
    {
        for (j = -1; j < 2; j++)
        {
            if (i != 0 && j != 0)   // 避免排到自己
            {
                if (x+i >= 1 && x+i <= ROW && y+j >= 1 && y+j <= COL)   //x y坐标是否合法
                {
                    if (show[x+i][y+j]=='*')  //该位置没有排雷
                    {

                        int count = get_minecount(mine, x+i, y+j);//统计该位置周围雷的个数
                        if (count != 0)                                   
                        {
                            show[x+i][y+j] = count + '0';   
                            (*p)++;  //每排雷一次,计数一次
                        }
                        else
                        {
                            show[x+i][y+j] = '0'; //该位置周围没有雷时,向周围八个位置进行扩展排雷
                            (*p)++;
                            expand(mine, x+i, y+j, show, p);
                        }

                    }

                }
            }
        }
    }


}

Summary:
When writing a program, continuous debugging will have a good effect. When the program does not go the way you think, use F11 to check each step, so that you can see clearly which step went wrong, which is beneficial for us to change Remove bugs in the program. Adding necessary comments when writing the program will help us to know which link has the problem faster in the later debugging process.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325805617&siteId=291194637