前前后后因为一些原因扫雷程序已经写了不下5遍了,在此分享一下自己发现的一些问题,希望对你有所帮助
文章目录
代码思路
对于这样的程序,分文件编写能更加有条理且美观,因此我们分了三个文件,分别用来声明所用函数(game.h),实现所用函数(game.c),进行汇总、执行(test.c)
实现扫雷的大体思路:
1.向玩家展示菜单,询问游玩或否
2.扫雷棋盘分为 显示给玩家看的棋盘 和 埋雷用的隐藏的棋盘,也就是说要定义2个二维数组
3.在玩家进入游戏后,系统需要进行 埋雷、打印棋盘给玩家参考、让玩家进行扫雷
剩下的就是各种细节和优化~
1.利用宏定义define 使得之后在修改行列数量时不用挨个修改
2.可以让埋雷的棋盘比显示用的棋盘多2行2列,控制雷埋在非边缘行列,可以对扫雷时周边雷数量的统计进行优化
3.srand((unsigned int)time(NULL))用时间控制随机数生成
扫雷代码
game.h 头文件
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define ROW 10 //排
#define COL 10 //列
//菜单
void Menu();
//初始化棋盘(显示给玩家的数组)
void InitChart(char arr[ROW][COL]);
//埋雷的数组似乎不用专门写个函数 直接 ={ 0 }就好
//打印棋盘
void Print(char arr[ROW][COL]);
//(测试用)打印埋雷棋盘
void Print_Mine(char arr[ROW + 2][ROW + 2]);
//埋雷
void SetMine(char arr[ROW + 2][ROW + 2],int num);
//扫雷
void Play(char arr[ROW][COL], char mine[ROW + 2][COL + 2]);
game.c 函数实现文件
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
//菜单
void Menu() {
printf("**************************\n");
printf("**** 0.退出 ** 1.开始 ****\n");
printf("**************************\n");
}
//初始化棋盘(显示给玩家的数组)
void InitChart(char arr[ROW][COL]) {
for (int i = 0; i < ROW; i++) for (int j = 0; j < COL; j++) arr[i][j] = '*';
}
//打印棋盘
void Print(char arr[ROW][COL]) {
printf(" "); for (int k = 1; k <= COL; k++) printf("%2d", k); printf("\n");
for (int i = 0; i < ROW; i++) {
printf("%-2d", i + 1);
for (int j = 0; j < COL; j++) {
printf(" %c", arr[i][j]);//查查ACSII码表就知道1如果用%c打印出来是个笑脸(打印不出来),所以不能让这里的值是1
}
printf("\n");
}
}
//(测试用)打印埋雷棋盘
void Print_Mine(char arr[ROW + 2][ROW + 2]) {
printf(" "); for (int k = 1; k <= COL + 2; k++) printf("%2d", k); printf("\n");
for (int i = 0; i < ROW + 2; i++) {
printf("%-2d", i + 1);
for (int j = 0; j < COL + 2; j++) {
printf(" %d", arr[i][j]);
}
printf("\n");
}
}
//埋雷——不可重复,不可设置在边缘
void SetMine(char arr[ROW + 2][ROW + 2],int num) {
while (num != 0) {
int row = rand() % ROW + 1; int col = rand() % ROW + 1;//随机出来的坐标必然在数组内且不在边缘(1~10)
if (arr[row][col] != 1) {//可千万注意写 =1时,ASCII码值为1--写='1'时ASCII值为31
arr[row][col] = 1;
num--;
}
}
}
//扫雷
void Play(char chart[ROW][COL], char mine[ROW + 2][COL + 2]) {
int x = 0, y = 0, i = 0, j = 0, num = 0;
while (1) {
x = 0; y = 0; i = 0; j = 0; num = 0;
//给玩家展示当前棋盘 以及测试用的埋雷棋盘
system("cls");
Print(chart);
Print_Mine(mine);
printf("请输入坐标:");
scanf("%d %d", &x, &y);
//判断坐标是否合理(不能重复,不可越界)
if (chart[x - 1][y - 1] != '*' || x < 1 || x > ROW || y < 1 || y > COL) {
printf("请重新输入\n");
continue;
}
//判断是否踩雷(游戏结束)
if (mine[x][y] == 1) {
//记得把棋盘展示出来(把所有雷所处的位置也展示出来)***有什么更好的方法吗
for (i = 0; i < ROW; i++) for (j = 0; j < COL; j++) if (mine[i + 1][j + 1] == 1) chart[i][j] = '#';
system("cls");
Print(chart);
printf("游戏结束!\n");
break;
}
//————已确认可以正常进行————
//检查周围雷的数量
for (i = x - 1; i < x + 2; i++) for (j = y - 1; j < y + 2; j++) num += mine[i][j];
chart[x - 1][y - 1] = num + 48;//让ASCII码值对应相应的数组
//展示棋盘就交给下一次循环开始做了
}
}
test.c 总程序
#define _CRT_SECURE_NO_WARNINGS
#include"game.h"
void Game(int num) {
char chart[ROW][COL];//显示棋盘用数组
char mine[ROW+2][COL+2] = { 0 };//埋雷数组
InitChart(chart);
SetMine(mine, num);
Play(chart, mine);
return;
}
int main() {
srand((unsigned int)time(NULL));//设置随机数
int input = 0, num = 0;
while (1) {
Menu();
scanf("%d", &input);
if (input == 0) {
printf("退出游戏"); break;
}
printf("请设置雷的数量:");
scanf("%d", &num);
Game(num);
}
return 0;
}
一些问题
扫雷作为一个新手入门编写的程序,在不加任何逻辑的情况下,其实只要有了大体的思路,剩下的就是处理各种细节了——主打一个熟能生巧(
char arr[1][1] = 1; 和 char arr[1][1] = ‘1’;
char arr[1][1] = 1; ASCII值为1,用%c打印是个笑脸,打印不出来
char arr[1][1] = ‘1’;ASCII值为49(十六进制31),用%c打印是1
通过 +48 的方式使得char arr[1][1] = 1; 用 %c 能够打印出’1’
关于在test.c里写的Game()函数
可能各位已经习惯于在此写一个函数对所有的步骤进行汇总——是个好习惯
之前写其他程序时将类似于Game()函数的函数写在了game.c里,产生了不少麻烦,所以我想应该有所注意