【C语言】经典小游戏--扫雷
程序员文章站
2024-03-18 13:13:46
...
致读者:
扫雷,是一个Windows平台下一个经典的小游戏,今有兴趣玩了几把后,就利用所学二维数组的相关知识模拟实现了一个“扫雷游戏”。由于学识浅薄,界面有点简陋,尽请谅解!
【项目思路】:
1、首先想一想扫雷游戏在Windows平台下是如何实现的。
2、其次通过观察游戏,我们可以想到需要用两个二维数组来实现扫雷的功能。
3、游戏刚开始,需要需要显示棋盘,用“*”遮盖雷的坐标,所以要有一个填充棋盘的函数。
4、通过rand()函数,随机生成雷的坐标,埋雷的函数。
5、每次扫过后,都要显示新的棋盘,显示棋盘的函数。
6、如果要想第一次踩不到雷的,需要把该坐标下得雷移动到其他不是雷的坐标,并且点击不是雷,还要满足一点击一片的效果。
7、最后需要一个函数判断是否扫雷成功。
【项目样图】:
是不是很有意思?当然重中之重的是:
要注意需要用二维数组来打印两个棋盘,假如我们要打印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;
}