一、游戏设计要求
1.输入坐标,显示周围雷的数目
2.附近没有雷的位置全部展开
3.玩家下第一步棋时,如果踩雷了,判定玩家不死,重新分布雷
二、代码功能
1.菜单界面
选择1开始游戏,0退出游戏
void menu()
{
printf("***************************\n");
printf("*********1.开始游戏********\n");
printf("*********0.退出游戏********\n");
printf("***************************\n");
}
2.创建2个数组? 一个数组用于设置雷,另外一个数组存放排雷过程中雷的数目
char board[LINES][ROWS] = { 0 }; // 存放雷
char show[LINES][ROWS] = { 0 };//存放之后雷的个数 为了方便排查最外围的雷 ,将方格扩大一圈
#define LINE 9
#define ROW 9
#define LINES 11
#define ROWS 11
?使用宏定义设定数组大小,方便更改
因为在排查雷的时候,需要计数周围一共8个坐标的雷的数目,在9*9的方格中,例如左上角坐标在访问时会出界,所以将9*9的数组扩大一圈,改为11*11数组,但是雷的信息仍储存于9*9格子之中。
3.两个数组的初始化?
board数组用于储存以后的雷,全部初始化为‘0’
show数组?用于储存排查出来的信息,初始化为‘*’
使用char set传入‘0‘ 和’*’
void Initboard(char board[LINES][ROWS], int lines, int rows, char set)
{
int i = 0; int j = 0;
for (i = 0; i < lines; i++)
{
for (j = 0; j < rows; j++)
{
board[i][j] = set;
}
}
}
4.打印数组
为了方便输入坐标,打印了行列?
void Displayboard(char board[LINES][ROWS], int line, int row)
{
int i = 0; int j = 0;
for (i = 1; i <= line; i++)
{
if (i == 1)
{
for (j = 0; j <= row; j++)
printf("%d ", j);
printf("\n");
}
printf("%d ", i);
for (j = 1; j <= row; j++)
{
printf("%c ", board[i][j]);
}
printf("\n");
}
}
5.开始设置雷
?使用宏定义设置雷的数目
要求雷的坐标不能越界,不能重复
因为打印了行列,数组坐标从1开始
void Setboard(char board[LINES][ROWS], int line, int row)
{//9*9的格子 范围 1~9
srand((unsigned int)time(NULL));
int count = COUNT;
while (count)
{
int x = rand() % line + 1;
int y = rand() % row + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
6.排查雷:Findboard()实现总体控制
int Time = 1;
void Findboard(char board[LINES][ROWS], char show[LINES][ROWS], int line, int row)
{
int x; int y;
int count = Countset(show, LINES, ROW);//show数组中没有展开的坐标总个数
while (count>COUNT)//循环条件 :show数组中没有被展开的个数比雷的总数要多
{
printf("游戏共有%d个雷\n", COUNT);
printf("请输入坐标,横坐标范围1~%d,纵坐标范围1~%d\n",line,row);
scanf("%d%d", &x, &y);
if (x >= 1 && x <= line && y >= 1 && y <= row) //坐标不能越界
{
if (show[x][y] != '*')// 输入已经展开了的坐标,重新进入循环
{
printf("该位置已经排过了,请重新输入坐标!\n");
}
else if (board[x][y] == '1')//输入的坐标是雷
{
if (Time == 1)//第一步下棋中雷,重新分布雷
{
printf("刚开始游戏踩到雷,雷已经重新分布\n");
Safe(board, LINES, ROWS, x, y);
Findboard(board, show, line, row);
}
else //输入的坐标是雷,且不是第一步下棋,死亡
{
Sleep(100);
system("cls");
printf("踩雷了\n");
printf("雷的分布情况如图:\n");
Displayboard(board, LINE, ROW);
break;// 中雷了跳出循环
}
}
else //输入的坐标不是雷,那么这局游戏不符合重新分布雷的要求,Time值改为0
{
Time = 0;
int s = Countboard(board, LINES, ROWS, x, y);//记录一周雷的个数
show[x][y] = s+'0';// 使用ASCII码值的特点,1+’0'='1',使得show数组可以存放雷的数目
Openboard(board ,show, LINES, ROWS, x, y);//展开坐标周围没有雷的地方
count = Countset(show, LINES, ROW);//记录剩余show数组没有展开的坐标个数,改变循环条件的比较值
Sleep(100);
system("cls");
Displayboard(show, LINE, ROW);//打印show数组
}
}
else//坐标越界,重新输入
printf("坐标非法,请重新输入\n");
}
if (count == COUNT)//当show数组没有展开的坐标等于雷的总数时,游戏胜利
printf("排雷成功\n");
}
?Setboard()函数在9*9的数组内部生成雷,要求个数足够且位置不重复
void Setboard(char board[LINES][ROWS], int line, int row)
{//9*9的格子 范围 1~9
srand((unsigned int)time(NULL));
int count = COUNT;
while (count)
{
int x = rand() % line + 1;
int y = rand() % row + 1;
if (board[x][y] != '1')
{
board[x][y] = '1';
count--;
}
}
}
Safe()函数在第一次输入坐标就中雷的情况下,将此坐标的雷去除,重新生成另外位置的雷,要求 :雷的位置不能重复?
void Safe(char board[LINES][ROWS], int line, int row, int x, int y) //避免第一次就踩到了雷
{
board[x][y] = '0';
int b = 1;
while (b)
{
int x = rand() % line + 1;
int y = rand() % row + 1;
if (board[x][y] == '0')
{
board[x][y] = '1';
b = 0;
}
}
Countboard():统计坐标周围的雷的数目
字符-字符得到数字
int Countboard(char board[LINES][ROWS], int lines, int rows,int x,int y)
{
return (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] - 8 * '0');
}
?Openboard():展开周围没有雷的位置,递归 要求:1.坐标不是雷
? ? ? ? ? ? 2.坐标周围没有雷
? ? ? ? ? ? ?3.为了避免重复扫描一圈中的坐标,在没有被展开的坐标处查找
void Openboard(char board[LINES][ROWS], char show[LINES][ROWS], int lines, int rows, int x, int y)
{
int ret = Countboard(board, LINES, ROWS, x, y);//ret存放周围雷的数目
if (ret == 0)//如果周围没有雷,判断周围没有展开的坐标是否有雷
{
show[x][y] = '0';//存放show
if (x - 1 >= 1 && x - 1 <= LINE && y - 1 >= 1 && y - 1 <= ROW && show[x - 1][y - 1] == '*')//坐标范围
Openboard(board, show, LINES, ROWS, x - 1, y - 1);
if (x - 1 >= 1 && x - 1 <= LINE && y + 1 >= 1 && y + 1 <= ROW && show[x - 1][y + 1] == '*')
Openboard(board, show, LINES, ROWS, x - 1, y + 1);
if (x - 1 >= 1 && x - 1 <= LINE && y >= 1 && y <= ROW && show[x - 1][y] == '*')
Openboard(board, show, LINES, ROWS, x - 1, y);
if (x >= 1 && x <= LINE && y - 1 >= 1 && y - 1 <= ROW && show[x][y - 1] == '*')
Openboard(board, show, LINES, ROWS, x, y - 1);
if (x >= 1 && x <= LINE && y + 1 >= 1 && y + 1 <= ROW && show[x][y + 1] == '*')
Openboard(board, show, LINES, ROWS, x, y + 1);
if (x + 1 >= 1 && x + 1 <= LINE && y - 1 >= 1 && y - 1 <= ROW && show[x + 1][y - 1] == '*')
Openboard(board, show, LINES, ROWS, x + 1, y - 1);
if (x + 1 >= 1 && x + 1 <= LINE && y >= 1 && y <= ROW && show[x + 1][y] == '*')
Openboard(board, show, LINES, ROWS, x + 1, y);
if (x + 1 >= 1 && x + 1 <= LINE && y + 1 >= 1 && y + 1 <= ROW && show[x + 1][y + 1] == '*')
Openboard(board, show, LINES, ROWS, x + 1, y + 1);
}
else//当坐标周围有雷时
show[x][y] = ret + '0';
}
?Countset():统计所有没有展开位置的坐标数目
int Countset(char show[LINES][ROWS], int lines, int rows)
{
int i, j;
int count = 0;
for (i = 1; i <= LINE; i++)
{
for (j = 1; j <= ROW; j++)
{
if (show[i][j] == '*')
count++;
}
}
return count;
}
三、代码
我们将以上函数的定义放在 game.c 文件中
game.h声明
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<windows.h>
#define LINE 9
#define ROW 9
#define LINES 11
#define ROWS 11
#define COUNT 10
void Initboard(char board[LINES][ROWS], int lines, int rows,char set);
void Displayboard(char board[LINES][ROWS], int line, int row);
void Setboard(char board[LINES][ROWS], int line, int row);
void Findboard(char board[LINES][ROWS], char show[LINES][ROWS], int line, int row);
int Countboard(char show[LINES][ROWS], int lines, int rows, int x, int y);
void Openboard(char board[LINES][ROWS], char show[LINES][ROWS], int lines, int rows, int x, int y);
void Safe(char board[LINES][ROWS], int lines, int rows,int x,int y);
int Countset(char show[LINES][ROWS], int lines, int rows);
将game.c,? game.h 放入test.c实现
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
void game()
{
char board[LINES][ROWS] = { 0 }; // 存放雷
char show[LINES][ROWS] = { 0 };//存放之后雷的个数 为了方便排查最外围的雷 ,将方格扩大一圈
Initboard(board, LINES, ROWS, '0');
Initboard(show, LINES, ROWS, '*');
printf("\n");
Displayboard(show, LINE, ROW);
Setboard(board, LINE, ROW);// 在中间的9*9格子之中生成雷
Findboard(board,show ,LINE, ROW);//坐标附近雷的数目传入show数组
}
int main()
{
int ch = 0;
do
{
menu();
scanf("%d", &ch);
switch (ch)
{
case 1:printf("开始游戏\n"); system("cls"); game(); break;
case 0:printf("退出游戏\n"); break;
default:printf("输入错误,请重新输入\n"); break;
}
} while (ch);
return 0;
}
|