扫雷代码程序包含的内容主要有以下几大块:
1.自定义函数的定义、数组作为自定义函数形式参数的传参方式
2.break跳出语句的局限性
3.不同函数头文件的include,<>和“”对不同头文件的引用情境,.c文件和.h文件之间信息的相互连结
4.不同变量的定义方式,如何有效实现变量名和其作用之间的对应区分
5.如何让程序更加有条理性
首先第一点,关于自定义函数这一知识点,我也会后续补充到《C语言--函数》文章里,以下是实战中对他的进一步加深理解。
为了提高代码的可读性和简洁性,我首先创建了game.h game.c whole.c三个文件,我所需要的函数在game.h头文件中进行声明,game.c源文件中完成了函数的定义,最后我们定义的函数在whole.c源文件中执行了他的功能。
其次,当数组作为形式参数加入到自定义函数中时,我们在使用函数时对应的数组只需要给数组名,而不要包括后面的下标值,完善的下标值在程序运行时会解析成数组中对应下标的元素。
以下是示例
//摘取了扫雷文件中打印棋盘的自定义函数print为例
void print(char arr[Rows][Cols], int row, int col);
//这是在头文件中的函数声明
//这是在源文件中的函数定义
void print(char arr[Rows][Cols], int row, int col)
//我们知道在二维数组定义时必须给定列数,行数非必要(电脑可以根据初始化元素数量进行划分)
//但是在我们的自定义函数中,除一维数组参与函数定义时中括号可以不输入对应元素,其余数组的容积大小需完善,同时我们要注意,这里的char arr[Rows][Cols]被视为数组的名称
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%c ", arr[i][j]);
printf("\n");
}
//以上代码块为二维数组通用的printf函数
}
int main()
{
char arr[3][5] ={1,2,3,4,5,2,3,4,5,6,3,4,5,6,7}
print(arr,3,5)
//在使用时只需要输入数组的名称,若照搬函数定义时的arr[Rows][Cols]则会产生报错
return 0;
}
如果我们在使用函数时对参数的输入格式错误,则会出现下面的情况
这里的char show[Rows][Cols]是类型声明语法(在函数定义时使用),但函数在调用传参时,不需要再写类型,直接传变量或者常量即可。
根据这个问题我们有以下总结:
1.函数调用时,传参只给变量/常量,不带类型;
2.调用前,变量(如arr、set数组)均已正确定义;
3.核对函数声明和定义的参数格式,确保一致性。
_______________________________________________________________________________
观察上图红圈部分,这是由于对'break’语句的不正确理解导致的情况。
break只能跳出离他最近的一次循环,如过break嵌套太深,会导致无法跳出循环的情况发生,他的这种特性类似于else语句总是和离他最近的if语句相关联。
同样的,如果我们担心break语句执行后仍未跳出循环,或继续执行后续的语句,我们可以加强对后续语句执行方式的限定,例如在print前加if(flag == 1)这样语句就会根据flag的值进行判断是否执行。
偷懒技巧:如果担心break跳出循环不准确,我们可以考虑使用goto语句,结束此循环
当一个库函数未包含头文件时,编译器会出现报警,警告内容如“”未定义,假设外部返回int
关于常用库函数对应的头文件总结(后续会逐渐更新):
1.<stdio.h>——printf scanf
2.<stdlib.h>——rand system srand
3.<string.h>——strlen
注:sizeof不是一个函数,他是C语言中的一个操作符,用于获取数据类型或者变量在内存中占用的字节数,使用时不需要包含头文件
4.<time.h>——time
_______________________________________________________________________________
在扫雷这个程序编写中,我们会使用到很多的变量去判断信息,那么我们应该如何定义他们的名称才能更加方便快捷的使用他们呢。以下是我个人总结的几大原则:
1.易读性
我们编写的变量名称一定要对看代码的人通俗易懂,我们可以使用他们的中文拼音也可以使用在英语中的单词,这是两个最简单的编写方式
2.唯一性
变量的名称编写要保持唯一性,尤其在全局变量中,名称如果不唯一,编译器会出现报警的情况,同时也会让我们混淆不同变量之间的功能
3.同一性
我们知道在C语言中数据的类型多种多样,如整型类型、字符类型、浮点类型、布尔类型;那么根据这个特性我们可以对同一类型变量,采取相同的名称定义,这样也能方便变量之间的调用。
_______________________________________________________________________________
注释是C语言代码编写中的强大功能,我们可以对自己编写代码键入合适的注释,以便后续自己活着他人阅读时可以更加方便快捷。
扫雷程序编写的思路方向:
1.游戏开始和退出的选择
2.进入游戏的游戏模块编写(思路很重要)
在此步骤中,我们要预设代码的实现,我们知道扫雷展现时我们是无法观察到雷的排布,但同样的我们又需要让系统知道我们在何处藏了雷,这两种功能我们显然不可能通过一个数组全部完成,因此我们可以定义两个数组完成,且他们最好是同数据类型
我们使用*来布置棋盘1,在棋盘2中使用‘1’来表示雷的位置,‘0’表示安全地带,当我们需要确认某一特定下标值是否为雷时,我们直接对此位置上的字符进行核对即可完成。
我们知道安全区会在他的地带上标写周围9格(含自身)的地雷数量,,那么我们知道他们是限定行和列范围的一个长方形,所以我们可以依靠这个特性对后续判断进行简化。同样的边缘位置的判断会出现越界问题,故而我们考虑给棋盘每边+1的空间,即9*9的游戏空间我们创建11*11的数组
3.设置游戏的循环方式和退出方式
———————————————————————————————————————————
下面是我编写的扫雷程序三个文件的源代码,可供大家参考,也辛苦大家指出我的编码问题
#pragma once
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#define Row 9
#define Col 9
#define Rows Row + 2
#define Cols Col + 2
void init_hide(char arr[Rows][Cols],int row,int col,char a);
void setbomb(char arr[Rows][Cols], int b, int row, int col);
void init_show(char arr[Rows][Cols], int row, int col, char a);
void print(char arr[Rows][Cols], int row, int col);
void compare_both(char arr[Rows][Cols], char arr2[Rows][Cols], int x, int y,int flag);
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
void init_hide(char arr[Rows][Cols], int row, int col, char a)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
arr[i][j] = a;
/* printf("%c", arr[i][j]);*/
}
}
}
void setbomb(char arr[Rows][Cols],int b ,int row,int col)
{
int x, y;
while (b > 0)
{
x = rand() % row + 1;
y = rand() % col + 1;
if (arr[x][y] != '1')
{
arr[x][y] = '1';
b --;
}
}
}
void init_show(char arr[Rows][Cols], int row, int col, char a)
{
int i = 0;
int j = 0;
for ( i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (i == 0 || i == row - 1)
arr[i][j] = j + '0';
else if (j == 0 || j == col -1)
arr[i][j] = i + '0';
else
arr[i][j] = a;
printf("%c ", arr[i][j]);
}
printf("\n");
}
}
void print(char arr[Rows][Cols], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
printf("%c ", arr[i][j]);
printf("\n");
}
}
void compare_both(char arr[Rows][Cols],char arr2[Rows][Cols], int x, int y,int flag)
{
int sum = 0;
if ((x > 0 && x < 9) && (y > 0 && y < 9))
{
if (arr[x][y] == '1')
{
flag = 0;
printf("很不幸,你被雷炸死了\n");
}
else
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (arr[x + i][y + j] == '1')
sum++;
}
}
arr2[x][y] = '0' + sum;
}
}
else
printf("请输入正确的行列数\n");
}
#define _CRT_SECURE_NO_WARNINGS 1
#include "game.h"
//choice()
//{
// int count;
// printf("请自定义你的埋雷个数\n");
// /*printf("简单 普通 困难\n");*/
// printf("请输入 ");
// scanf("%d", &count);//定义埋雷数量
//
//}
game()//游戏具体操作方式
{
char show[Rows][Cols];
char hide[Rows][Cols];
init_show(show,Rows,Cols, '*');//游戏上界面展示
init_hide(hide,Rows,Cols, '0');//游戏下界面雷区
//布置雷
int count;
printf("请自定义你的埋雷个数\n");
/*printf("简单 普通 困难\n");*/
printf("请输入 ");
scanf("%d", &count);//定义埋雷数量
setbomb(hide, count, Row, Col);//埋雷
print(hide, Rows, Cols);
//检验埋雷的位置
int flag = 1;//用来判断是否结束循环
int try = Row * Col - count;//限制测试的次数
while (flag == 1 && try > 0 )
{
int x, y;
printf("请输入你想查询的埋雷坐标");
scanf("%d%d", &x, &y);
try--;
/*compare_both(hide, show, x, y,flag);*/
int sum = 0;
if ((x > 0 && x < 9) && (y > 0 && y < 9))
{
if (hide[x][y] == '1')
{
flag = 0;
printf("很不幸,你被雷炸死了\n");
break;
}
else
{
for (int i = -1; i < 2; i++)
{
for (int j = -1; j < 2; j++)
{
if (hide[x + i][y + j] == '1')
sum++;
}
}
show[x][y] = '0' + sum;
}
}
else
printf("请输入正确的行列数\n");
/* if (flag == 0)
{
break;
}
else if (flag == 1 && try == 0)
{
printf("恭喜你完成了游戏\n");
}
else*/
print(show, Rows, Cols);
}
}
//进入游戏界面
int main()
{
int answer;//判断玩家输入值,以实现游戏的开始、结束、重新输入
while (1)
{
srand((unsigned int)time(NULL));
printf("*******************\n");
printf("******1. play******\n");
printf("******0. exit******\n");
printf("*******************\n");
printf("请输入 ");
scanf("%d", &answer);//输入answer的值
if (answer == 1)
{
printf("游戏开始\n");
game();
/* break;*/
}
else if (answer == 0)
{
printf("游戏结束\n");
break;
}
else
{
printf("输入错误,请重新输入\n");
}
}
return 0;
}
打怪升级中..................................................................................................................................