• c语言——扫雷游戏(简易版)


    前言

    什么是扫雷游戏
    游戏目标是在最短的时间内根据点击格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
    这个游戏对于c语言的初学者来说难度还是挺大的,那我就实现一个初学者也能快速学会的初级版扫雷游戏。

    游戏设计

    我们先创建三个文件

    1. game.h、game.c(游戏逻辑的实现)
      2.test.c(游戏功能测试)

    这些是我们需要实现的游戏功能

    //初始化棋盘
    void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
    //打印棋盘
    void DisPlayBoard(char arr[ROWS][COLS], int row, int col);
    //布置雷
    void SetMine(char arr[ROWS][COLS],int row, int col);
    //排查雷
    void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row,int col);
    

    再次之前,我们在测试文件里先创建游戏菜单

    //test.c
    void meun()
    {
    	printf("******************\n");
    	printf("***** 1.play  ****\n");
    	printf("***** 0.exit  ****\n");
    	printf("******************\n");
    }
    

    之后再实现菜单功能

    void test()
    {
    	int input = 0;
    	srand((unsigned int)(time(NULL)));
    	do {
    		meun();
    		printf("请选择:>");
    		scanf("%d", &input);
    		switch(input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("游戏结束,退出游戏\n");
    			break;
    		default:
    			printf("输入错误,请重新选择\n");
    			break;
    		}
    	} while (input);
    }
    

    游戏规则

    1.如果这个位置是雷,那么游戏结束
    2.如果把不是雷的位置都找出来了,那么游戏结束
    3.如果这个位置不是雷,就计算这个位置的周围的8个格子有几个雷,并显示出雷的个数

    我以一个9*9的的棋盘为例,在棋盘中,雷为1,非雷为0,如果我选中非雷,并且周围雷的数量为1,那么我如何区分呢?
    其实创建两个棋盘就能解决了,一个棋盘放置雷的信息,一个棋盘给玩家展示,就能很好的解决。
    在这里插入图片描述

    //test.c
    void game()
    {
    	//mine数组中存放布置好雷的信息
    	char mine[ROWS][COLS] = { 0 };//数组全部初始化为字符'0'
    	//show数组中存放排查出雷的信息
    	char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'
    	//初始化棋盘
    	InitBoard(mine, ROWS, COLS, '0');
    	InitBoard(show, ROWS, COLS, '*');  
    	//布置雷
    	SetMine(mine, ROWS, COLS);
    	
    	//打印棋盘
    	//DisPlayBoard(mine, ROW, COL);
    	DisPlayBoard(show, ROW, COL);
    	
    	//排查雷
    	FindMine(mine, show, ROWS, COLS);
    }
    

    然后我们初始化棋盘

    //game.c
    #include "game.h"//记得包含头文件
    void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
    {
    	int i = 0;
    	for (i = 0; i < rows; i++)
    	{
    		int j = 0;
    		for (j = 0; j < cols; j++)
    		{
    			arr[i][j] = set;
    		}
    	}
    }
    

    打印棋盘

    void DisPlayBoard(char arr[ROWS][COLS], int row, int col)
    {
    	int i = 0;
    	printf("-------扫雷游戏--------\n");
    	for (i = 0; i <= col; i++)//打印列
    	{
    		printf("%d ", i);
    	}
    	printf("\n");
    	for (i = 1; i <= row; i++)
    	{
    		int j = 0;
    		printf("%d ", i);//打印行
    		for (j = 1; j <= col; j++)
    		{
    			printf("%c ", arr[i][j]);	
    		}
    		printf("\n");
    	}
    }
    

    如果我们不打印行和列等会就无法定位坐标

    在这里插入图片描述
    然后就可以开始布置雷了
    我们先实现简单版

    //game.h
    //行和列
    #define ROW 9
    #define COL 9
    
    #define ROWS ROW+2
    #define COLS COL+2
    
    #define EASY_COUNT 10//雷的数量 
    

    这里用rand因为是想随机布置雷,rand如何使用大家可以顺便了解一下

    rand()和srand()的关系
    rand()和srand()要一起使用,其中srand()用来初始化随机数种子,rand()用来产生随机数。
    因为默认情况下随机数种子为1,而相同的随机数种子产生的随机数是一样的,失去了随机性的意义,所以为使每次得到的随机数不一样,用函数srand()初始化随机数种子。srand()的参数,用time函数值(即当前时间),因为两次调用rand()函数的时间通常是不同的,这样就可以保证随机性了。

    //布置雷
    void SetMine(char arr[ROWS][COLS], int row, int col)
    {
    	int count = EASY_COUNT;
    	while (count)
    	{
    		int x = rand() & row + 1;
    		int y = rand() & col + 1;
    		if (arr[x][y] == '0')
    			arr[x][y] = '1';
    		count--;
    	}
    }
    
    //test.c
    void test()
    {
    	int input = 0;
    	srand((unsigned int)(time(NULL)));
    	do {
    		meun();
    		printf("请选择:>");
    		scanf("%d", &input);
    		switch(input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("游戏结束,退出游戏\n");
    			break;
    		default:
    			printf("输入错误,请重新选择\n");
    			break;
    		}
    	} while (input);
    }
    

    排查地雷

    //game.c
    /*第一种方法
    int GetMineCount(char arr[ROWS][COLS],int x, int y)
    {
    	int count = 0;
    	for (int i = x - 1; i <= x + 1; x++)
    	{
    		for (int j = y - 1; j <= y + 1; j++)
    		{
    			count += (arr[x][y] - '0');
    		}
    	}
    	return count;
    }*/
    //第二种
    int GetMineCount(char mine[ROWS][COLS], int x, int y)
    {
    	return mine[x + 1][y] + mine[x - 1][y] +
    		mine[x][y + 1] + mine[x][y - 1] +
    		mine[x + 1][y + 1] + mine[x - 1][y + 1] +
    		mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
    }
    //排查雷
    void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int win = 0;
    	int x = 0;
    	int y = 0;
    	while (win < row * col - EASY_COUNT)
    	{
    		printf("请输入要查找的坐标:");
    		scanf("%d %d", &x, &y);
    		//检查坐标的有效性
    		if (x > 1 && x <= row && y > 1 && y <=col)
    		{
    			if (show[x][y] == '*')
    			{
    				if (mine[x][y] == '1')
    				{
    					printf("倒霉鬼,你被炸死了");
    					DisPlayBoard(mine, ROW, COL);
    					break;
    				}
    				else
    				{
    					//该坐标不是雷,统计附近的雷的数量
    					int count = GetMineCount(mine, x, y);
    					show[x][y] = count + '0';
    					DisPlayBoard(show, ROW, COL);
    					win++;
    				}
    			}
    			else
    			{
    				printf("该坐标已经被排查了,重新输入坐标\n");
    			}
    		}
    		else
    		{
    			printf("请重新输入,坐标错误:");
    		}
    	}
    	if (win == row * col - EASY_COUNT)
    	{
    		printf("恭喜你,排雷成功!");
    		DisPlayBoard(mine, ROW, COL);
    	}
    
    }
    

    源码:
    game.h

    #include 
    #include 
    #include 
    //行和列
    #define ROW 9
    #define COL 9
    
    #define ROWS ROW+2
    #define COLS COL+2
    
    #define EASY_COUNT 10//雷的数量 
    //初始化棋盘
    void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set);
    //打印棋盘
    void DisPlayBoard(char arr[ROWS][COLS], int row, int col);
    //布置雷
    void SetMine(char arr[ROWS][COLS],int row, int col);
    //排查雷
    void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row,int col);
    

    game.c

    #define _CRT_SECURE_NO_WARNINGS 1
    #include "game.h"
    void InitBoard(char arr[ROWS][COLS], int rows, int cols, char set)
    {
    	int i = 0;
    	for (i = 0; i < rows; i++)
    	{
    		int j = 0;
    		for (j = 0; j < cols; j++)
    		{
    			arr[i][j] = set;
    		}
    	}
    }
    
    void DisPlayBoard(char arr[ROWS][COLS], int row, int col)
    {
    	int i = 0;
    	printf("-------扫雷游戏--------\n");
    	for (i = 0; i <= col; i++)
    	{
    		printf("%d ", i);
    	}
    	printf("\n");
    	for (i = 1; i <= row; i++)
    	{
    		int j = 0;
    		printf("%d ", i);
    		for (j = 1; j <= col; j++)
    		{
    			printf("%c ", arr[i][j]);	
    		}
    		printf("\n");
    	}
    }
    //布置雷
    void SetMine(char arr[ROWS][COLS], int row, int col)
    {
    	
    	int count = EASY_COUNT;
    	while (count)
    	{
    		int x = rand() & row + 1;
    		int y = rand() & col + 1;
    		if (arr[x][y] == '0')
    			arr[x][y] = '1';
    		count--;
    	}
    }
    
    int GetMineCount(char mine[ROWS][COLS], int x, int y)
    {
    	return mine[x + 1][y] + mine[x - 1][y] +
    		mine[x][y + 1] + mine[x][y - 1] +
    		mine[x + 1][y + 1] + mine[x - 1][y + 1] +
    		mine[x - 1][y - 1] + mine[x + 1][y - 1] - 8 * '0';
    }
    
    
    int GetMineCount(char arr[ROWS][COLS],int x, int y)
    {
    	int count = 0;
    	for (int i = x - 1; i <= x + 1; x++)
    	{
    		for (int j = y - 1; j <= y + 1; j++)
    		{
    			count += (arr[x][y] - '0');
    		}
    	}
    	return count;
    }
    //排查雷
    void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
    {
    	int win = 0;
    	int x = 0;
    	int y = 0;
    	while (win < row * col - EASY_COUNT)
    	{
    		printf("请输入要查找的坐标:");
    		scanf("%d %d", &x, &y);
    		//检查坐标的有效性
    		if (x > 1 && x <= row && y > 1 && y <=col)
    		{
    			if (show[x][y] == '*')
    			{
    				if (mine[x][y] == '1')
    				{
    					printf("倒霉鬼,你被炸死了");
    					DisPlayBoard(mine, ROW, COL);
    					break;
    				}
    				else
    				{
    					//该坐标不是雷,统计附近的雷的数量
    					int count = GetMineCount(mine, x, y);
    					show[x][y] = count + '0';
    					DisPlayBoard(show, ROW, COL);
    					win++;
    				}
    			}
    			else
    			{
    				printf("该坐标已经被排查了,重新输入坐标\n");
    			}
    		}
    		else
    		{
    			printf("请重新输入,坐标错误:");
    		}
    	}
    	if (win == row * col - EASY_COUNT)
    	{
    		printf("恭喜你,排雷成功!");
    		DisPlayBoard(mine, ROW, COL);
    	}
    
    }
    

    test.c

    #define _CRT_SECURE_NO_WARNINGS 1
    
    #include "game.h"
    void meun()
    {
    	printf("******************\n");
    	printf("***** 1.play  ****\n");
    	printf("***** 0.exit  ****\n");
    	printf("******************\n");
    }
    void game()
    {
    	//mine数组中存放布置好雷的信息
    	char mine[ROWS][COLS] = { 0 };//数组全部初始化为字符'0'
    	//show数组中存放排查出雷的信息
    	char show[ROWS][COLS] = { 0 };//数组全部初始化为'*'
    	//初始化棋盘
    	InitBoard(mine, ROWS, COLS, '0');
    	InitBoard(show, ROWS, COLS, '*');  //这里是你字母打错了  现在可以了哦
    	//布置雷
    	SetMine(mine, ROWS, COLS);
    	
    	//打印棋盘
    	//DisPlayBoard(mine, ROW, COL);
    	DisPlayBoard(show, ROW, COL);
    	
    	//排查雷
    	FindMine(mine, show, ROWS, COLS);
    }
    void test()
    {
    	int input = 0;
    	srand((unsigned int)(time(NULL)));
    	do {
    		meun();
    		printf("请选择:>");
    		scanf("%d", &input);
    		switch(input)
    		{
    		case 1:
    			game();
    			break;
    		case 0:
    			printf("游戏结束,退出游戏\n");
    			break;
    		default:
    			printf("输入错误,请重新选择\n");
    			break;
    		}
    	} while (input);
    }
    int main()
    {
    	test();
    
    	return 0;
    }
    

    运行效果:
    在这里插入图片描述
    希望这篇博客对你有所帮助!!!

  • 相关阅读:
    存储优化知识复习一详细版解析
    如何使用 Docker 部署 Appsmith 低代码平台
    产品-Axure9英文版,A页面内a1状态跳转B页面的b2状态,(条件跳转状态)
    13、Callable介绍(Thread如何启动Callable)
    7-39 最优合并问题——优先队列
    Java:代理模式详解
    ChatGPT付费创作系统V2.3.4独立版 +WEB端+ H5端 + 小程序最新前端
    SQL INSERT INTO SELECT 语句
    设计模式简要总结
    【区块链 | 智能合约】Ethereum源代码(2)- go-ethereum 客户端入口代码和Node分析
  • 原文地址:https://blog.csdn.net/super_coders/article/details/139721707