c语言游戏扫雷——二维数组运用解析
二维数组简单应用游戏—扫雷
想必大家都很熟悉扫雷这个游戏其规则简单如下:
- 在一个雷盘中有定量的雷需要玩家进行排除,不限时间。
- 玩家踩到雷,游戏结束。
- 玩家输入坐标不是雷,便将展开坐标周围情况。
- 玩家第一步走将保证不被炸死。
思路:
- 创建两个雷盘,一个是设计者雷盘为了实现逻辑,一个是玩家雷盘展示给玩家结果,
- 雷盘的大小9×9的话,应该初始化11×11的这是考虑到边缘的情况,并且打印雷盘。
- 布雷,第一步不会被炸死,还要展开显示坐标周围雷的数量。
- 判断输赢,运用多文件结构game.c,test.h先声明头文件game.h。
先画出游戏的流程图来提供一个清晰思路,往后按流程写代码就不容易混乱。
注意:由于本程序用的是多文件结构所以一定要声名头文件game.h
头文件game.h
#ifndef _GAME_H_
#define _GAME_H_
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define EASY_COUNT 10//雷的个数
#define ROWS 11//实际雷盘大小
#define COLS 11
#define ROW 9//显示雷盘大小
#define COL 9
void init(char mine[ROWS][COLS], int rows, int cols, int set);//初始化
void display(char mine[ROWS][COLS], int row, int col);//打印数组
void setmine(char mine[ROWS][COLS], int row, int col);//布雷
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS] ,int row, int col);//排雷且判输赢
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y);//展开坐标周围
void safemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col);//保证第一步不被炸死
#endif
游戏测试模块test.c
void test()//游戏测试运行
{
char mine[ROWS][COLS] = { 0 };//存放雷的信息
char show[ROWS][COLS] = { 0 };//存放排查出雷的信息
int input = 0;
do
{
printf("请选择:>");
scanf("%d", &input);
switch (input)
{
case 1:
init(mine, ROWS, COLS, '0');
init(show, ROWS, COLS, '*');
setmine(mine, ROW, COL);
display(show, ROW, COL);
safemine(mine, show, ROW, COL);
findmine(mine, show,ROW, COL);
break;
case 0:
printf("推出游戏!\n");
break;
default:
printf("输入错误,请从新选择:>\n");
break;
}
} while (input);
}
游戏运行模块game.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
void init(char mine[ROWS][COLS], int rows, int cols, char set)//初始化
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
mine[i][j] = set;
}
}
}
void display(char mine[ROWS][COLS], int row, int col)//打印数组
{
int i = 0;
int j = 0;
printf("------------------------------\n");
for (i = 0; i <= col; i++)
{
printf("%d ", i);
}
printf("\n");
for (i = 1; i <=row; i++)
{
printf("%d ", i);
for (j = 1; j <=col; j++)
{
printf("%c ", mine[i][j]);
}
printf("\n");
}
printf("------------------------------\n");
}
void setmine(char mine[ROWS][COLS], int row, int col) //布雷
{
int x = 0;
int y = 0;
int count = EASY_COUNT;
while (count)
{
x = rand() % row+1 ;
y = rand() % col+1 ;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
count--;
}
}
}
int CountMine(char mine[ROWS][COLS], int x, int y)//计算x,y周围的雷数量
{
int count = 0;
if (mine[x - 1][y - 1] == '1') //1表示该位置有雷
{
count++;
}
if (mine[x - 1][y] == '1')
{
count++;
}
if (mine[x - 1][y + 1] == '1')
{
count++;
}
if (mine[x][y - 1] == '1')
{
count++;
}
if (mine[x][y + 1] == '1')
{
count++;
}
if (mine[x + 1][y - 1] == '1')
{
count++;
}
if (mine[x + 1][y] == '1')
{
count++;
}
if (mine[x + 1][y + 1] == '1')
{
count++;
}
return count;
}
void OpenMine(char mine[ROWS][COLS], char show[ROWS][COLS], int x, int y)//计算x,y坐标周围坐标的雷数
{
if (mine[x - 1][y - 1] == '0') //如果该位置没有雷,则计算出其周围8个区域雷的个数并标记在玩家棋盘对应位置
{
show[x - 1][y - 1] = CountMine(mine, x - 1, y - 1) + '0'; //CountMine()函数返回的是数字,而PlayerMine数组存的是字符,所以将数字加上字符零可得数字字符
}
if (mine[x - 1][y] == '0')
{
show[x - 1][y] = CountMine(mine, x - 1, y) + '0';
}
if (mine[x - 1][y + 1] == '0')
{
show[x - 1][y + 1] = CountMine(mine, x - 1, y + 1) + '0';
}
if (mine[x][y - 1] == '0')
{
show[x][y - 1] = CountMine(mine, x, y - 1) + '0';
}
if (mine[x][y + 1] == '0')
{
show[x][y + 1] = CountMine(mine, x, y + 1) + '0';
}
if (mine[x + 1][y - 1] == '0')
{
show[x + 1][y - 1] = CountMine(mine, x + 1, y - 1) + '0';
}
if (mine[x + 1][y] == '0')
{
show[x + 1][y] = CountMine(mine, x + 1, y) + '0';
}
if (mine[x + 1][y + 1] == '0')
{
show[x + 1][y + 1] = CountMine(mine, x + 1, y + 1) + '0';
}
}
void findmine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//扫雷且判输赢
{
int x = 0;
int y = 0;
int count = 0;
while (1)
{
printf("请输入排查坐标:>");
scanf("%d %d", &x, &y);
if (x >= 1 && x <= row&&y >= 1 && y <= col)
{
if (mine[x][y] == '1')
{
printf("抱歉!你踩雷了\n");
display(mine, row, col);
break;
}
else
{
int ret = CountMine(mine, x, y);//计算x,y周围雷数
show[x][y] = ret+'0';
OpenMine(mine,show,x,y);
display(show, row, col);
count++;
if ((ROW*COL) - EASY_COUNT == count)
{
printf("你赢了!\n");
display(mine, row, col);
}
}
}
else
{
printf("输入错误,坐标非法!");
}
}
}
void safemine(char mine[ROWS][COLS], char show[ROWS][COLS], int row, int col)//保证第一步不被炸死
{
int x = 0;
int y = 0;
int ret = 1;
int ch = 0;
printf("请输入要排查的坐标:>");
scanf("%d%d", &x, &y);
if (mine[x][y] == '1')//如果是雷,去除这个雷从新布一个雷
{
mine[x][y] = '0';
ch = CountMine(mine, x, y);
show[x][y] = ch + '0';
while (ret)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (mine[x][y] == '0')
{
mine[x][y] = '1';
}
ret--;
}
}
display(show, row, col);
}
游戏主函数模块main( )
#define _CRT_SECURE_NO_WARNINGS 1
#include"game.h"
int main()
{
srand((unsigned int)time(NULL));//随机数发生器
menu();
test();
//system("pause");
return 0;
}
总结:
- 设计是要考虑到用两个雷盘也就是两个二维数组且作用也不相同;
- 多文件结构注意头文件的声名。
- 熟练运用#define来定值,是游戏难度变化简单容易。
- 要理清思维逻辑,切忌提手就敲代码容易卡壳。