【C语言】扫雷游戏的编译与实现(细节与过程)

思路:

  1. 0表示无,1表示雷
  2. 1表示雷还是雷的个数不清楚,所以用两个数组分别存放
  3. 为了防止越界,方便统计九宫格的雷数量,加俩行俩列,即9x9 —> 11x11
  4. 棋盘11x11,且为字符数组

代码实现:

  1. test.c 测试游戏的代码
  2. game.c 游戏的实现
  3. game.h 游戏函数的声明

步骤:

        1.菜单

(1)菜单在test.c源文件内实现

#include "game.h"

void menu()//打印菜单
{
	printf("************************\n");
	printf("******* 1 : enter ******\n");
	printf("******* 0 : exit  ******\n");
	printf("************************\n");
}

int main()
{
	srand((unsigned int)time(NULL));//此为随机时间戳,后面会用到,此处不赘述

	int input = 0;

	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("非法输入,请重试\n");
			break;
		}
	} while (input);

	return 0;
}

        2.设置棋盘

(1)先设置两个二维数组,即设置棋盘

(2)设置11*11便于在排查雷时显示九宫格雷数     

(3)因采用数字显冗杂,故采用宏定义,在game.h头文件中实现

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

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

void game()
{
	char mine[ROWS][COLS];//存放雷
	char show[ROWS][COLS];//排查雷
}

                                                                                         

        3.初始化棋盘

(1)再用函数初始化棋盘,这里采用 0无雷,1有雷

(2)为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用,下图为test.c文件的代码

void game()
{
    char mine[ROWS][COLS];//存放雷
	char show[ROWS][COLS];//排查雷    

    Intiboard(mine, ROWS, COLS, '0');
    Intiboard(show, ROWS, COLS, '*');
}

(3)因为使用的函数在源文件的game()函数内,所以要在game.h头文件中进行函数的声明

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);

(4)下图为game.c文件内具体函数的实现

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void Intiboard(char board[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++)
		{
			board[i][j] = set;
		}
	}
}

        4.打印棋盘

(1)同样头文件函数声明

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2

void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);

void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);

(2)打印只需要9*9的格子,下图为test.c文件代码

void game()
{
    char mine[ROWS][COLS];//存放雷
    char show[ROWS][COLS];//排查雷

    Intiboard(mine, ROWS, COLS, '0');
    Intiboard(show, ROWS, COLS, '*');

    //打印棋盘
    //Displayboard(mine, ROW, COL);
    Displayboard(show, ROW, COL);
}

(3)打印中间9*9,顾从1开始,9结束,下图为game.c文件内函数实现

Displayboard(char board[ROWS][COLS], int row, int col)
{
	int i = 0;
	for ( i = 1; i <= row; i++)
	{
		int j = 0;
		for ( j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

此代码打印出的棋盘如图

(4)为了美观,修改代码如图


void Displayboard(char board[ROWS][COLS], int row, int col)
{
	printf("*********扫雷游戏*********\n");

	int i = 0;

	printf("  | ");
	for (  i = 1; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	printf("  | ");
	for (i = 1; i <= col; i++)
	{
		printf("--");
	}
	printf("\n");

	for (i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
	{
		int j = 0;
		printf("%d | ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

效果如图

        5.设置雷

(1)头文件函数声明

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10

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

//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);

void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);

void Setmine(char board[ROWS][COLS], int row, int col);

(2)随机数设置雷,注意此处用到一开始提到的时间戳,其中相应头文件,在game.h中实现,下图为game.c中函数实现

void Setmine(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = Eazycount;//此处同样采用宏定义更方便,还可便于动态测试程序是否可行

	while (count)
	{
		x = rand() % 9 + 1;//随机数设置雷
		y = rand() % 9 + 1;

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

(3)下图是源文件test.c的函数调用及时间戳的实现

void game()
{
	//先设置两个二维数组,即设置棋盘
	//设置11便于在排查雷时显示九宫格雷数
	char mine[ROWS][COLS];//存放雷
	char show[ROWS][COLS];//排查雷
	//因采用数字显冗杂,故采用宏定义,在头文件中实现
	
	//再用函数初始化棋盘,这里采用 0无雷,1有雷
	Intiboard(mine, ROWS, COLS, '0');
	Intiboard(show, ROWS, COLS, '*');
	//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用

	//打印棋盘
	//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
	Displayboard(show, ROW, COL);

	//设置雷
	Setmine(mine, ROW, COL);
	//Displayboard(mine, ROW, COL);
}

int main()
{
    srand((unsigned int)time(NULL));

    return 0;
}

        6.寻找雷

(1)game.h头文件中函数的声明

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10

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

//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);

void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);

void Setmine(char board[ROWS][COLS], int row, int col);

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

(2)test.c源代码的函数调用

void game()
{
	//先设置两个二维数组,即设置棋盘
	//设置11便于在排查雷时显示九宫格雷数
	char mine[ROWS][COLS];//存放雷
	char show[ROWS][COLS];//排查雷
	//因采用数字显冗杂,故采用宏定义,在头文件中实现
	
	//再用函数初始化棋盘,这里采用 0无雷,1有雷
	Intiboard(mine, ROWS, COLS, '0');
	Intiboard(show, ROWS, COLS, '*');
	//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用

	//打印棋盘
	//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
	Displayboard(show, ROW, COL);

	//设置雷
	Setmine(mine, ROW, COL);
	//Displayboard(mine, ROW, COL);

	//排查雷
	Findmine(mine, show, ROW, COL);

}

(3)当排查完所以雷,即知道所以非雷坐标后,结束,所以采用循环结构

(4)被排查点显示数等于周围8个数减去'0'ASCII码值的八倍

(5)注意在使棋盘显示出周围雷个数时,应该加上'0',因为数组只能显示字符类型,这里用ASCII码值转换

(6)下图为game.c中的代码实现

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;//设置胜利条件

	while ( win < row * col - Eazycount)//当排查完所以雷,即知道所以非雷坐标后,循环结束
	{
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		if (x <= 9 && x >= 1 && y <= 9 && y >= 1)//坐标需要满足条件
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			else
			{
				int num = Getmine(mine, x, y);
				show[x][y] = num + '0';//因为要用字符类型,所以用ASCII码值转换
				Displayboard(show, ROW, COL);
				win++;//每排查出一个雷,则win+1
			}
		}
		else
		{
			printf("非法输入,请重试:>");
		}
		if (win == row * col - Eazycount)
		{
			printf("恭喜你,你赢了,埋雷如图\n");
			Displayboard(mine, ROW, COL);
		}
	}
	
}

int Getmine(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
		mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}

        7.总代码实现

(1)game.h

#pragma once

#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#define Eazycount 10

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

//因为使用的函数在源文件的game()函数内,所以要进行函数的声明
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);
void Intiboard(char board[ROWS][COLS], int rows, int cols, char set);

void Displayboard(char board[ROWS][COLS], int row, int col);
void Displayboard(char board[ROWS][COLS], int row, int col);

void Setmine(char board[ROWS][COLS], int row, int col);

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);

(2)test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"//因要包含game.h,则在game.h中引入需要的头文件更简洁

void menu()//打印菜单
{
	printf("************************\n");
	printf("******* 1 : enter ******\n");
	printf("******* 0 : exit  ******\n");
	printf("************************\n");
}

void game()
{
	//先设置两个二维数组,即设置棋盘
	//设置11便于在排查雷时显示九宫格雷数
	char mine[ROWS][COLS];//存放雷
	char show[ROWS][COLS];//排查雷
	//因采用数字显冗杂,故采用宏定义,在头文件中实现
	
	//再用函数初始化棋盘,这里采用 0无雷,1有雷
	Intiboard(mine, ROWS, COLS, '0');
	Intiboard(show, ROWS, COLS, '*');
	//为更加简洁,这里将 0 和 * 各自放在引用值中,便于一函数多用

	//打印棋盘
	//Displayboard(mine, ROW, COL);//打印只需要9*9的格子
	Displayboard(show, ROW, COL);

	//设置雷
	Setmine(mine, ROW, COL);
	//Displayboard(mine, ROW, COL);

	//排查雷
	Findmine(mine, show, ROW, COL);

}


int main()
{
	srand((unsigned int)time(NULL));

	int input = 0;

	do
	{
		menu();
		printf("请输入:>");
		scanf("%d", &input);
		switch (input)
		{
		case 1:
			game();
			break;
		case 0:
			printf("退出\n");
			break;
		default:
			printf("非法输入,请重试\n");
			break;
		}
	} while (input);

	return 0;
}

(3)game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void Intiboard(char board[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++)
		{
			board[i][j] = set;//因为数组用的字符类型,所以这里也要字符类型,0加''号
		}
	}
}


//Displayboard(char board[ROWS][COLS], int row, int col)
//{
//	int i = 0;
//	for ( i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
//	{
//		int j = 0;
//		for ( j = 1; j <= col; j++)
//		{
//			printf("%c ", board[i][j]);
//		}
//		printf("\n");
//	}
//}

//为了美观,进行修正
void Displayboard(char board[ROWS][COLS], int row, int col)
{
	printf("*********扫雷游戏*********\n");

	int i = 0;

	printf("  | ");
	for (  i = 1; i <= col; i++)
	{
		printf("%d ", i);
	}
	printf("\n");

	printf("  | ");
	for (i = 1; i <= col; i++)
	{
		printf("--");
	}
	printf("\n");

	for (i = 1; i <= row; i++)//打印中间9*9,顾从1开始,9结束
	{
		int j = 0;
		printf("%d | ", i);
		for (j = 1; j <= col; j++)
		{
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
}

void Setmine(char board[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int count = Eazycount;//此处同样采用宏定义更方便,还可便于动态测试程序是否可行

	while (count)
	{
		x = rand() % 9 + 1;//随机数设置雷
		y = rand() % 9 + 1;

		if (board[x][y] == '0')
		{
			board[x][y] = '1';
			count--;
		}
	}
}

void Findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)
{
	int x = 0;
	int y = 0;
	int win = 0;//设置胜利条件

	while ( win < row * col - Eazycount)//当排查完所以雷,即知道所以非雷坐标后,循环结束
	{
		printf("请输入坐标:>");
		scanf("%d %d", &x, &y);
		if (x <= 9 && x >= 1 && y <= 9 && y >= 1)//坐标需要满足条件
		{
			if (mine[x][y] == '1')
			{
				printf("很遗憾,你被炸死了\n");
				Displayboard(mine, ROW, COL);
				break;
			}
			else
			{
				int num = Getmine(mine, x, y);
				show[x][y] = num + '0';//因为要用字符类型,所以用ASCII码值转换
				Displayboard(show, ROW, COL);
				win++;//每排查出一个雷,则win+1
			}
		}
		else
		{
			printf("非法输入,请重试:>");
		}
		if (win == row * col - Eazycount)
		{
			printf("恭喜你,你赢了,埋雷如图\n");
			Displayboard(mine, ROW, COL);
		}
	}
	
}

int Getmine(char mine[ROWS][COLS], int x, int y)
{
	return (mine[x - 1][y - 1] + mine[x][y - 1] + mine[x + 1][y - 1] + mine[x - 1][y] + mine[x + 1][y] +
		mine[x - 1][y + 1] + mine[x][y + 1] + mine[x + 1][y + 1] - 8 * '0');
}

        8.运行测试

(1)为了便于测试运行,将雷数Eazycount设置为80,并打印出埋雷棋盘

结语

以上便是C语言扫雷代码实现全过程,感谢大家垂阅!

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值