目录
  • 思路
    • 清晰的逻辑
  • 菜单
    • 棋盘
    • 布置雷
    • 排雷
    • 判断输赢
  • text.c实现
    • game.c实现
      • game.h实现
        • 递归部分详解
          • 总结

            思路

            清晰的逻辑

            为方便将其分为三个文件:text.c(测试) game.c(函数实现) game.h(头文件声明)

            在排雷的时候为了方便,我们需要将每一行每一列对应的行数,列数打印出来。

            #define LEI 10
            #define ROW 10
            #define LOW 10
             
            #define ROWS ROW+2
            #define LOWS LOW+2
            //在定义棋盘的长宽时,特意加上2,便于标记行数列数。

            C语言实现递归版扫雷游戏实例

            菜单

            打印的菜单只需要有开始游戏、退出游戏的选项即可

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

            棋盘

            1.雷盘

            2.棋盘

            扫雷需要先记录雷的信息再进行排雷,如果使用一个棋盘太过于复杂,所以我们使用两个棋盘,一个用于布置雷,一个用于玩家排雷。

            两个棋盘初始化

            布置雷的棋盘初始化,将字符‘0’作为非雷,字符‘1’作为雷。

            玩家盘将字符‘*’作为还没有扫的地方

                board(arr1, ROWS, LOWS, '0');//雷盘
            	board(arr2, ROWS, LOWS, '*');//玩家盘

            因为两个的初始化方式不同,所以我们采用传参ret初始化

            //初始化棋盘
            void board(char arr1[ROWS][LOWS], int rows, int lows, char ret)
            {
            	int i = 0;
            	for (i = 0; i < rows; i++)
            	{
            		int j = 0;
            		for (j = 0; j < lows; j++)
            		{
            			arr1[i][j] = ret;
            		}
            	}

            布置雷

            布置的雷放置需要随机,所以采用两个随机数来定位坐标。

             
            //布置雷
            void Get_lei(char arr1[ROWS][LOWS], int row, int low)
            {
            	int count = LEI;
            	while (count)
            	{
            		int x = rand() % row + 1;
            		int y = rand() % low + 1;
            		if (arr1[x][y] == '0')
            		{
            			arr1[x][y] = '1';
            			count--;
            		}
            	}
            	//displayboard(arr1, ROW, LOW);//用于测试
            }

            排雷

            当我们输入一个坐标时,我们需要知道这个坐标周围雷的个数,定义一个Get_num函数来获取雷个数。但此时只能获取一个坐标的信息,我们知道一般的扫雷,如果当前坐标雷的个数为0,就会展开,这个过程较为复杂,所以我们使用递归来实现

            //玩家盘
            static int Get_num(char arr1[ROWS][LOWS],int x, int y)//获得当前坐标周围雷的个数
            {
            	int count = 0;
            	int i = 0;
            	for (i = x - 1; i <= x + 1; i++)
            	{
            		int j = 0;
            		for (j = y - 1; j <= y + 1; j++)
            		{
            			if (arr1[i][j] == '1')
            			{
            				count++;
            			}
            		}
             
            	}
            	return count;
            }
            //判断是否展开,实现函数
            static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y)
            {
            	if (x > 0 && x <= ROW && y > 0 && y <= LOW)
            	{
            		int ret = Get_num(arr1, x, y);
            		if (ret != 0)
            			arr2[x][y] = ret + '0';//记录雷的个数
            		//递归散开
            		else if (arr1[x][y] != ' ')
            		{
            			arr2[x][y] = '0';
            			arr1[x][y] = ' ';
            			int i = 0;
            			for (i = x - 1; i <= x + 1; i++)
            			{
            				int j = 0;
            				for (j = y - 1; j <= y + 1; j++)
            				{
            					Judge(arr2, arr1, i, j);
            				}
            			}
            		}
            		else
            		{
            			return;
            		}
            	}
            }

            判断输赢

            输:即每排一次雷,检查一下雷盘对应的信息,如果是雷,就被炸死,如果不是,就继续排雷。

            赢:当玩家将所有的非雷的区域都排查出来时,判断为赢。(这里采用一个计数器,没排一次雷计数器就++一下,当计数器与总的非雷的区域数目相同时,判断为赢)

            void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS])
            {
            	int x = 0;
            	int y = 0;
            	while (1)
            	{
            		printf("请输入坐标:>");
            		scanf("%d,%d", &x, &y);
            		if (x >= 1 && x <= ROW && y >= 1 && y <= LOW)
            		{
            			if (arr1[x][y] == '1')
            			{
            				arr2[x][y] = '#';
            				displayboard(arr2, ROW, LOW);//排雷
            				printf("遗憾你输了\n");
            				break;
            			}
            			else
            			{
            				Judge(arr2, arr1, x, y);
            				displayboard(arr2, ROW, LOW);//排雷
            			}
            		}
            		else
            		{
            			printf("输入错误!\n");
            		}
             
            		//判断扫雷是否赢
            		int i = 0, flag = 0;
            		for (i = 1; i <= ROW; i++)
            		{
            			int j = 0;
            			for (j = 1; j <= LOW; j++)
            			{
            				if (arr2[i][j] != '*')
            				{
            					flag++;
            				}
            			}
            		}
            		if (flag == ROW*LOW - LEI)
            		{
            			printf("你赢了!\n");
            			break;
            		}
            	}
            }

            text.c实现

            #define  _CRT_SECURE_NO_WARNINGS 1
             
            #include "game.h"
            //菜单
            void menu()
            {
            	printf("*************************************\n");
            	printf("************1.开始游戏***************\n");
            	printf("************0.退出游戏***************\n");
            	printf("*************************************\n");
             
            }
             
             
            void game()
            {
            	//初始化棋盘
            	char arr1[ROWS][LOWS] = { 0 };//雷盘
            	char arr2[ROWS][LOWS] = { 0 };//玩家盘
            	board(arr1, ROWS, LOWS, '0');
            	board(arr2, ROWS, LOWS, '*');
            	//打印棋盘
            	//displayboard(arr1, ROW, LOW);//布置雷
            	displayboard(arr2, ROW, LOW);//排雷
            	//布置雷
            	Get_lei(arr1,ROW,LOW);
            	//排雷
            	Out_lei(arr2,ROW,LOW, arr1);
             
            }
            int main()
            {
            	int input = 0;
            	srand((unsigned int)time(NULL));
            	do
            	{
            		menu();
            		printf("请选择:>");
            		scanf("%d",&input);
            		switch (input)
            		{
            		case 1:
            		{
            			printf("扫雷\n");
            			game();
            			break;
            		}
            		case 0:
            		{
            			printf("退出游戏\n");
            			break;
            		}
            		default:
            		{
            			printf("选择错误\n");
            			break;
            		}
            		}
            	} while (input);
             
            	return 0;
            }

            game.c实现

            #define  _CRT_SECURE_NO_WARNINGS 1
             
            #include "game.h"
             
            //初始化棋盘
            void board(char arr1[ROWS][LOWS], int rows, int lows, char ret)
            {
            	int i = 0;
            	for (i = 0; i < rows; i++)
            	{
            		int j = 0;
            		for (j = 0; j < lows; j++)
            		{
            			arr1[i][j] = ret;
            		}
            	}
            }
             
            //打印棋盘
            void displayboard(char arr1[ROWS][LOWS], int row, int low)
            {
            	printf("<———扫雷游戏———>\n");
            	int i = 0;
            	for (i = 1; i <= row; i++)
            	{
            		int j = 0;
            		if (i == 1)
            		{
            			for (j = 0; j <= low; j++)
            			{
            				printf("%2d ", j);
            			}
            			printf("\n");
            		}
             
            		for (j = 1; j <= low; j++)
            		{
            			if (j == 1)
            			{
            				printf("%2d ", i);
            			}
            			
            			printf("%2c ", arr1[i][j]);
            		}
            		printf("\n");
            	}
            	printf("<———扫雷游戏———>\n");
             
            }
             
            //布置雷
            void Get_lei(char arr1[ROWS][LOWS], int row, int low)
            {
            	int count = LEI;
            	while (count)
            	{
            		int x = rand() % row + 1;
            		int y = rand() % low + 1;
            		if (arr1[x][y] == '0')
            		{
            			arr1[x][y] = '1';
            			count--;
            		}
            	}
            	//displayboard(arr1, ROW, LOW);
            }
            //玩家盘
            static int Get_num(char arr1[ROWS][LOWS],int x, int y)
            {
            	int count = 0;
            	int i = 0;
            	for (i = x - 1; i <= x + 1; i++)
            	{
            		int j = 0;
            		for (j = y - 1; j <= y + 1; j++)
            		{
            			if (arr1[i][j] == '1')
            			{
            				count++;
            			}
            		}
             
            	}
            	return count;
            }
            //判断是否展开,实现函数
            static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y)
            {
            	if (x > 0 && x <= ROW && y > 0 && y <= LOW)
            	{
            		int ret = Get_num(arr1, x, y);
            		if (ret != 0)
            			arr2[x][y] = ret + '0';
            		//递归散开
            		else if (arr1[x][y] != ' ')
            		{
            			arr2[x][y] = '0';
            			arr1[x][y] = ' ';
            			int i = 0;
            			for (i = x - 1; i <= x + 1; i++)
            			{
            				int j = 0;
            				for (j = y - 1; j <= y + 1; j++)
            				{
            					Judge(arr2, arr1, i, j);
            				}
            			}
            		}
            		else
            		{
            			return;
            		}
            	}
            }
            void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS])
            {
            	int x = 0;
            	int y = 0;
            	while (1)
            	{
            		printf("请输入坐标:>");
            		scanf("%d,%d", &x, &y);
            		if (x >= 1 && x <= ROW && y >= 1 && y <= LOW)
            		{
            			if (arr1[x][y] == '1')
            			{
            				arr2[x][y] = '#';
            				displayboard(arr2, ROW, LOW);//排雷
            				printf("遗憾你输了\n");
            				break;
            			}
            			else
            			{
            				Judge(arr2, arr1, x, y);
            				displayboard(arr2, ROW, LOW);//排雷
            			}
            		}
            		else
            		{
            			printf("输入错误!\n");
            		}
             
            		//判断扫雷是否赢
            		int i = 0, flag = 0;
            		for (i = 1; i <= ROW; i++)
            		{
            			int j = 0;
            			for (j = 1; j <= LOW; j++)
            			{
            				if (arr2[i][j] != '*')
            				{
            					flag++;
            				}
            			}
            		}
            		if (flag == ROW*LOW - LEI)
            		{
            			printf("你赢了!\n");
            			break;
            		}
            	}
            }
             
             

            game.h实现

            #pragma once
             
            #include <stdio.h>
            #include <stdlib.h>
             
            #define LEI 10
            #define ROW 10
            #define LOW 10
             
            #define ROWS ROW+2
            #define LOWS LOW+2
             
            //初始化棋盘
            void board(char arr1[ROWS][LOWS],int rows,int lows,char ret);
             
            //打印棋盘
            void displayboard(char arr1[ROWS][LOWS], int row, int low);
             
            //布置雷
            void Get_lei(char arr1[ROWS][LOWS], int row, int low);
            //玩家盘
            void Out_lei(char arr2[ROWS][LOWS], int row, int low, char arr1[ROWS][LOWS]);

            递归部分详解

            递归条件:1.有停止的条件。2.每一次递归都会向这个条件靠拢。

            那么这里的停止条件是什么呢?

            递归:当返回雷的个数为0时,就符合继续递归的条件,我们需要将当前坐标周围的点全部排除。且需要将已经排查了的坐标做一个标记,否则就会不停的排查下去,就会形成死递归。所以

            停止条件:当前这个坐标是已被排查过的,就停止递归。

            因为每一次排查都会的一个标记,所以这就是那个不断向停止条件靠拢的过程。

            //判断是否展开,实现函数
            static void Judge(char arr2[ROWS][LOWS], char arr1[ROWS][LOWS], int x, int y)
            {
            	if (x > 0 && x <= ROW && y > 0 && y <= LOW)
            	{
            		int ret = Get_num(arr1, x, y);
            		if (ret != 0)
            			arr2[x][y] = ret + '0';
            		//递归散开
            		else if (arr1[x][y] != ' ')
            		{
            			arr2[x][y] = '0';//玩家盘
            			arr1[x][y] = ' ';//雷盘
            			int i = 0;
            			for (i = x - 1; i <= x + 1; i++)
            			{
            				int j = 0;
            				for (j = y - 1; j <= y + 1; j++)
            				{
            					Judge(arr2, arr1, i, j);
            				}
            			}
            		}
            		else
            		{
            			return;
            		}
            	}
            }

            总结

            声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。