[Lenguaje C][Juego][Buscaminas]

Prefacio:

Para consolidar el lenguaje C, utilicé los conocimientos adquiridos para escribir un blog sobre el juego del buscaminas. Si alguien ve este artículo, si hay alguna deficiencia, por favor indíquelo.
Las reglas del juego:
abrimos una cuadrícula al azar en el tablero de ajedrez (ingrese la fila y la columna para confirmar la cuadrícula), si la cuadrícula no es mía, esta posición se excluirá y, después de la exclusión, se mostrará la cuadrícula en varias cuadrículas que lo rodean Hay varias minas, si la cuadrícula en la que se hizo clic está enterrada con minas, el juego fallará.

1. Programación modular

Programación modular: Ponga el código de cada módulo en diferentes archivos .c y proporcione la declaración de funciones llamadas externas en el archivo .h. Cuando otros archivos .c quieran usar el código, solo necesita #incluir "XXX.h "El archivo está bien. El uso de programación modular puede mejorar en gran medida la legibilidad, mantenibilidad, portabilidad, etc. del código.
Aquí creé tres archivos: el archivo game.h se usa para escribir la declaración de la función personalizada; el archivo game.c se usa para escribir la definición; el archivo test.c se usa para escribir la implementación de todo el programa. (Aquí, solo necesita #incluir "game.h" en el archivo c para conectar el archivo de encabezado y el archivo fuente)
de la siguiente manera:
inserte la descripción de la imagen aquí

2. La idea del juego

1. Diseño del juego:

1) El juego del buscaminas necesita almacenar la información de las minas dispuestas, lo que requiere una matriz bidimensional
2) Se proporcionan dos matrices bidimensionales de 9*9:
una almacena la información de las minas y la otra almacena la información de las minas dispuestas
3) Para evitar que la matriz cruce el límite al contar el número de minas alrededor de las coordenadas, diseñamos la matriz como una matriz bidimensional de 11*11 4) La matriz es 11
* 11, y es una matriz de caracteres (aquí usamos '0' para representar a no Ray, '1' significa trueno)

2. La lógica del juego:

1) Cree una función de menú para elegir ingresar al juego y salir del juego
2) Cree una función de juego e inicialice el tablero (el juego necesita almacenar datos durante el juego, puede usar la matriz bidimensional 11 * 11 char board[ROWS][COLS ];)
3). Imprimir tablero de ajedrez
4). Organizar minas
5). Comprobar minas

3. Darse cuenta de los pasos/procesos del juego

1... Crea una función de menú para elegir entrar al juego y salir del juego

1) Crear un menú

void menu()
{
    
    
    printf("**********************\n");
    printf("****  1.开始游戏  ****\n");
    printf("****  0.退出游戏  ****\n");
    printf("**********************\n");
}

Prueba:
inserte la descripción de la imagen aquí
2) Elija ingresar al juego y salir del juego (si no está satisfecho después de jugar, usará do while una vez)

#include "game.h"
void menu()
{
    
    
    printf("**********************\n");
    printf("****  1.开始游戏  ****\n");
    printf("****  0.退出游戏  ****\n");
    printf("**********************\n");
}
int main()
{
    
    
    int input;
    do
    {
    
    
        menu();
    scanf("%d", &input);
    switch (input)//用来进行一次操作
    {
    
    
    case 0:
        break;
    case 1:
    {
    
    
        printf("扫雷游戏\n");//可以进入游戏
        break;
    }
    default:
    {
    
    
        printf("笨蛋输错了,重新输入:\n");
        break;
    }
    }
    }while (input);//可以进行多次游戏
    return 0;
}

prueba:
inserte la descripción de la imagen aquí

2. Crea una función de juego e inicializa el tablero.

1) Crear función de juego:
crea dos matrices idénticas:
debido a que el usuario ve el tablero cubierto cuando juega y no puede ver dónde están enterradas las minas, este es el tablero de visualización. También necesitamos un tablero de ajedrez para colocar minas, de modo que el jugador pueda pasar el nivel o no pasar el nivel cuando juega, y presentar el punto donde las minas están enterradas para el jugador.
La razón para crear una matriz de 11*11:
en el rastreo de minas, si se muestra un número en una posición que verificamos, significa que hay minas con este número en las 8 cuadrículas alrededor de esta posición, entonces estamos en los cuatro lados de la fila. No hay suficientes 8 cuadrículas en este momento, pero nuestra función aún buscará estas 8 cuadrículas cuando se implemente, lo que causará el problema del acceso fuera de los límites a la matriz. Para facilitar la etapa posterior , podemos cambiar el tamaño del tablero de ajedrez
inserte la descripción de la imagen aquí
y el número de minas. , usando la definición de macro define

#define ROW 9//  显示棋盘的行数
#define COL 9//  显示棋盘的列数
#define ROWS ROW+2//  实际棋盘的行数
#define COLS COL+2//  实际棋盘的列数
#define mine_count 10//设置雷的数量

2) Inicializar la placa
inserte la descripción de la imagen aquí

void InitBoard(char board[][COLS], int rows, int cols, char set)//初始化棋盘
{
    
    
    int i, j;
    for(i=0;i<rows;i++)//遍历的方法,给每个数组元素赋值
        for (j = 0; j < cols; j++)
        {
    
    
            board[i][j] = set;
        }
        printf("\n";
}

3. Imprime el tablero de ajedrez

void DisPlayBoard(char board[][COLS], int row, int col)
{
    
    
    int i, j;
    printf("******* 扫雷游戏 *******\n");
    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");
    }
}

Prueba dos tableros:
inserte la descripción de la imagen aquí
Prueba:
Tablero donde se almacena Ray
inserte la descripción de la imagen aquí
Tablero operado por el usuario
inserte la descripción de la imagen aquí

4. Organizar minas

void SetMine(char mine[][COLS], int row, int col)
{
    
    
    int i=mine_count,x,y;
    while(i)
    {
    
    
        x = rand() % row + 1;
        y = rand() % col + 1;
        if (mine[x][y] == '0')
        {
    
    
            mine[x][y] = '1';//字符1就是雷
            i--;
        }
    }
}

Prueba (10 minas en la matriz mine_1):
inserte la descripción de la imagen aquí

5. Revisa el mío

Primero, juzgamos si la posición de coordenadas ingresada por el jugador es legal o no. La coordenada debe estar entre 1 ~ fila/columna (incluyendo 1 y fila/columna). Si no está en este rango, el código irá a la primera declaración else para recordar al jugador "Estúpido, las coordenadas son incorrectas, vuelva a ingresar:". Si es legal, iremos a la primera sentencia if, después de ingresar, juzgaremos la posición para ver si la posición es el carácter '1', si es el carácter '1', significa pisar un trueno, y le recordará al jugador "Desafortunadamente, "te volaron hasta la muerte", y le mostrará el mapa de distribución de minas al jugador. Si es el carácter '0', ejecuta la instrucción else para calcular y marcar el número de minas en las 8 cuadrículas alrededor de la posición. En este momento simplemente llamamos a la función GetMine() para calcular:

void FindMine(char mine_1[][COLS],char mine_2[][COLS],int row,int col)
{
    
    
    int x,y,count;
    while (1)
    {
    
    
        printf("请输入排查雷的坐标:\n");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)//坐标输入正确
        {
    
    
            if (mine_1[x][y] == '1')//踩雷了
            {
    
    
                printf("你被炸死了\n");
                DisPlayBoard(mine_1, ROW, COL);
                break;
              }
            else//没踩雷
            {
    
    
                count = GetMine(mine_1, x, y);//统计雷的四周有几个雷
                mine_2[x][y] = '0' + count;
                //if (count == 0)
                  //  expend(mine_1, mine_2, row, col, x, y);
                DisPlayBoard(mine_2, ROW, COL); 
            }
        }
        else
            printf("笨蛋,坐标输错了,请重新输入:\n");
    }
}

Resultados de la prueba:
inserte la descripción de la imagen aquí

6. Juez gane o pierda

Las coordenadas no verificadas en la matriz mine_2 son '*', así que solo cuente si el '*' restante es igual al número de minas, y si es igual, el juego gana.

lswin(char mine_2[][COLS], int row, int col)//判断有几个符号‘*’然后返回
{
    
    
    int i,j,c;
    for(i=0;i<row;i++)
        for (j = 0; j < col; j++)
        {
    
    
            if (mine_2[i][j] == '*')
                c++;
        }
    return c;
}

inserte la descripción de la imagen aquí

7. Ampliar

Explicación: El rango de coordenadas extendidas debe ser limitado. Si las coordenadas que quiero verificar tienen minas, el juego terminará inmediatamente. Si no hay minas, se expandirá a las 8 coordenadas circundantes, y si no hay minas, establece esta coordenada en un espacio ¡Evita que se repita la recursividad! Luego limite el rango de coordenadas. Si alcanza el límite, no hay necesidad de continuar recursando fuera del límite. Cruzará el límite. Después de la recursión, encontrará que hay truenos alrededor y puede mostrar la cantidad de truenos. .

void expend(char mine_1[][COLS], char mine_2[][COLS], int row, int  col, int x, int  y)
{
    
    
    int count = GetMine(mine_1, x, y);//统计雷的四周有几个雷
    if (count == 0)
    {
    
    
        mine_1[x][y] = ' ';//如果周围地雷数为零则把这个位置赋值为空格
        int i = 0;
        int j = 0;
        for (i = x - 1; i <= x + 1; i++)
        {
    
    
            for (j = y - 1; j <= y + 1; j++)
            {
    
    
                if (mine_2[i][j] == '*' && i > 0 && i <= row && j > 0 && j <= col)
                {
    
    
                    expend(mine_1, mine_2, row, col, i, j);
                }
            }
        }
    }
    else
    {
    
    //递归的出口就是我统计到周围有几个雷
        mine_2[x][y] = count + '0';
}
}

4. Volumen total de código

1. Pruebe el código del archivo test.c del juego

#include "game.h"
void menu()
{
    
    
    printf("**********************\n");
    printf("****  1.开始游戏  ****\n");
    printf("****  0.退出游戏  ****\n");
    printf("**********************\n");
}
void game()//创建游戏
{
    
    
    system("cls");//每次玩游戏,都把前面的记录全部清掉
    srand((unsigned)time(NULL));
    //创建雷的数组(mine_1)显示数组(mine_2)两个数组的类型,大小相同
    char mine_1[ROWS][COLS];//存放布置的雷的信息
    char mine_2[ROWS][COLS];//存放排查出雷的信息
    //初始化棋盘
    InitBoard(mine_1, ROWS, COLS,'0');//初始化棋盘里全部赋‘0’
    InitBoard(mine_2, ROWS, COLS, '*');//初始化棋盘里全部赋‘*’
    //打印棋盘
    //DisPlayBoard(mine_1, ROW, COL);//打印存放雷信息的9*9的棋盘
    DisPlayBoard(mine_2, ROW, COL);//打印排查出雷信息的9*9的棋盘
    //布置雷
    SetMine(mine_1, ROW, COL);

    //排查雷
    FindMine(mine_1,mine_2, ROW, COL);
}
int main()
{
    
    
    int input;
    do
    {
    
    
        menu();
    scanf("%d", &input);
    switch (input)//用来进行一次操作
    {
    
    
    case 0:
    {
    
    
        printf("退出游戏\n");
    break;
    }
    case 1:
    {
    
    
        game();//可以进入游戏
        break;
    }
    default:
    {
    
    
        printf("笨蛋输错了,重新输入:\n");
        break;
    }
    }
    }while (input);//可以进行多次游戏
    return 0;
}

2. El juego implementa el código del archivo game.c

#include "game.h"
void InitBoard(char board[][COLS], int rows, int cols, char set)//初始化棋盘
{
    
    
    int i, j;
    for(i=0;i<rows;i++)
        for (j = 0; j < cols; j++)
        {
    
    
            board[i][j] = set;
        }
    printf("\n");
}
void DisPlayBoard(char board[][COLS], int row, int col)
{
    
    
    int i, j;
    printf("******* 扫雷游戏 *******\n");
    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 SetMine(char mine[][COLS], int row, int col)
{
    
    
    int i=mine_count,x,y;
    while(i)
    {
    
    
        x = rand() % row + 1;
        y = rand() % col + 1;
        if (mine[x][y] == '0')
        {
    
    
            mine[x][y] = '1';//字符1就是雷
            i--;
        }
    }
}
int GetMine(char mine_1[][COLS], int x, int y)
{
    
    

    return mine_1[x - 1][y - 1] + mine_1[x - 1][y] + mine_1[x - 1][y + 1]
        + mine_1[x][y - 1] + mine_1[x][y + 1] + mine_1[x + 1][y - 1]
        + mine_1[x + 1][y] + mine_1[x + 1][y + 1] - 8 * '0';
}
void FindMine(char mine_1[][COLS],char mine_2[][COLS],int row,int col)
{
    
    
    int x,y,count;
    while (1)
    {
    
    
        printf("请输入排查雷的坐标:\n");
        scanf("%d %d", &x, &y);
        if (x >= 1 && x <= row && y >= 1 && y <= col)//坐标输入正确
        {
    
    
            if (mine_1[x][y] == '1')//踩雷了
            {
    
    
                printf("你被炸死了\n");
                DisPlayBoard(mine_1, ROW, COL);
                break;
              }
            else//没踩雷
            {
    
    
                   expend(mine_1, mine_2, row, col, x, y);
                DisPlayBoard(mine_2, ROW, COL); 
                int a=lswin(mine_2, row, col);//判断是否排查完
                if (a == ROW * COL - mine_count)//不需要排查了,赢啦
                {
    
    
                    printf("你赢了,真棒!\n");
                    break;
                }
            }
        }
        else
            printf("笨蛋,坐标输错了,请重新输入:\n");
    }
}
void expend(char mine_1[][COLS], char mine_2[][COLS], int row, int  col, int x, int  y)
{
    
    
    int count = GetMine(mine_1, x, y);//统计雷的四周有几个雷
    if (count == 0)
    {
    
    
        mine_1[x][y] = ' ';//如果周围地雷数为零则把这个位置赋值为空格
        int i = 0;
        int j = 0;
        for (i = x - 1; i <= x + 1; i++)
        {
    
    
            for (j = y - 1; j <= y + 1; j++)
            {
    
    
                if (mine_2[i][j] == '*' && i > 0 && i <= row && j > 0 && j <= col)
                {
    
    
                    expend(mine_1, mine_2, row, col, i, j);
                }
            }
        }
    }
    else
    {
    
    //递归的出口就是我统计到周围有几个雷
        mine_2[x][y] = count + '0';
}
}
lswin(char mine_2[][COLS], int row, int col)//判断有几个符号‘*
{
    
    
    int i,j,c=0;
    for(i=0;i<row;i++)
        for (j = 0; j < col; j++)
        {
    
    
            if (mine_2[i][j] == '*')
                c++;
        }
    return c;
}

3. Declaración de la función del juego código de archivo de encabezado game.h

#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define ROW 9//  显示棋盘的行数
#define COL 9//  显示棋盘的列数
#define ROWS ROW+2//  实际棋盘的行数
#define COLS COL+2//  实际棋盘的列数
#define mine_count 10//设置雷的数量
void InitBoard(char board[][COLS], int rows, int cols, char set);//初始化棋盘
void DisPlayBoard(char board[][COLS], int row, int col);//布置棋盘
void SetMine(char mine[][COLS], int row, int col);//布置雷
void FindMine(char mine_1[][COLS], char mian_2[][COLS], int row, int col);//排查雷
int GetMine(char mine_1[][COLS], int x, int y);//统计雷的四周有几个雷
void expend(char mine_1[][COLS], char mine_2[][COLS], int row, int  col, int x, int  y);//扩展坐标的范围
int lswin(char mine_2[][COLS], int row, int col);//统计有几个字符‘*’

prueba

inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/plj521/article/details/131188953
Recomendado
Clasificación