【C语言】扫雷游戏的拓展 2.0版(超详细)

在前面讲到了如何实现扫雷游戏

💡 扫雷游戏初版

今天来讲讲如何实现它的拓展,全部的代码放在文章的最后处

一.拓展的功能如下:

• 选择游戏难度
  ◦ 简单 9*9 棋盘,10个雷
  ◦ 中等 16*16棋盘,40个雷
  ◦ 困难 30*16棋盘,99个雷
• 展开周围的一片 

• 标记雷

1.选择游戏难度

由于我们之前首先定义了棋盘的row col的大小,导致最多只能玩一种难度,这里我们稍微改动一下 ,给game函数传入参数,使得可以选择三种难度

2. 展开周围的一片 

在之前的程序里 排查雷时,若是雷则被炸死,游戏结束; 若输入的坐标不是雷且周围没有雷,我们把它赋值为 0 ,若不是雷但周围有雷,赋值为它周围雷的个数。

现在我们需要展开周围的一片,如果不是雷则赋值为空格,来实现展开的效果

代码如下:

void Open(char mine[MAXSIZE][MAXSIZE], char show[MAXSIZE][MAXSIZE], int x, int y) {
		int count = Get(mine, x, y);
		if (count != 0) { //周围有雷
			show[x][y] = '0' + count;
		}
		else if (show[x][y] != ' ') { //周围无雷 且 还没被展开
			show[x][y] = ' ';
			int i, j;      //判断周围的坐标的周围有没有雷,直到有雷为止
			for (i = x - 1; i <= x + 1; i++) {
				for (j = y - 1; j <= y + 1; j++) {
					Open(mine,show, i, j);
				}
			}
		}
		else { return ; }
}

3. 标记雷

成功排查雷之后加一个标记雷的函数,标记地雷为 ?  ,这样更方便我们进行后续的排雷。

代码如下:

void Sign(char show[MAXSIZE][MAXSIZE]) {
	int i,x,y;
	do{
		printf("是否标记地雷?\n > 1开始标记 0退出标记\n");
		scanf("%d", &i);
		switch (i) {
		case 0:
			printf("您已退出标记\n");
			break;
		case 1:
			printf("标记雷的坐标:");
			scanf("%d %d", &x, &y);
			if (show[x][y] == '*') {
				show[x][y] ='?';
			}
			else printf("该坐标已被排查!请重新选择标记的位置\n");
		break;
		default: 
			printf("该指令无效,请重新下指令:\n");
		}


	}while(i);
}

二.源代码如下

game.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//#define ROW 9
//#define COL 9
//#define ROWS ROW+2
//#define COLS COL+2
//#define E 10
#define MAXSIZE 50

void Initboard(char a[MAXSIZE][MAXSIZE], int rows, int cols, char set);
void Displayboard(char a[MAXSIZE][MAXSIZE], int row, int col);
void Layoutboard(char a[MAXSIZE][MAXSIZE], int row, int col,int E);
void Find(char a[MAXSIZE][MAXSIZE], char b[MAXSIZE][MAXSIZE], int row, int col,int E);
void Open(char mine[MAXSIZE][MAXSIZE], char show[MAXSIZE][MAXSIZE], int , int y);
int Get(char show[MAXSIZE][MAXSIZE], int rows, int cols);
void Sign(char show[MAXSIZE][MAXSIZE]);

game.c


#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996)
#include"game.h"

void Initboard(char a[MAXSIZE][MAXSIZE], int rows, int cols, char set) {
	int i, j;
	for (i = 0; i < rows; i++) {
		for (j = 0; j < cols; j++) {
			a[i][j] = set;
		}
	}
}

void Displayboard(char a[MAXSIZE][MAXSIZE], int row, int col) {
	int i, j,i1=0,i2=0,i3=0;
	printf("__________________________________________\n");
	printf(" ");
	for (i = 0; i <= col; i++) {
		if (i>29) { 
			printf("%d ", i3++);
		}else if(i>19&&i<=29) printf("%d ", i2++);
		 else if(i>9&&i<=19)  printf("%d ", i1++);
		 else printf("%d ", i);
	}
	printf("\n");
	for (i = 1; i <= row; i++) {
		printf("%-2d ", i);
		for (j = 1; j <= col; j++) {
			printf("%c ", a[i][j]);
		}
		printf("\n");
	}
	printf("__________________________________________\n");
}

void Layoutboard(char a[MAXSIZE][MAXSIZE], int row, int col,int E) {
	int x, y;
	int e = E;
	while (e) {
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (a[x][y] != '1') {
			a[x][y] = '1';
			e--;
		}
	}
}

int Get(char mine[MAXSIZE][MAXSIZE], int x, int y) {
	return (mine[x - 1][y] + mine[x - 1][y - 1] + mine[x - 1][y + 1] +
		mine[x + 1][y + 1] + mine[x + 1][y - 1] + mine[x + 1][y] +
		mine[x][y - 1] + +mine[x][y + 1] - 8 * '0');
}
void Find(char mine[MAXSIZE][MAXSIZE], char show[MAXSIZE][MAXSIZE], int row, int col,int E) {
	int win = 0;
	int x, y;
	while (win < row * col - E) {
		printf("请输入一个坐标:\n");
		scanf("%d %d", &x, &y);
		if (x >= 1 && x <= row && y >= 1 && y <= col) {
			if (mine[x][y] == '1') {
				printf("很遗憾,你被炸死了\n");
				//显示出有雷的地方
				Displayboard(mine,row,col);
				break;
			}
			if (mine[x][y] == '0') {
				if ((show[x][y] >= '0' && show[x][y] <= '9') || show[x][y] == ' ') {
					printf("不好意思,该坐标已经排查过,请重新输入:\n");
				}
				//如果不是雷,展开一片(用mine数组)
				else {
					printf("恭喜你,该坐标不是雷\n");
					/*int count = get(mine, x, y);
					show[x][y] = count + '0';*/
					Open(mine, show, x, y);
					Displayboard(show,row,col);
					win++;
					Sign(show);
				}
			}
		}
		else {
			printf("输入错误,请重新输入:\n");
		}
	}
	if (win == row * col - E) {
		printf("恭喜你,排雷成功!!!\n");
		Displayboard(mine,row,col);
	}
}

void Open(char mine[MAXSIZE][MAXSIZE], char show[MAXSIZE][MAXSIZE], int x, int y) {
		int count = Get(mine, x, y);
		if (count != 0) { //周围有雷
			show[x][y] = '0' + count;
		}
		else if (show[x][y] != ' ') { //周围无雷 且 还没被展开
			show[x][y] = ' ';
			int i, j;      //判断周围的坐标的周围有没有雷,直到有雷为止
			for (i = x - 1; i <= x + 1; i++) {
				for (j = y - 1; j <= y + 1; j++) {
					Open(mine,show, i, j);
				}
			}
		}
		else { return; }
}

void Sign(char show[MAXSIZE][MAXSIZE]) {
	int i,x,y;
	do{
		printf("是否标记地雷?\n > 1开始标记 0退出标记\n");
		scanf("%d", &i);
		switch (i) {
		case 0:
			printf("您已退出标记\n");
			break;
		case 1:
			printf("标记雷的坐标:");
			scanf("%d %d", &x, &y);
			if (show[x][y] == '*') {
				show[x][y] ='?';
			}
			else printf("该坐标已被排查!请重新选择标记的位置\n");
		break;
		default: 
			printf("该指令无效,请重新下指令:\n");
		}


	}while(i);
}

test.c

#define _CRT_SECURE_NO_WARNINGS 1
#pragma warning(disable:4996)
#include "game.h"
void menu() {
	printf("******************************\n");
	printf("********** 1.简单难度 ********\n");
	printf("********** 2.中等难度 ********\n");
	printf("********** 3.困难难度 ********\n");
	printf("********** 0.结束游戏 ********\n");
	printf("******************************\n");
}
void game(int ROWS,int COLS,int ROW,int COL,int E) {
	char mine[MAXSIZE][MAXSIZE];
	char show[MAXSIZE][MAXSIZE];
	//1.先初始化
	Initboard(mine, ROWS, COLS, '0');
	Initboard(show, ROWS, COLS, '*');
	//Displayboard(mine,ROW,COL);
	Displayboard(show, ROW, COL);
	//2.给数组mine放置雷
	Layoutboard(mine, ROW, COL,E);
	//Displayboard(mine, ROW, COL);
	//3.找出雷
	Find(mine, show, ROW, COL,E);
}

int main() {
	srand((unsigned int)time(NULL));
	int n = 0;
	do {
		menu();
		printf("请选择:<");
		scanf("%d", &n);
	switch (n) {
		case 1:
		    game(11, 11, 9, 9, 10);
		    break;
		case 2:
		    game(18, 18, 16, 16, 40);
		    break;
		case 3:
		    game(18, 32, 16, 30, 99);
		    break;
		case 0:
			printf("游戏结束\n");
			break;
		default:
			printf("输入错误,请重新输入\n");
		}
	} while (n);


}

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值