/*
扫雷练习
*/
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main() {
int map[10][10] = {0};
int delta[][2] = {-1, -1, -1, 0, -1, 1,
0, -1, 0, 1, 1, -1, 1, 0, 1, 1};
int row = 0, col = 0, cnt = 0, num = 0;
srand(time(0));
do {
//找到一个随机的存储区
row = rand() % 10;
col = rand() % 10;
if (!map[row][col]) {
//随机存储区里不是地雷
map[row][col] = -1;
cnt++;
}
} while (cnt < 10);
for (row = 0;row <= 9;row++) {
for (col = 0;col <= 9;col++) {
if (map[row][col] == -1) {
//如果当前位置是地雷就忽略
continue;
}
for (num = 0;num <= 7;num++) {
//依次处理周围的八个格子
int tmp_row = row + delta[num][0];
int tmp_col = col + delta[num][1];
//忽略不再地图里的格子
if (tmp_row < 0 || tmp_row > 9) {
continue;
}
if (tmp_col < 0 || tmp_col > 9) {
continue;
}
if (map[tmp_row][tmp_col] == -1) {
//如果周围的某个格子里是地雷就把当前格子里的数字加一
map[row][col]++;
}
}
}
}
for (row = 0;row <= 9;row++) {
for (col = 0;col <= 9;col++) {
if (!map[row][col]) {
printf("O");
}
else if (map[row][col] == -1) {
printf("X");
}
else {
printf("%d", map[row][col]);
}
}
printf("\n");
}
return 0;
}
C语言程序中可以用分组的方式管理语句
每个语句分组叫做一个函数
/*
函数演示
*/
#include <stdio.h>
void print(void) {
int num = 2;
printf("1\n");
printf("num是%d\n", num);
}
int main() {
int num = 1;
printf("num是%d\n", num);
print();
return 0;
}
多函数程序执行模式有如下特点
整个程序的执行时间被分解成几段,每段时间被分给一个函数使用
任何两个时间段不能互相重叠并且所有时间段必须连续
如果函数A在工作过程中把一段时间分配给函数B使用,则函数B在使用完所有时间之后必须把后面的时间还给函数A
如果函数A把时间分配给函数B则它们之间存在函数调用关系
其中函数A叫做调用函数,函数B叫做被调用函数
函数调用关系有时间范围,只有被调用函数工作期间函数调用关系才存在
在程序中使用函数调用语句产生调用关系
不可以跨函数使用变量
不同函数里的变量可以重名
如果一个函数多次运行则每次运行的时候内部变量对应的存储区有可能不同
volatile关键字可以用来声明变量
使用这个关键字声明的变量每次拿数的时候都可以得到存储区里真正的数字
函数调用过程中通常伴随着两个函数之间的数据传递
数据传递存在两个完全不同的方向,有可能从调用函数向被调用函数传递,也可能从被调用函数向调用函数传递
任何一个方向的数据传递都需要使用被调用函数提供的存储区
只能从被调用函数向调用函数传递一个数据
只能在被调用函数结束的时候才能传递这个数据
这个数据叫被调用函数的返回值
函数的返回值必须记录在被调用函数提供的一个专门的存储区里,应该把这个存储区的类型名称写在函数名称前
在被调用函数里使用return关键字向这个存储区里放返回值
调用函数直接把函数调用语句当数字使用就可以得到被调用函数的返回值
/*
返回值演示
*/
#include <stdio.h>
int read(void) {
int num = 0;
printf("请输入一个数字:");
scanf("%d", &num);
return num;
}
int add(void) {
int num = 0, num1 = 0;
printf("请输入两个数字:");
scanf("%d%d", &num, &num1);
return num + num1;
}
int main() {
int num = read();
//printf("数字是%d\n", read());
printf("num是%d\n", num);
num = add();
printf("num是%d\n", num);
return 0;
}
如果被调用函数里没有使用return关键字指定返回值则存放返回值的存储区里内容是随机的
这个存储区不能用来长期存放数字,调用函数得到返回值以后或者立刻使用或者转存到其它存储区里
函数名称前写void表示函数没有提供用来存放返回值的存储区
如果函数名称前什么都没写在C89规范里表示函数提供了一个整数类型存储区用来存放返回值,C99规范里不允许这样
/*
形式参数演示
*/
#include <stdio.h>
void print(int num, int num1) {
printf("%d %d\n", num, num1);
}
int main() {
int num = 0, num1 = 0;
printf("请输入两个数字:");
scanf("%d%d", &num, &num1);
print(num, num1);
return 0;
}
被调用函数不能使用数组存放返回值
调用函数可以一次向被调用函数传递多个不同类型的数据,被调用函数需要提供多个存储区存放这些数据
可以用一组变量表示这些存储区,这组变量必须声明在函数名称后面的小括号里
这些变量叫做形式参数,小括号里的内容统称为形式参数列表
形式参数列表是用逗号连接的多个变量声明语句,每个形式参数的类型名称都不可以省略
/*
形式参数练习
*/
#include <stdio.h>
int add(int num, int num1) {
return num + num1;
}
int main() {
int num = 0, num1 = 0;
printf("请输入两个数字:");
scanf("%d%d", &num, &num1);
printf("求和结果是%d\n", add(num, num1));
return 0;
}
函数调用语句里需要为每个形式参数提供一个对应的数据,这些数据叫实际参数。
函数调用的时候计算机把实际参数记录到对应的形式参数里,被调用函数可以从形式参数里获得实际参数的数值
所有能当数字使用的内容都可以当作实际参数使用
函数名称后面的小括号里写void表示函数不需要从调用函数得到任何数字
如果小括号里什么都没写表示函数可以提供任意多个任意类型的形式参数
/*
函数练习
*/
#include <stdio.h>
int rabbit(int heads, int legs) {
int num = 0;
for (num = 0;num <= heads;num++) {
if (4 * num + 2 * (heads - num) == legs) {
return num;
}
}
}
int main() {
int heads = 0, legs = 0, num = 0;
printf("请输入头和脚的数量:");
scanf("%d%d", &heads, &legs);
num = rabbit(heads, legs);
printf("兔子一共有%d只,鸡一共有%d只\n", num, heads - num);
return 0;
}
/*
函数练习
*/
#include <stdio.h>
void print(int num, int num1) {
printf("%d X %d = %d\n", num, num1, num * num1);
}
int main() {
int num = 0;
for (num = 1;num <= 5;num++) {
print(num, 10 - num);
}
return 0;
}