五一假期我竟然做出来了这个程序———— 扫雷 (功能完全版)
Posted 赏一杯茶:
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了五一假期我竟然做出来了这个程序———— 扫雷 (功能完全版)相关的知识,希望对你有一定的参考价值。
1. 扫雷整体思路分析
- 扫雷算是一个代码量比较大的程序,需要用到大量我们自定义的函数,故需要不同的文件去声明与实现函数。
- 设置两个二维数组,一个用来储存雷的信息,另一个打印出游戏的信息。
- 各种函数来实现功能。
文件 | 功能 |
---|---|
test.c | 程序main函数的运行文件 |
game.c | 实现函数的功能 |
game.h | 声明函数和引用各种头文件 |
2. 初始化数据与雷的放置
- 数组stormir存放雷
- 数组showmir展示游戏信息
- 根据游戏功能,后面排查雷时需要遍历其周围的八个格子,故将数组大小扩大到行:11、列:11。(实际操作数组还是行9列9)
- 用rand()函数随机布置雷
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
char stormir[ROWS][COLS] = { 0 };
char showmir[ROWS][COLS] = { 0 };
initboard(stormir,ROWS,COLS,' '); //初始化
initboard(showmir, ROWS,COLS,' ');
setmire(stormir, ROW, COL); //放置雷
//函数功能实现
void initboard(char stormir[][COLS], int rows, int cols, char ch)
{
int i = 0;
int j = 0;
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
{
stormir[i][j] = ch;
}
}
}
void setmire(char stormir[ROWS][COLS], int row, int col)
{
int count = 0;
int i = 0, j = 0;
while (count !=10)
{
i = rand() % row + 1;
j = rand() % col + 1;
if (stormir[i][j] != '*')
{
stormir[i][j] = '*';
count++;
}
}
}
3. 打印游戏信息
void disaplayboard(char showmir[][COLS], int row, int col)
{
int i = 0, j = 0;
printf("\\n");
for (i = 1; i <= row; i++)
{
if (i == 1)
{
printf(" ");
for (j = 0; j < col; j++)//打印每一列的数字
{
printf(" %d ", j + 1);
printf(" ");
}
printf("\\n");
}
printf(" %2d ", i);//打印每一行的数字
for (j = 1; j <= col; j++)//打印| 信息 |
{
printf(" %c ", showmir[i][j]);
if (j != col)
{
printf("|");
}
}
printf("\\n");
for (j = 0; j < col; j++)//打印|--|分割用
{
if (j == 0)
printf(" ");
printf("---");
if (j != col - 1)
{
printf("|");
}
}
printf("\\n");
}
}
- 存放雷的数组的打印
- 游戏信息的打印
4. 排查雷与标记雷
- 排查当前格子附近八个格子雷的个数,并把数目赋值给该格子
- 标记符号用“?”来标记。
//排查雷
printf("请输入排查雷的坐标:>\\n");
printf("行:"); scanf("%d", &i);
printf("\\n");
printf("列:"); scanf("%d", &j);
if (i > 0 && i<ROW+1 && j>0 && j < COL+1)//判断排查坐标的合法性
{
if (stormir[i][j] == '*')
{
Sleep(1000);
printf("很遗憾,你被炸死了\\n");
disaplayboard(stormir, ROW, COL);//打印雷
break;
}
else
{
countmir(stormir, showmir, i, j);//对周围雷的个数计数
disaplayboard(showmir, ROW, COL);
}
void countmir(char stormir[][COLS], char showmir[][COLS], int x, int y)
{
int count = 0;
count = stormir[x - 1][y - 1] % 32 + stormir[x][y - 1] % 32 + stormir[x + 1][y - 1] % 32 + stormir[x - 1][y] % 32 + stormir[x + 1][y] % 32 + stormir[x - 1][y + 1] % 32 + stormir[x][y + 1] % 32 + stormir[x + 1][y + 1] % 32;
showmir[x][y] = count / 10 + 48;//转换成字符‘\\1’的形式赋给char类型的数组
}
//标记雷
printf("请选择标记雷的位置:>\\n");
printf("行:"); scanf("%d", &x);
printf("\\n");
printf("列:"); scanf("%d", &y);
if (x > 0 && x<ROW+1 && y>0 && y < COL+1&&showmir[x][y]==' ')
{
markmir(showmir,ROW,COL,x,y);
disaplayboard(showmir, ROW, COL);
}
else
{
printf("输入非法,请重新输入:>");
}
void markmir(char showmir[][COLS], int row, int col, int x, int y)
{
showmir[x][y] = '?';
}
- 排查雷
- 标记雷
5. 排查后附近格子的自动展开
- 一个一个排查太麻烦,根据游戏功能,可以实现自动展开
- 八个方向展开,碰到0则继续展开,碰到不为0的则停止
- 注意不越界
void if_extern(char stormir[][COLS], char showmir[][COLS], int x, int y)
{
if (countmir(stormir,showmir,x,y) == '0')//此时将countmir函数的返回类型由void改为char
{
if (x - 1 > 0&&showmir[x-1][y]==' ')
if_extern(stormir, showmir, x - 1, y);
if (x + 1 <= ROW&&showmir[x+1][y]==' ')
if_extern(stormir, showmir, x + 1, y);
if (y-1>0&&showmir[x][y-1]==' ')
if_extern(stormir, showmir, x , y-1);
if (y+1<=COL&&showmir[x][y+1]==' ')
if_extern(stormir, showmir, x, y+1);
if (x-1>0&&y-1>0&&showmir[x-1][y-1]==' ')
if_extern(stormir, showmir, x - 1, y-1);
if (x-1>0&&y+1<=COL&&showmir[x-1][y+1]==' ')
if_extern(stormir, showmir, x - 1, y+1);
if(x+1<=ROW&&y-1>0&&showmir[x+1][y-1]==' ')
if_extern(stormir, showmir, x + 1, y-1);
if (x+1<=ROW&&y+1<=COL&&showmir[x+1][y+1]==' ')
if_extern(stormir, showmir, x + 1, y+1);
}
}
6. 判断输赢
当showmir数组中出现了71个数字时,即剩下10个格子全为雷。
int if_win(char showmir[][COLS], int row, int col)
{
int i = 0, j = 0;
int count = 0;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (showmir[i][j] != ' '||showmir[i][j]!='?')
count++;
}
}
return count;//count71时,即排雷成功。
}
7. 细节优化
- 添加选择项,是排雷还是标记雷
- 当要显示雷的信息时,添加exchangmir函数来交换雷的信息(当被炸死时可以只用showmir显示游戏信息与雷的信息)
- 进入游戏界面时,采用do while循环保证进入while循环一次,而后根据玩家所选择再判断while循环是否继续
- 游戏菜单与界面优化
void exchangmire(char stormir[][COLS], char showmir[][COLS], int row, int col)
{
char tmp = ' ';
int i = 1, j = 1;
for (i = 1; i <= row; i++)
{
for (j = 1; j <= col; j++)
{
if (stormir[i][j] == '*'&&showmir[i][j]==' ')
{
tmp = stormir[i][j];
showmir[i][j] = tmp;
}
}
}
}
//功能选项
void selct_menu()
{
printf("|————————————————————————————————|\\n");
printf("| |\\n");
printf("| 1.查雷 2.标记雷 |\\n");
printf("| |\\n");
printf("|————————————————————————————————|\\n");
}
//游戏菜单选项
void game_menu()
{
printf("|————————————————————————————————|\\n");
printf("| |\\n");
printf("| 1.paly 0.exit |\\n");
printf("| |\\n");
printf("|————————————————————————————————|\\n");
}
int input = 0;
do
{
game_menu();
printf("请选择:>\\n");
scanf("%d", &input);
switch (input)
{
case 1:
game();
break;
default:
break;
}
} while (input);
}
8. 各个文件中的原码
// game.h
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <windows.h>
#define ROWS 11
#define COLS 11
#define ROW 9
#define COL 9
void initboard(char stormir[][COLS],int rows,int cols, char ch);
void setmire(char stormir[][COLS], int row, int col);
void disaplayboard(char showmir[][COLS], int row, int col);
char countmir(char stormir[][COLS], char showmir[][COLS], int x, int y);
void exchangmire(char stormir[][COLS],char showmir[][COLS],int row,int col);
void if_extern(char stormir[][COLS], char showmir[][COLS], int x, int y);
int if_win(char showmir[][COLS], int row, int col);
void selct_menu();
void markmir(char showmir[][COLS], int row, int col, int x, int y);
// test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void game()
{
char stormir[ROWS][COLS] = { 0 };
char showmir[ROWS][COLS] = { 0 };
initboard(stormir,ROWS,COLS,' ');
initboard(sh以上是关于五一假期我竟然做出来了这个程序———— 扫雷 (功能完全版)的主要内容,如果未能解决你的问题,请参考以下文章