C语言游戏之扫雷

今天给大家大家带来一个用c语言实现的扫雷游戏

首先说一下用c语言实现的扫雷游戏的特点

1.打印扫雷棋盘

2.玩家选择点开(扫雷)坐标

3.选中雷 --> 游戏结束

   没选中 --> 打印棋盘并提示刚才坐标周围的雷数(八个方向)

 再说下我的程序功能

1.游戏过程中,如果选的坐标八个方向都没有雷则展开这九个坐标并提示雷数

2.如果坐标四周没有雷则不进行提示显示空格

3.选中雷则在同一张棋盘上打印出所有雷的位置和先前的游戏记录

4.记录游戏时间

5.计分功能

6.提供标记雷和去标记的功能

如果对您有帮助或者启发不妨给我点一个赞或者关注哦~ 

游戏视频如下: 

 注意:

 扫雷游戏实现分三步
1 初始化
2 布置雷
3 扫雷

注意:
1)首先要清楚,扫雷棋盘上的元素:1)提示信息 2)雷   而我们在打印棋盘时不能将雷的位置打印出来。
所以,我么们就需要两个棋盘分别存贮这两种信息
2)扫雷时我们要给玩家在被点开处一个周围雷数的提示(0~8)。这个提示基于四周雷的个数,所以要对四周的坐标做出判断。
因此就出现了一个问题:在棋盘边角的元素如何判断?直接判断可能会造成溢出,所以我们给棋盘增加2行2列
3)字符和整型的转化问题


 由于我是用vs分三个文件写的,想测试我的代码的朋友不妨如下图方式打开:


下面带大家具体看看我的函数的实现: 

1. 游戏过程中,如果选的坐标八个方向都没有雷则展开这九个坐标并提示雷数

static int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) {
    int count = 0;//记录周围没有雷的点的个数
    if (HintMine(mine, x, y) == '0')
        count++;
    if (HintMine(mine, x - 1, y) == '0')    
        count++;
    if (HintMine(mine, x - 1, y-1) == '0')
        count++;
    if (HintMine(mine, x - 1, y+1) == '0')
        count++;
    if (HintMine(mine, x + 1, y) == '0')
        count++;
    if (HintMine(mine, x + 1, y-1) == '0')
        count++;
    if (HintMine(mine, x + 1, y+1) == '0')
        count++;
    if (HintMine(mine, x , y+1) == '0')
        count++;
    if (HintMine(mine, x , y-1) == '0')
        count++;
    if (count == 9) {
        show[x][y] = ' ';
        show[x-1][y] = ' ';
        show[x-1][y-1] = ' ';
        show[x-1][y+1] = ' ';
        show[x+1][y] = ' ';
        show[x+1][y-1] = ' ';
        show[x+1][y+1] = ' ';
        show[x][y-1] = ' ';
        show[x][y+1] = ' ';
        return 0;
    }
    else
        return 1;
    //如果是count = 9说明输入的坐标周围的点的周围都没有雷,则将这个区域全部亮出
    //否则,返回1执行操作
}
 static char HintMine(char board[ROWS][COLS], int x, int y) {
    return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
          + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]  
          + board[x][y - 1] + board[x][y + 1] - 7 * '0');
    //因为棋盘上没有雷就是‘0’,有雷就是‘1’,所以他们的ASCII值加起来减去8个‘0’的ASCII值就是周围的雷数,
    //雷数在加上一个‘0’的ACSII值就是之个数对应的ASCII值
}

 2.如果坐标四周没有雷则不进行提示显示空格

    if (HintMine(mine, x, y) == '0') {
             show[x][y] = ' ';
     }
     else
            show[x][y] = HintMine(mine, x, y);

 3.选中雷则在同一张棋盘上打印出所有雷的位置和先前的游戏记录

 void FailBoard(char mine[ROWS][COLS], 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++) {
             if (mine[i][j] == '1')
                 show[i][j] = '!';
         }
     }
 }

 6.提供标记雷和去标记的功能

    printf("是否执行操作?1.是 0.否 ->");
        scanf("%d", &choose);
        while (choose) {
            printf("1.标记地雷 2.取消标记 0.退出 -> ");
            scanf("%d", &mark);
            switch (mark) {
                case 1:
                    printf("请输入坐标:->");
                    scanf("%d %d", &x, &y);
                    if (show[x][y] == '*')
                        show[x][y] = '#';
                    else
                        printf("非法操作!\n");
                    DisplayBoard(show, ROW, COL);
                    break;
                case 2:
                    printf("请输入坐标:->");
                    scanf("%d %d", &x, &y);
                    if (show[x][y] == '#')
                        show[x][y] = '*';
                    else
                        printf("非法操作!\n");
                    DisplayBoard(show, ROW, COL);
                    break;
                case 0:
                    choose = 0;
                    break;
                default:
                    printf("选择错误请重新选择!\n");
            }

        }


下面就是我的程序源代码 

首先我们来看一下头文件game.h,这里基本包含这个程序所有的函数:


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

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

#define INIT_MINE '0'//这样后面的提示函数会比较好写
#define INIT_SHOW '*'
#define MARK '#'//标记地雷

#define MINENUM 15 //生成雷的个数

void InitBoard(char board[ROWS][COLS], int row, int col,char set);//初始化棋盘
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);//开始扫雷
char HintMine(char board[ROWS][COLS], int x, int y);//生成提示
int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//展开坐标周围
void FailBoard(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//失败棋盘

 游戏函数实现模块:

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"

void InitBoard(char board[ROWS][COLS], int row, int col,char set) {
	int i = 0;
	int j = 0;
	//这里初始化一定要全部初始化,方便后面判断。
	for (i = 0; i <row; i++) {
		for (j = 0; j <col; j++) {
			board[i][j] = set;
		}
	}
}
void DisplayBoard(char board[ROWS][COLS], int row, int col){
	int i = 0;
	int j = 0;
	int choose = 0;
	printf("本局地雷数:%d\n",MINENUM);
	printf("   ");
	for (i = 1; i <= col; i++) {
		printf("%d ", i);
	}
	printf("\n-------------------------------------\n");
	for (i = 1; i <= row; i++) {
		printf("%d |", i);
		for (j = 1; j <= col; j++) {
			printf("%c ", board[i][j]);
		}
		printf("\n");
	}
	printf("-------------------------------------\n");
}
void SetMine(char board[ROWS][COLS], int row, int col){
	int x = 0;
	int y = 0;
	int count = MINENUM;
	while (count) {
		x = rand() % row + 1;//这里row是9 一个随机数模9为0~8
		y = rand() % col + 1;
		if (board[x][y] == '0') {//字符和整型要分清,只有位置上是0才进行赋值,防止重复
			board[x][y] = '1';
			count--;
		}
	}
}
//文件内部调用的函数可以加上static
 static int Stretch(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y) {
	int count = 0;//记录周围没有雷的点的个数
	if (HintMine(mine, x, y) == '0')
		count++;
	if (HintMine(mine, x - 1, y) == '0')	
		count++;
	if (HintMine(mine, x - 1, y-1) == '0')
		count++;
	if (HintMine(mine, x - 1, y+1) == '0')
		count++;
	if (HintMine(mine, x + 1, y) == '0')
		count++;
	if (HintMine(mine, x + 1, y-1) == '0')
		count++;
	if (HintMine(mine, x + 1, y+1) == '0')
		count++;
	if (HintMine(mine, x , y+1) == '0')
		count++;
	if (HintMine(mine, x , y-1) == '0')
		count++;
	if (count == 9) {
		show[x][y] = ' ';
		show[x-1][y] = ' ';
		show[x-1][y-1] = ' ';
		show[x-1][y+1] = ' ';
		show[x+1][y] = ' ';
		show[x+1][y-1] = ' ';
		show[x+1][y+1] = ' ';
		show[x][y-1] = ' ';
		show[x][y+1] = ' ';
		return 0;
	}
	else
		return 1;
	//如果是count = 9说明输入的坐标周围的点的周围都没有雷,则将这个区域全部亮出
	//否则,返回1执行操作
}
 static char HintMine(char board[ROWS][COLS], int x, int y) {
	return (board[x - 1][y] + board[x - 1][y - 1] + board[x - 1][y + 1]
		  + board[x + 1][y] + board[x + 1][y - 1] + board[x + 1][y + 1]  
		  + board[x][y - 1] + board[x][y + 1] - 7 * '0');
	//因为棋盘上没有雷就是‘0’,有雷就是‘1’,所以他们的ASCII值加起来减去8个‘0’的ASCII值就是周围的雷数,
	//雷数在加上一个‘0’的ACSII值就是之个数对应的ASCII值
}
 void FailBoard(char mine[ROWS][COLS], 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++) {
			 if (mine[i][j] == '1')
				 show[i][j] = '!';
		 }
	 }
 }
void FindMine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col) {
	int x = 0;
	int y = 0;
	int count = row*col;
	double begin = 0;//开始时间
	double end = 0;//结束时间
	int choose = 0;//选项
	int mark = 0;//选项
	int score = 0;//计分
	begin = (double)clock();
	while (count-MINENUM) {
		printf("是否执行操作?1.是 0.否 ->");
		scanf("%d", &choose);
		while (choose) {
			printf("1.标记地雷 2.取消标记 0.退出 -> ");
			scanf("%d", &mark);
			switch (mark) {
				case 1:
					printf("请输入坐标:->");
					scanf("%d %d", &x, &y);
					if (show[x][y] == '*')
						show[x][y] = '#';
					else
						printf("非法操作!\n");
					DisplayBoard(show, ROW, COL);
					break;
				case 2:
					printf("请输入坐标:->");
					scanf("%d %d", &x, &y);
					if (show[x][y] == '#')
						show[x][y] = '*';
					else
						printf("非法操作!\n");
					DisplayBoard(show, ROW, COL);
					break;
				case 0:
					choose = 0;
					break;
				default:
					printf("选择错误请重新选择!\n");
			}

		}
		rechoose:
		printf("请亮出输入坐标:->");
		scanf("%d %d", &x, &y);
		 if (show[x][y] == '#') {
			printf("这是您标记的地雷!确定要打开吗?->1.是 0.否");
			scanf("%d", &choose);
			if (choose == 0)
				goto rechoose;
		 }
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == '1') {
				end = (double)clock();
				printf("可惜,你被炸死了!	用时%.1f秒	 得分:%d分\n", (end - begin) / CLOCKS_PER_SEC,score);//使用clock()计时需要一个差,除以CLOCKS_PER_SEC转化单位为秒
				FailBoard(mine,show, ROW, COL);
				DisplayBoard(show, ROW, COL);
				break;
			}
			else {
				if (show[x][y] == '*') {
					if (Stretch(mine, show, x, y)) {
						if (HintMine(mine, x, y) == '0') {
							show[x][y] = ' ';
						}
						else
							show[x][y] = HintMine(mine, x, y);
						DisplayBoard(show, ROW, COL);
						count--;
						score++;
					}
					else {
						count -= 9;//x,y周围都被亮出,棋盘上减少了9个数
						score += 9;
						DisplayBoard(show, ROW, COL);
					}
				}
			
				else
					printf("这个坐标您已经检查过了!请重新输入\n");
			}
		}
		else
			printf("输入坐标非法!请重新输入\n");
	}
	if (!(count - MINENUM)) {
		end = (double)clock();
		printf("恭喜你!获得胜利!	用时%.1f秒\n	得分:%d分", (end - begin) / CLOCKS_PER_SEC,score);
	}
	
}

 main函数所在的test.c文件

#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void menu() {
	printf("\n                        ==================================\n");
	printf("                        *          欢迎来到扫雷游戏  !  *\n");
	printf("                        *  请输入选项:                  *\n");
	printf("                        *             1.  play           *\n");
	printf("                        *             0.  exit           *\n");
	printf("                        *                                *\n");
	printf("                        ==================================\n\n");
}
void game() {
	char mine[ROWS][COLS];//定义放置雷的数组
	char show[ROWS][COLS];//定义防止提示的数组
	srand((unsigned)time(NULL));
	InitBoard(mine,ROWS,COLS,INIT_MINE);//初始化雷
	InitBoard(show, ROWS, COLS,INIT_SHOW);//初始化提示
	//DisplayBoard(mine,ROW,COL);
	DisplayBoard(show, ROW, COL);
	SetMine(mine, ROW, COL);
	FindMine(mine, show, ROW, COL);	

}
void test() {
	int Input = 0;
	do {
		menu();
		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;
}

以上

谢谢观看

发布了19 篇原创文章 · 获赞 88 · 访问量 3264

猜你喜欢

转载自blog.csdn.net/qq_44954010/article/details/103825633