扫雷游戏:格子出现的数字找出所有非雷格子,同时避免踩雷,踩到一个雷即全盘皆输。
一.要求
1.第一次扫雷的时候,要确保扫不到雷子。
2.扫到雷的时候,游戏退出。
3.玩家看到的是10*10的背景大小,雷子的个数是20。
二.整体思路
1.设两个表,一张雷表,一张玩家表,大小都为12X12。但显示的时候都是显示中间的10X10部分。
设置大小为12X12的原因是,为了方便计算显示的10X10边框上的附近有雷个数。
'1’表示该位置是雷,'0’表示该位置没雷。
12X12雷表 边框都为’0’。
下图为简略的雷表(蓝色为显示部分):
下图为相应玩家表(蓝色是显示部分):
在图中黄色的是玩家排雷的位置,在玩家表中显示周围雷的个数。
2.埋雷
使用随机数生成雷的座标x,y;总共要生成雷的个数为20个。
3.玩家扫雷
玩家输入座标进行扫雷。
要避免玩家第一次扫到雷的情况发生,我们可以这么做:雷埋完毕,找到一个非雷的座标保存起来(n_x , n_y),如果玩家第一次扫到雷了,座标是(x,y),那么交换座标(n_x , n_y)和座标(x,y)里存的内容。雷会被交换掉,而且也不会改变雷的个数。
4.玩家表上显示该位置附近雷的个数
5.显示玩家表
6.如果玩家输了,要提醒玩家,并且要显示出相应雷的表
三.实现代码
头文件 mine.h
函数的初始化和宏定义。
#ifndef __MINE__
#define __MINE__
#include<stdio.h>
#include<windows.h>
#include<string.h>//要用到给数组初始化的memset函数
#include<time.h>//要用到随机数
#pragma warning (disable:4996)
#define ROW 12
#define COL 12
#define MINES 20
//埋雷
void Set_mine(char board[][COL], int row, int col, int *x_p, int *y_p);
//打印表
void Show_Board(char board[][COL], int row, int col);
//该位置附近雷的个数
int GetCount(char board[][COL], int x, int y);
#endif
主函数 main.c
实现菜单的打印,选择开始游戏和退出游戏。
#include"mine.h"
void menu()//打印菜单
{
printf("##########################\n");
printf("######欢迎来到扫雷游戏#####\n");
printf("##########################\n");
printf("####1.play#####2.exit#####\n");
printf("##########################\n");
printf("请选择>>> ");
}
int main()
{
int quit = 0;
while (!quit)
{
menu(); //打印菜单
int select = 0;
scanf("%d", &select);
switch (select)
{
case 1: //开始游戏
game();
break;
case 2: //退出游戏
quit = 1;
break;
default: //输入有误
printf("请重新选择!\n");
break;
}
}
printf("欢迎下次来玩,再见。\n");
system("pause");
return;
}
子函数mine.c
实现游戏埋雷功能,打印功能,计算座标附近雷的个数的功能
#include"mine.h"
//埋雷
void Set_mine(char board[][COL],int row, int col,int *x_p,int *y_p)
{
int count = MINES;
while (count>0)
{
int x = rand()%10+1;
int y = rand()%10+1;
if (board[x][y] == '0')
{
count--;
board[x][y] ='1';
}
int i = 1;
for (; i <= 10; i++)
{
int j = 1;
for (; j <= 10; j++)
{
if (board[i][j] == '0')
{
*x_p = i;
*x_p = j;
}
break;
}
}
}
}
//打印表
void Show_Board(char board[][COL], int row, int col)
{
int i = 1;
printf(" ");
for (; i <=10; i++)
{
printf(" %d ", i);
}
printf("\n");
for (i = 1; i <=10; i++)
{
printf("-----");
}
printf("---\n");
for (i = 1; i <=10; i++)
{
printf(" %d | ", i);
int j = 1;
for (; j <=10; j++)
{
printf(" %c | ",board[i][j]);
}
printf("\n");
int k;
for (k = 1; k <=10; k++)
{
printf("-----");
}
printf("---\n");
}
}
//座标<x,y>附近雷的个数
int GetCount(char board[][COL], int x,int y)
{
int num = (board[x - 1][y - 1] + board[x - 1][y] + board[x - 1][y + 1] + \
board[x][y - 1] + board[x][y + 1] + board[x + 1][y - 1] + \
board[x + 1][y] + board[x + 1][y + 1])-('0'*8);
return num;
}
void game()
{
srand((unsigned long)time(NULL));//种随机数种子
char mine_board[ROW][COL];
char show_board[ROW][COL];
memset(mine_board, '0', sizeof(mine_board));//初始化雷表为'0'
memset(show_board, '*', sizeof(show_board));//初始化玩家表为'*'
int no_x;//雷埋完,没有雷的座标。若玩家第一次扫到雷,此座标与之交换
int no_y;
Set_mine(mine_board, ROW, COL,&no_x,&no_y);
int num = 100 - MINES;
do{
system("cls");//清屏
Show_Board(show_board, ROW, COL);//打印玩家表
printf("请输入<x,y> :");
int x = 0, y = 0;
scanf("%d %d", &x, &y);
if (x<1 || x>10 || y<1 || y>10)//判断玩家坐标输入是否合法
{
printf("座标有误!请重新输入!\n");
continue;
}
if (show_board[x][y] != '*')//判断玩家输入座标是否已被排除
{
printf("该位置已被排除,请重新输入!\n");
continue;
}
if (mine_board[x][y] == '1')
{
if (num == 80)//第一次扫到雷的情况
{
mine_board[no_x][no_y] = '1';
mine_board[x][y] = '0';
}
else{
printf("boom!\n");
printf("game over!\n");
Show_Board(mine_board, ROW, COL);
printf(" 不过瘾? 要不要再来一把?\n");
break;
}
}
int count = GetCount(mine_board, x, y);//在此座标上附近雷的个数
show_board[x][y] = count + '0';//注意:显示的是字符型
num--;
} while (num>0);
}
若有不足,请提醒,感谢!