扫雷游戏C语言模拟实现

头文件game.h


#ifndef __GAME_H__
#define __GAME_H__

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

//9*9棋盘,周围多一圈方便判断周围雷的个数
#define ROWS_SET 9
#define COLS_SET 9

#define ROWS (ROWS_SET+2)
#define COLS (COLS_SET+2)
#define MINE_MAX 10

void init(char a[ROWS][COLS]);
void display(char a[ROWS][COLS]);
void set_main(char a[ROWS][COLS]);
void open_s(char a[ROWS][COLS]);
void game();


#endif //__GAME_H__



源文件

test.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"


enum Option	//用枚举,后面switch方便阅读
{
	EXIT,	//0,有逗号
	PLAY	//1,没逗号
};		//这有个分号

void menu()
{
	printf("**********************************\n");
	printf("******   1.play    0.exit  *******\n");
	printf("**********************************\n");
}

void test()
{
	int input = 0;
	srand((unsigned int)time(NULL));
	while(1)
	{
		menu();
		scanf("%d",&input);
		switch(input)
		{
		case PLAY:
			game();
			break;
		case EXIT:
			exit(1);
			break;	
		default:
			printf("选择错误\n");
			break;
		}
	}
}


int main()
{
	test();
	return 0;
}




game.c

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

//初始化
void init(char a[ROWS][COLS])
{
	//int i = 0;
	//int j = 0;
	//for(i=0;i<ROWS;i++)
	//	for(j=0;j<COLS;j++)
	//		a[i][j]=' ';
	memset(a, ' ',ROWS*COLS*sizeof(a[0][0]));
}

//打印棋盘,显示全部
void display_all(char a[ROWS][COLS])
{
	int i = 0;
	int j = 0;
	
	//输出列号
	printf("   ");
	for(i=1;i<COLS-1;i++)
	{
		if(i<=9)
			printf("%d   ",i);
		else
			printf("%d  ",i);
	}
	printf("\n");


	//11*11的数组只打印中间9*9的棋盘
	//数组下标是1~9,ROWS和COLS都是11
	for(i=1;i<ROWS-1;i++)
	{
		//打印行号
		if(i<=9)
			printf("%d ",i);
		else
			printf("%d",i);
		//打印一行数组
		for(j=1;j<COLS-1;j++)
		{
			if(j<COLS-2)
				printf(" %c |",a[i][j]);
			else 
				printf(" %c\n",a[i][j]);//行末回车
		}
		//一行下面的横线
		if(i!=ROWS-2)
		{
			printf("  ");
			for(j=1;j<COLS-1;j++)
				printf("----");
			if(j==COLS-1)
				printf("\n");
		}
	}
}

//打印棋盘,不显示雷
void display(char a[ROWS][COLS])
{
	int i = 0;
	int j = 0;
	
	//输出列号
	printf("   ");
	for(i=1;i<COLS-1;i++)
	{
		if(i<=9)
			printf("%d   ",i);
		else
			printf("%d  ",i);
	}
	printf("\n");


	//11*11的数组只打印中间9*9的棋盘
	//数组下标是1~9,ROWS和COLS都是11
	for(i=1;i<ROWS-1;i++)
	{
		//打印行号
		if(i<=9)
			printf("%d ",i);
		else
			printf("%d",i);
		//打印一行数组
		for(j=1;j<COLS-1;j++)
		{
			//打印不显示雷的行内字符
			if (j<COLS-2)
			{
				if	(a[i][j]!='x')
				{
					printf(" %c |",a[i][j]);
				}
				else
				{
					printf("   |");
				}
			}
			//打印不显示雷的行末字符和\n
			else 
			{
				if (a[i][j]!='x')
				{
					printf(" %c\n",a[i][j]);//行末回车
				}
				else
				{					
					printf("   |\n");
				}
			}
		}
		//一行下面的横线
		if(i!=ROWS-2)
		{
			printf("  ");
			for(j=1;j<COLS-1;j++)
				printf("----");
			if(j==COLS-1)
				printf("\n");
		}
	}
}

//设置雷
void set_mine(char a[ROWS][COLS])
{
	int count = 0;	
	//已经生成雷的位置不能再放雷
	while (count != MINE_MAX)
	{
		//x,y范围1~9 ROWS和COLS都是11时
		int x = rand()%(ROWS-2)+1;	
		int y = rand()%(COLS-2)+1;
		if (a[x][y] == ' ')
		{
			a[x][y] = 'x';
			count++;
		}
	}
}
	
//判断棋盘是否满了(胜利条件)
int is_full(char a[ROWS][COLS])
{
	int i = 0;
	int j = 0;
	for(i=1;i<ROWS-1;i++)
	{
		for(j=1;j<COLS-1;j++)
		{
			if(a[i][j]==' ')
			{
				return 0;	//没满返回0
			}
		}
	}
	return 1;//棋盘满了返回1
}

//计算某位置周围雷的个数
char judge(char a[ROWS][COLS], int x, int y)
{

	char count = '0';
	
	if (a[x-1][y-1] == 'x')
		count++;
	if (a[x-1][y] == 'x')
		count++;
	if (a[x-1][y+1] == 'x')
		count++;
	if (a[x][y-1] == 'x')
		count++;
	if (a[x][y+1] == 'x')
		count++;
	if (a[x+1][y-1] == 'x')
		count++;
	if (a[x+1][y] == 'x')
		count++;
	if (a[x+1][y+1] == 'x')
		count++;

	return count;
}

//打开雷数为0位置的8方向,如果是空位置,则判断该位置雷的个数
void open(char a[ROWS][COLS], int x, int y)
{
	if (a[x-1][y-1] == ' ')
		a[x-1][y-1] = judge(a,x-1,y-1);

	if (a[x-1][y] == ' ')
		a[x-1][y] = judge(a,x-1,y);

	if (a[x-1][y+1] == ' ')
		a[x-1][y+1] = judge(a,x-1,y+1);

	if (a[x][y-1] == ' ')
		a[x][y-1] = judge(a,x,y-1);

	if (a[x][y+1] == ' ')
		a[x][y+1] = judge(a,x,y+1);

	if (a[x+1][y-1] == ' ')
		a[x+1][y-1] = judge(a,x+1,y-1);

	if (a[x+1][y] == ' ')	
		a[x+1][y] = judge(a,x+1,y);

	if (a[x+1][y+1] == ' ')	
		a[x+1][y+1] = judge(a,x+1,y+1);
		
}

//遍历数组许多遍,如果该次能找到0,则打开0,并把它变成*,然后继续遍历,直到没有相邻的0
void open_s(char a[ROWS][COLS])
{
	int i = 0;
	int j = 0;
	int flag = 0;

	
	do
	{
		flag = 0;
		for (i=1;i<ROWS-1;i++)
		{
			for (j=1;j<COLS-1;j++)
			{
				if (a[i][j] == '0')
				{
					open(a,i,j);	
					a[i][j] = '*';
					flag = 1;
				}
			}
		}
	}while (flag == 1);
	 
}



void game()
{
	char a[ROWS][COLS]={0};
	int x = 0;
	int y = 0;
	int flag = 0;
	init(a);
	display_all(a);

	while(is_full(a) != 1)	//如果棋盘没满则一直扫雷
	{
		printf("输入要排查的坐标:\n");
		scanf("%d %d",&x,&y);
		
		if ((x >= 1) && (x <= ROWS-2) && (y >= 1) && (y <= COLS))
		{
			//保证第一步不是雷(先输入一个位置,然后生成雷,再判断该位置周围有多少雷并显示)
			if(flag == 0)
			{
				a[x][y] = 'p';	//把这个位置随便写个字符,让下面生成雷的时候跳过该位置
				set_mine(a);
				a[x][y] = judge(a,x,y);
				if (a[x][y] == '0')
				{
					open_s(a);//如果该位置是0,则显示与之相连的所有0的位置
				}
				display_all(a);
				flag = 1;
				continue;
			}

			if(a[x][y] == 'x')	
			{
				a[x][y] = '+';
				printf("你被炸死了\n");//如果是雷,则游戏结束
				break;
			}
			else if(a[x][y] != ' ')
			{
				printf("该位置已探索\n\n");
			}
			else
			{
				a[x][y] = judge(a,x,y);	//判断该位置周围雷的个数
				if (a[x][y] == '0')
				{
					open_s(a);//如果该位置是0,则显示与之相连的所有0的位置
				}
				display(a);
			}
		}
		else
		{
			printf("输入的位置超出边界\n\n");
		}
	}
	if (is_full(a) == 1)
	{
		printf("胜利\n");
	}
	display_all(a);
}			



  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值