c项目之扫雷

时间:2022-01-12 21:01:31

扫雷游戏
功能实现:
    1、可以选择难度级别(初级、中级、高级);
    2、实现了连续无雷区的显示。
设计思路:
    1、有难度的选择:初级、中级、高级,不同的难度级别会有不同数量的雷和不一样大小的网格;
    2、通过输入坐标来确定你选择的踩雷位置, 当你踩到此区显示0(即它的周围无雷)时,它会在显示周围各个位置(8个)的数字,若它周围的位置有显示0的情况,则同样又会显示它 周围各个位置(8个)的数字 ,依次向外扩散,若出现不为0(即周围有雷)的情况,则不再继续显示该位置周围的位置。若是踩到该位置有雷,游戏结束;
    3、在统计周边雷的个数时,为了省略对周边的位置是否超出数组大小,在定义数组时,定义为[+2][+2]形式。
c项目之扫雷
所遇问题并解决:
    1、返回值为char型的函数,虽返回char型,但是char在内存中以数字形式(即为它的ASCII码)存储,所以在赋值给char型变量时,需要通过+'0'的形式使其存储的ASCII码显示为字符(转化);强制类型转换:对内存空间未改变,仅是“看做”;
    2、显示一大片无雷区的实现:用循环逻辑实现,分为四个方向,均向边界处循环判断;
    3、选择难度级别的实现:均定义难度级别最高的数组大小,但用各自难度级别数组的大小来决定输出与判断,这样解决了三个难度级别所对应三个数组的问题。

#ifndef _CLEARMINES_H_
#define _CLEARMINES_H_

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

#pragma warning(disable:4996)

#define ROW 16
#define COL 30
#define MineSum 99

void playPrimary();
void playIntermediate();
void playAdvanced();

#endif

#include"clearMines.h"

void view()
{
	printf("*********************************\n");
	printf("********* 欢迎来到扫雷!*********\n");
	printf("******** 1:paly!  0:exit! *******\n");
	printf("*********************************\n");
	printf("please select:");
}

void selectModelView()
{
	printf("**********************************\n");
	printf("********** 选择游戏难度 **********\n");
	printf("* a:初级(10个雷,9*9平铺网格)***\n");
	printf("* b:中级(40个雷,16*16平铺网格)*\n");
	printf("* c:高级(99个雷,16*30平铺网格)*\n");
	printf("**********************************\n");
	printf("please select:");
}


int main()
{
	int sel;
	char selmod;
	do{
		view();
		scanf("%d", &sel);
		switch (sel)
		{
		case 0:
			exit(0);
		case 1:
			system("cls");
			do{
				fflush(stdin);
				selectModelView();
				scanf("%c", &selmod);
				switch (selmod)
				{
				case 'a':
					playPrimary(ROW - 7, COL - 21, MineSum - 89);
					break;
				case 'b':
					playIntermediate(ROW, COL - 14, MineSum - 59);
					break;
				case 'c':
					playAdvanced(ROW, COL, MineSum);
					break;
				default:
					printf("input error.try again!\n");
					break;
				}
			} while (selmod != 'a' && selmod != 'b' && selmod != 'c');
			break;
		default:
			printf("input error.try again!\n");
			break;
		}
	} while (1);
	system("pause");
	return 0;
}

#include"clearMines.h"

static void showView(char MineOrView[][COL + 2], int row, int col)
{
	int k = 1;
	printf("  ");
	for (k = 1; k <= col; k++){
		printf("%3d", k);
	}
	printf("\n___");
	for (k = 0; k < col; k++){
		printf("___");
	}
	printf("\n");

	int i = 1;
	for (; i <= row; i++){
		int j = 1;
		printf("%2d", i);
		for (; j <= col; j++){
			printf("|%2c", MineOrView[i][j]);
		}
		printf("|\n");
	}
}

static void layMines(char Mine[][COL + 2], int start, int endr, int endc, int minesNum)//设置雷区  
{
	srand((unsigned)time(NULL));
	int x, y;
	int n = 0;
	do{
		x = (rand() % endr - start + 1) + start;
		y = (rand() % endc- start + 1) + start;
		if (Mine[x][y] == '0'){
			Mine[x][y] = '1';//雷区设置为字符'1':方便计算周围的雷总数  
			n++;
		}
	} while (n < minesNum);
}

static int aroundMine(char Mine[][COL + 2], int x, int y)
{
	return (Mine[x - 1][y - 1] + Mine[x - 1][y] + Mine[x - 1][y + 1] + \
		Mine[x][y - 1] + Mine[x][y + 1] + \
		Mine[x + 1][y - 1] + Mine[x + 1][y] + Mine[x + 1][y + 1]) - 8 * '0';//周围雷的个数  
}
static void showAround(char View[][COL + 2], char Mine[][COL + 2], int x_a, int y_a, int count)
{
	int x, y;
	for (x = x_a - 1; x <= x_a + 1; x++){
		for (y = y_a - 1; y <= y_a + 1; y++){
			if (x == x_a && y == y_a){
				continue;
			}
			View[x][y] = aroundMine(Mine, x, y) + '0';
			count++;
		}
	}
}

static char judge(char View[][COL + 2], char Mine[][COL + 2], int x, int y, int row, int col, int minesNum)
{
	if (Mine[x][y] == '1'){
		return 'f';//file  
	}
	static int count = 0;
	int x_a, y_a;
	View[x][y] = aroundMine(Mine, x, y) + '0';
	count++;
	int flag = 0;
	//左上:循环  
	x_a = x;
	y_a = y;
	for (; aroundMine(Mine, x_a, y_a) == 0 && x > 0; x_a--){
		flag = 1;
		y_a = y;
		for (; aroundMine(Mine, x_a, y_a) == 0 && y_a > 0; y_a--){
			View[x_a][y_a] = '0';
			count++;
			showAround(View, Mine, x_a, y_a, count);
		}
	}
	if (flag == 0){//若条件成立,说明aroundMine(Mine, x, y)!=0  
		goto judge;
	}
	//左下  
	x_a = x + 1;//此时aroundMine(Mine, x, y)已判断过  
	y_a = y;
	for (; aroundMine(Mine, x_a, y_a) == 0 && x <= row; x_a++){
		y_a = y;
		for (; aroundMine(Mine, x_a, y_a) == 0 && y_a > 0; y_a--){
			View[x_a][y_a] = '0';
			count++;
			showAround(View, Mine, x_a, y_a, count);
		}
	}
	//右上  
	x_a = x;
	y_a = y + 1;
	for (; aroundMine(Mine, x_a, y_a) == 0 && x > 0; x_a--){
		y_a = y + 1;
		for (; aroundMine(Mine, x_a, y_a) == 0 && y_a <= col; y_a++){
			View[x_a][y_a] = '0';
			count++;
			showAround(View, Mine, x_a, y_a, count);
		}
	}
	//右下  
	x_a = x + 1;
	y_a = y + 1;
	for (; aroundMine(Mine, x_a, y_a) == 0 && x < row; x_a++){
		y_a = y + 1;
		for (; aroundMine(Mine, x_a, y_a) == 0 && y_a <= col; y_a++){
			View[x_a][y_a] = '0';
			count++;
			showAround(View, Mine, x_a, y_a, count);
		}
	}
judge:
	if (count == row*col - minesNum){
		return 's';//success  
	}
	return 'n';
}

static int start(char View[][COL + 2], char Mine[][COL + 2], int row, int col, int minesNum)
{
	int x, y;
	char j;
	do{
		printf("please input the position <x y> of your select!\n");
		scanf("%d%d", &x, &y);
		if (x < 1 || x > row || y < 1 || y > col){
			printf("This position out of bounds!\n");
		}
		else if (View[x][y] == '#'){
			j = judge(View, Mine, x, y, row, col, minesNum);
			switch (j){
			case 'f':
				return 1;
			case 's':
				return 0;
			case 'n':
				break;
			}
			break;
		}
		else{
			printf("This location has been determined!\n");
		}
	} while (1);
	return -1;
}

static void endTip(int res)
{
	system("cls");
	switch (res){
	case 1:
		printf("你踩到雷了!\n");
		break;
	case 0:
		printf("扫雷成功!\n");
		break;
	}
}

void playPrimary(int row, int col, int minesNum)//row:9;col:9;minesNum:10
{
	char View[ROW + 2][COL + 2];
	char Mine[ROW + 2][COL + 2];
	memset(View, '#', (ROW + 2)*(COL + 2));
	memset(Mine, '0', (ROW + 2)*(COL + 2));//将布雷的数组初始化为'0'  
	layMines(Mine, 1, row, col, minesNum);//布雷  
	int res;
	do{
		system("cls");
		showView(View, row, col);
		res = start(View, Mine, row, col, minesNum);
		if (res != -1){
			break;
		}
	} while (1);
	endTip(res);
	showView(Mine, row, col);
}

void playIntermediate(int row, int col, int minesNum)
{
	char View[ROW + 2][COL + 2];
	char Mine[ROW + 2][COL + 2];
	memset(View, '#', (ROW + 2)*(COL + 2));
	memset(Mine, '0', (ROW + 2)*(COL + 2));//将布雷的数组初始化为'0'  
	layMines(Mine, 1, row, col, minesNum);//布雷  
	int res;
	do{
		system("cls");
		showView(View, row, col);
		res = start(View, Mine, row, col, minesNum);
		if (res != -1){
			break;
		}
	} while (1);
	endTip(res);
	showView(Mine, row, col);
}

void playAdvanced(int row, int col, int minesNum)
{
	char View[ROW + 2][COL + 2];
	char Mine[ROW + 2][COL + 2];
	memset(View, '#', (ROW + 2)*(COL + 2));
	memset(Mine, '0', (ROW + 2)*(COL + 2));//将布雷的数组初始化为'0'  
	layMines(Mine, 1, row, col, minesNum);//布雷  
	int res;
	do{
		system("cls");
		showView(View, row, col);
		res = start(View, Mine, row, col, minesNum);
		if (res != -1){
			break;
		}
	} while (1);
	endTip(res);
	showView(Mine, row, col);
}

运行结果:
c项目之扫雷
c项目之扫雷
c项目之扫雷
c项目之扫雷
c项目之扫雷c项目之扫雷c项目之扫雷