欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【C语言】经典小游戏--扫雷

程序员文章站 2024-03-18 13:13:46
...

致读者:

扫雷,是一个Windows平台下一个经典的小游戏,今有兴趣玩了几把后,就利用所学二维数组的相关知识模拟实现了一个“扫雷游戏”。由于学识浅薄,界面有点简陋,尽请谅解!

【项目思路】:

1、首先想一想扫雷游戏在Windows平台下是如何实现的。 
2、其次通过观察游戏,我们可以想到需要用两个二维数组来实现扫雷的功能。 
3、游戏刚开始,需要需要显示棋盘,用“*”遮盖雷的坐标,所以要有一个填充棋盘的函数。 
4、通过rand()函数,随机生成雷的坐标,埋雷的函数。 
5、每次扫过后,都要显示新的棋盘,显示棋盘的函数。
6、如果要想第一次踩不到雷的,需要把该坐标下得雷移动到其他不是雷的坐标,并且点击不是雷,还要满足一点击一片的效果。 
7、最后需要一个函数判断是否扫雷成功。

【项目样图】:

【C语言】经典小游戏--扫雷

【C语言】经典小游戏--扫雷

是不是很有意思?当然重中之重的是

要注意需要用二维数组来打印两个棋盘,假如我们要打印10X10的棋盘,那我们的二维数组元素也要为10X10个吗?,不能,因为我们在设计算法时需要统计坐标周围8个方位雷的个数,假如要统计边界坐标周围雷的个数,那么就会有数组越界的问题,那我们就要在10X10的边界多上一圈元素,也就要定义12X12的数组元素,这些元素我们不要打印出来,心里有数就行

【项目代码】:

game.h:

/*********************************************************************************************
*                     项目名称:扫雷游戏                                                       *
*		      编译环境:Vs 2013			                               	      *
*                     创建日期:2018.4.18                                                      *
*                     项目编辑:Mr.Yao                                                         * 
***********************************************************************************************/
 //知识点:
//1.数组
//2.函数
//3.循环
//4.扩展内容: 递归 (内存换取时间)

#ifndef __GAME_H_
#define __GAME_H_

#include <stdio.h>
#include <Windows.h>
#include <time.h>
#include <string.h>
 
enum opp
{
	EXIT,
	PLAY
};

#define EASY 10
#define HARD 30

#define ROW 10
#define COL 10

#define ROWS (ROW+2)
#define COLS (COL+2)

void InitMap(char arr[ROWS][COLS], int row,int col, char set); //创建初始化棋盘
void PrintMap(char arr[ROWS][COLS], int row, int col);	//打印棋盘
void SetMy(char arr[ROWS][COLS], int row, int col, int count); //布雷
void SweepMap(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int row, int cow, int sum);	//扫雷
void MoveLei(char my_map[ROWS][COLS], int x, int y); //若第一次扫到雷,则移动雷的位置
void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y);//统计雷数


#endif

game.c:

#define _CRT_SECURE_NO_WARNINGS 1

#include "game.h"

void InitMap(char arr[ROWS][COLS], int row, int col, char set)
{
	memset(arr, set, col*row*sizeof(arr[0][0]));
}

void PrintMap(char arr[ROWS][COLS], int row, int col)
{
		int i = 0;
		int j = 0;
		printf("   ");
		for (i = 1; i<=row ; i++)
		{
			printf("%3d", i);
		}
		printf("\n");
		for (i = 0; i<=row; i++)
		{
			printf("---");
		}
		printf("\n");
		for (i = 1; i <= row; i++)
		{								 
			printf("%2d|", i);
			for (j = 1; j <= col ; j++)
			{
				printf("%3c", arr[i][j]);
			}
			printf("\n");
		}
	 
}
void SetMy(char arr[ROWS][COLS], int row, int col, int sum)
{
	int count = sum;
	int x = 0;
	int y = 0;
	while (count)
	{
		x = rand() % row + 1;
		y = rand() % col + 1;
		if (arr[x][y] == '0')
		{
			arr[x][y] = '1';
			count--;
		}
	}
}

void SweepMap(char my_map[ROWS][COLS],char player_map[ROWS][COLS], int row, int col, int sum)
{
	int x = 0;
	int y = 0;
	int count = 0;
	int temp = 0;
	int win = 0;
	
	while (win < (row * col - sum))
	{
		printf("请输入你扫雷坐标:>");
		scanf("%d%d", &x, &y);
		temp++;
		if (x >= 1 && x <= row&&y >= 1 && y <= col)
		{

			while ((my_map[x][y] == '1') && (temp == 1))
			{
				//保证玩家第一次不死
				MoveLei(my_map, x, y);
				//对周围的雷数进行遍历
				GetCount(my_map, player_map, x, y);
			}

			if (my_map[x][y] == '1')
			{
				printf("\n恭喜你,壮烈牺牲\n");
				PrintMap(my_map, ROW, COL);
				break;
			}
			else
			{
				GetCount(my_map, player_map, x, y);
				printf("\n");
				win++;
			}
			PrintMap(player_map, ROW, COL);
		}
		else
		{
			printf("坐标输入有误\n");
		}

	}
	if(win == (row * col - sum))
	{
		printf("恭喜你,排完了\n");
	}
	
}

//若输入的坐标无雷,则要遍历周围,统计雷数  
//若周围无雷,则递归遍历,统计周围雷数  
void GetCount(char my_map[ROWS][COLS], char player_map[ROWS][COLS], int x, int y)
{


	if ((my_map[x][y] == '0'))
	{
		int count = 0;

		if (my_map[x - 1][y - 1] == '1')
			count++;

		if (my_map[x - 1][y] == '1')
			count++;

		if (my_map[x - 1][y + 1] == '1')
			count++;

		if (my_map[x][y - 1] == '1')
			count++;

		if (my_map[x][y + 1] == '1')
			count++;
		if (my_map[x + 1][y - 1] == '1')
			count++;

		if (my_map[x + 1][y] == '1')
			count++;

		if (my_map[x + 1][y + 1] == '1')
			count++;

		player_map[x][y] = (count + '0');
	}

	if (player_map[x][y] == '0')
	{
		if (player_map[x - 1][y - 1] == '*')
			GetCount(my_map, player_map, x - 1, y - 1);

		if (player_map[x - 1][y] == '*')
			GetCount(my_map, player_map, x - 1, y);

		if (player_map[x - 1][y + 1] == '*')
			GetCount(my_map, player_map, x - 1, y + 1);

		if (player_map[x][y - 1] == '*')
			GetCount(my_map, player_map, x, y - 1);

		if (player_map[x][y + 1] == '*')
			GetCount(my_map, player_map, x, y + 1);

		if (player_map[x + 1][y - 1] == '*')
			GetCount(my_map, player_map, x + 1, y - 1);

		if (player_map[x + 1][y] == '*')
			GetCount(my_map, player_map, x + 1, y);

		if (player_map[x + 1][y + 1] == '*')
			GetCount(my_map, player_map, x + 1, y + 1);
	}
}

//为提高游戏体验,设置玩家第一次无论如何都不会被炸死  
void MoveLei(char my_map[ROWS][COLS], int x, int y)
{
	int ret = 1;
	do
	{
		my_map[x][y] = '0';
		while (ret)
		{
			x = rand() % ROW + 1;
			y = rand() % COL + 1;
			if (my_map[x][y] == '0')
			{
				my_map[x][y] = '1';
			}
			ret--;
		}
	} while (ret);
}
 

test.c:

#define _CRT_SECURE_NO_WARNINGS 1


#include "game.h"

void GotoXY(int x, int y) //设定输出位置
{
	COORD c;
	c.X = x - 1;
	c.Y = y - 1;
	SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), c);
}

void meau()
{
	GotoXY(10, 5); printf("开始游戏\n         Let's Go!");
	Sleep(1500);
	system("cls");
	printf("****    《扫雷》    ****\n");
	printf("************************\n");
	printf("*******  1.play  *******\n");
	printf("*******  0.exit  *******\n");
	printf("************************\n");
}

void game()
{
	int input = 0;
	int sum = 0;
	char my_map[ROWS][COLS];
	char player_map[ROWS][COLS];

	InitMap(my_map,ROWS,COLS,'0');
	InitMap(player_map, ROWS, COLS, '*');

	printf("**** 1.Easy 0.Hard *****\n");
	scanf("%d", &input);
	switch (input)
	{
		case PLAY:
			sum = EASY;
			break;
		case EXIT:
			sum = HARD;
			break;
		default:
			printf("输入有误\n");
			break;
	}
	printf("\n这个棋盘有%d个雷。\n", sum);
	SetMy(my_map,ROW,COL,sum);

	PrintMap(player_map, ROW, COL);
	//PrintMap(my_map, ROW, COL);
	SweepMap(my_map,player_map ,ROW, COL, sum);
	system("pause");
}



void test()
{	 
	int input = 0;
	do
	{
		meau();
		printf("请选择:>");
		scanf("%d", &input);
		switch (input)
		{
		case PLAY:
			game();
			break;
		case EXIT:
			break;
		default:
			printf("输出有误\n");
		}

	} while (input);
}

int main()
{
	srand((unsigned)time(NULL));
	test();
	system("pause");
	return 0;
}