我们都玩过一款名为扫雷的游戏,而利用我们所学的C语言也可以模拟实现扫雷的功能。通过对扫雷的了解,明白其原理。首先在一块区域上,选取一个坐标点,如果该坐标点是雷点,游戏结束;如果是安全区,而且周围都为安全区,则会进行扩展,雷区的附近会有坐标显示雷存在的颗数。
根据C语言所学,大致思路是:系统布雷,玩家选取坐标,是安全区,游戏继续,扩展或者显示周围雷数;如果雷区,则游戏结束。用随机数的生成,在一个10X10的二维数组布雷,雷数为10颗,用递归的方法对安全区进行扩展和对周围雷数的探测。
我们将程序分为3个模块,首先为头文件:函数的声明,宏的定义,头文件的引入;然后是测试文件:主函数部分;最后是游戏主要程序的编写。
1.头文件(game.h)
#ifndef __GAME_H__
#define __GAME_H__
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include<string.h>
extern void meun();
extern void Map(char a[][10]);
extern char Discorn(char a[][10],int x,int y);
extern void Extend(char a[][10], char b[][10],int x,int y);
extern void Judgement(char a[][10]);
extern void Set();
extern void game();
#endif //__GAME_H__
2.测试程序(test.c)
#include"game.h"
int main()
{
srand((unsigned)time(NULL)); //随机数种子产生
int a;
do
{
meun();
scanf_s("%d", &a);
switch (a)
{
case 1:
game();
break;
case 0:
break;
default:
printf("输入错误\n11");
system("cls");
break;
}
} while (a);
return 0;
}
3.主要游戏程序部分(game.h)
//游戏程序
void game()
{
printf("--------------------------------------------------------------------\n");
Set();
char mine[10][10];
memset(mine, ' ', sizeof(mine)); //对雷区进行初始化
int i = 0;
while (i < 10)
{
int x = rand() % 10 ; //随机数的接受(产生0-9的随机数)
int y = rand() % 10 ;
if (mine[y][x] == ' ') //布置地雷(不能重复)
{
mine[y][x] = 'X';
i++;
}
}
//Map(mine); //雷区的显示
Judgement(mine); //输赢的判断
}
//游戏界面
void meun()
{
printf("*************************************************************\n");
printf("************ Welcome to Minesweeper **************\n");
printf("*************************************************************\n");
printf("************ - 1. Play - **************\n");
printf("************ - 0. Exit - **************\n");
printf("*************************************************************\n");
}
//游戏地图的初始化
void Set()
{
char set[10][10];
memset(set, '*', sizeof(set));
Map(set);
}
//打印地图
void Map(char m[10][10])
{
int i, j;
printf("\n\n");
for (j = 1; j < 11; j++)
{
if (j == 1)
printf(" ");
printf("%3d", j);
}
printf("\n");
for (i = 0; i < 10; i++)
{
printf("%2d", i + 1);
for (j = 0; j < 10; j++)
{
printf("%3c", m[i][j]);
}
printf("\n");
}
printf("\n");
printf("\n--------------------------------------------------------------------\n");
}
//对安全区的扩展
void Extend(char a[10][10], char set[10][10], int x, int y)
{
if ((a[y - 1][x - 1] != 'X') && (a[y - 1][x] != 'X') &&
(a[y - 1][x + 1] != 'X') && (a[y][x + 1] != 'X') &&
(a[y][x - 1] != 'X') && (a[y + 1][x] != 'X') &&
(a[y + 1][x + 1] != 'X') && (a[y + 1][x - 1] != 'X'))
{
if ((x - 1 > -1) && ((y - 1) > -1) && (a[y - 1][x - 1] ==' ') && (set[y - 1][x - 1] != ' '))
{
set[y - 1][x - 1] = ' ';
char ret1 = Discorn(a, x - 1, y - 1);
if (ret1 == '0')
ret1 = ' ';
else
set[y - 1][x - 1] = ret1;
Extend(a, set, x - 1, y - 1);
}
if (((x - 1) > -1) && (y < 10) && (y>-1) && (a[y][x - 1] == ' ') && (set[y][x - 1] != ' '))
{
set[y][x - 1] = ' ';
char ret2 = Discorn(a, x - 1, y);
if (ret2 == '0')
ret2 = ' ';
else
set[y][x - 1] = ret2;
Extend(a, set, x - 1, y);
}
if ((x - 1 >-1) && (y + 1< 10) && (a[y + 1][x - 1] == ' ') && (set[y + 1][x - 1] != ' '))
{
set[y + 1][x - 1] = ' ';
char ret3 = Discorn(a, x - 1, y + 1);
if (ret3 == '0')
ret3 = ' ';
else
set[y + 1][x - 1] = ret3;
Extend(a, set, x - 1, y + 1);
}
if ((x>-1) && (x < 10) && (y + 1 < 10) && (a[y + 1][x] == ' ') && (set[y + 1][x] != ' '))
{
set[y + 1][x] = ' ';
char ret4 = Discorn(a, x, y + 1);
if (ret4 == '0')
ret4 = ' ';
else
set[y + 1][x] = ret4;
Extend(a, set, x, y + 1);
}
if ((x>-1) && (x < 10) && (y - 1>-1) && (a[y - 1][x] == ' ') && (set[y - 1][x] != ' '))
{
set[y - 1][x] = ' ';
char ret5 = Discorn(a, x, y - 1);
if (ret5 == '0')
ret5 = ' ';
else
set[y - 1][x] = ret5;
Extend(a, set, x, y - 1);
}
if ((x + 1 < 10) && (y - 1 >-1) && (a[y - 1][x + 1] == ' ') && (set[y - 1][x + 1] != ' '))
{
set[y - 1][x + 1] = ' ';
char ret6 = Discorn(a, x + 1, y - 1);
if (ret6 == '0')
ret6 = ' ';
else
set[y - 1][x + 1] = ret6;
Extend(a, set, x + 1, y - 1);
}
if ((x + 1 < 10) && (y<10) && (y>-1) && (a[y][x + 1] == ' ') && (set[y][x + 1] != ' '))
{
set[y][x + 1] = ' ';
char ret7 = Discorn(a, x + 1, y);
if (ret7 == '0')
ret7 = ' ';
else
set[y][x + 1] = ret7;
Extend(a, set, x + 1, y);
}
if ((x + 1 < 10) && ((y + 1) < 10) && (a[y + 1][x + 1] == ' ') && (set[y + 1][x + 1]))
{
set[y + 1][x + 1] = ' ';
char ret8 = Discorn(a, x + 1, y + 1);
if (ret8 == '0')
ret8 = ' ';
else
set[y + 1][x + 1] = ret8;
Extend(a, set, x + 1, y + 1);
}
}
}
//对周围雷数进行统计
char Discorn(char a[10][10], int x, int y)
{
char count = '0';
if (((x - 1) > -1) && ((y - 1) > -1) && (a[y - 1][x - 1] == 'X'))
count++;
if (((x - 1) > -1) && (y < 10) && (y>-1) && (a[y][x - 1] == 'X'))
count++;
if (((x - 1) > -1) && ((y + 1) < 10) && (a[y + 1][x - 1] == 'X'))
count++;
if ((x>-1) && (x < 10) && ((y + 1) < 10) && (a[y + 1][x] == 'X'))
count++;
if ((x>-1) && (x < 10) && ((y - 1)>-1) && (a[y - 1][x] == 'X'))
count++;
if (((x + 1) < 10) && ((y - 1) >-1) && (a[y - 1][x + 1] == 'X'))
count++;
if (((x + 1) < 10) && (y<10) && (y>-1) && (a[y][x + 1] == 'X'))
count++;
if (((x + 1) < 10) && ((y + 1) < 10) && (a[y + 1][x + 1] == 'X'))
count++;
return count;
}
//判断输赢
void Judgement(char a[10][10])
{
int x, y;
char set[10][10];
memset(set, '*', sizeof(set));
while (1)
{
int count = 0;
printf("input coordinate:");
scanf("%d %d", &x, &y);
system("cls"); //对屏幕的刷新
if (x > 10 || y > 10 || x < 0 || y < 0)
{
printf("Please again!!!\n");
continue;
}
x = x - 1;
y = y - 1;
if (a[y][x] == 'X')
{
Map(a);
printf("you were dead!!!\n");
break;
}
else
{
char ret = Discorn(a, x, y);
if (ret == '0')
ret = ' ';
set[y][x] = ret;
Extend(a, set, x, y);
Map(set);
for (int i = 0; i < 10; i++)
{
for (int j = 0; j < 10; j++)
if (set[i][j] == '*')
count++;
}
}
if (count == 10)
{
printf("You win this game!!!\n");
break;
}
}
}
图片展示
游戏的扩展部分需要用到函数的递归,本程序的精华所在,通过递归和限制条件的设置,对安全区进行一步步扩展,递归的引入很好的结局了这一问题。
程序还可以进行扩展,对游戏雷数的设置,难度的设置等,新的功能及优化等着进一步的完善。
Author:yk