------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
1、基本概念
把具有相同类型的若干变量按有序的形式组织起来。这些按序排列的同类数据元素的集合称为数组。
在C语言中,数组属于构造数据类型。一个数组可以分解为多个数组元素,这些数组元素可以是基本数据类型或是构造类型。
数组的几个名词
1)数组:一组具有形同数据类型的数据的有序的集合
2)数组元素:
构成数组的数据。数组中的每一个数组元素具有相同的名称,不同的下标,可以作为单个变量使用,所以也称为下标变量。
3)数组的下标:
是数组元素的位置的一个索引或指示。
4)数组的维数:
数组元素下标的个数。根据数组的维数可以将数组分成一维,二维,三维,多维数组。
2、按存储的内容分类
按数组元素的类型不同,数组又可分为:
数值数组:存储数值
字符数组:存储字符
指针数组:存放指针
结构数组:存放一个结构体类型的数据
3、按维度分类
一维数组
二维数组
多维数组
一、一维数组
注意:先用一维数值数组作为例子,其他类型的数组单独总结。
如果一个数组的所有元素都不是数组,那么该数组称为一维数组。
在C语言中使用数组必须要先进行定义。
1、一维数组的定义方式为:
类型说明符 数组名[常量表达式];
int a[10];
类型说明符:
是一种基本数据类型或构造数据类型。
数组名:
用户定义的数组标识符。
方括号中的常量表达式:
表示数据元素的个数,也称为数组的长度。
注意事项:
1)数组的长度可以是一个常量,也可以是常量表达式。
2)数组名的命名规范:严格按照标识符的命名规范。
3)数组名不能和其他变量同名。
4)数组的长度不可以为一个变量。
2、一维数组的初始化:
1)定义的同时进行初始化。
int a[3]={1,2,3};
2)先定义,后初始化。
用下标法进行初始化。
int a[3];
a[0]=1;
a[1]=2’
a[2]=3;
不能写成a={1,2,3};
因为数组名是一个常量,不能赋值。
如果定义数组后,没有初始化,数组中是有值的,是随机的垃圾数,所以如果想要正确使用数组应该要进行初始化。
3、一维数组的引用
数组元素是组成数组的基本单元。
数组元素也是一种变量,其标识方法为数组名后跟一个下标。
小标表示了元素在数组中的顺序号。
数组元素访问的一般形式为:
数组名[下标]
例:a[0] 数组a的第一个元素。
其中下标只能位整型常量或整型表达式。如为小数是,C编译将自动取整。
应用:数组的遍历
#include <stdio.h>
int main(int argc, const char * argv[]) {
int len;
printf("请输入数组的长度:\n");
scanf("%d",&len);
int a[len];
for (int i = 0; i<len; i++) {
printf("请给第%d个元素赋值:\n",i+1);
scanf("%d",&a[i]);
}
for (int j = 0; j<len; j++) {
printf("%d\t",a[j]);
}
return 0;
}
4、一维数组的存储方式
1)计算机会给数组分配一块连续的存储空间。
2)数组名代表数组的首地址,从首地址位置,依次存入数组的第1个、第2个······第n个元素。
3)每个元素占用相同的字节数(取决于数据类型)。
4)元素之间的地址是连续的。
#include <stdio.h>
int main(int argc, const char * argv[]) {
int x[5]={1,2,3,4,5};
char ch[5]={'a','b','c','d','e'};
printf("数组 x的地址:%p\n",x);
printf("数组ch的地址:%p\n",ch);
printf("先定义的数组分配高地址!\n");
printf("数组x=:%p\n",x);
printf("&x[0]= %p\n",&x[0]);
printf("数组ch= %p\n",ch);
printf("&ch[0]= %p\n",&ch[0]);
printf("数组名存放的是数组的首地址。\n");
for (int i =0; i<5; i++) {
printf("数组x的第%d个元素的地址是:%p\n",i+1,&x[i]);
}
printf("数组内部元素的地址是连续的!\n");
return 0;
}
运行的结果是:
数组 x的地址:0x7fff5fbff760
数组ch的地址:0x7fff5fbff74b
先定义的数组分配高地址!
数组x=:0x7fff5fbff760
&x[0]= 0x7fff5fbff760
数组ch= 0x7fff5fbff74b
&ch[0]= 0x7fff5fbff74b
数组名存放的是数组的首地址。
数组x的第1个元素的地址是:0x7fff5fbff760
数组x的第2个元素的地址是:0x7fff5fbff764
数组x的第3个元素的地址是:0x7fff5fbff768
数组x的第4个元素的地址是:0x7fff5fbff76c
数组x的第5个元素的地址是:0x7fff5fbff770
数组内部元素的地址是连续的!
Program ended with exit code: 0
5、一维数组长度计算方法
数组在内存中占用的总字节数:sizeof(数组名);
所以:
数组的长度:数组占用总字节数/ 数组元素占用的字节数。
int main(int argc, const char * argv[]) {
int a[8]={1,2,3,4,5,6,7,8};
int len=0;
len=sizeof(a)/sizeof(int);
printf("len =%d\n",len);
return 0;
}
6、一维数组的越界问题
调用了不属于数组的内存空间。
这是不安全的,因为这个空间不属于数组
即使没有报错,但是这个数据可能会丢失
应用:
通过for循环,从键盘获取10个数,存放到数组中。找出10个数中的最大值。
#include <stdio.h>
int main(int argc, const char * argv[]) {
int max;
int a[10];
printf("请输入10个数\n");
for (int i =0; i<10; i++) {
printf("请输入第%d个数:\n",i+1);
scanf("%d",&a[i]);
}
printf("你输入的10个数是:\n");
for (int j = 0; j<10; j++) {
printf("%d\t",a[j]);
}
printf("\n这10个数中最大的是:");
max = a[0];
for (int n = 1; n<10; n++) {
if (a[n]>max) {
max = a[n];
}
}
printf("%d",max);
return 0;
}
7、数组元素作为函数参数
数组可以作为函数的参数使用,进行数据传送。
数组用作函数参数有两种形式:
1)数组元素(下标变量)作为实参使用。
2)数组名作为函数的形参和实参使用。
数组元素作为函数实参
数组元素就是下标变量,它与普通变量并无区别。
在发生函数调用是,把作为实参的数组元素的值传递给形参,实现单向的值传递。
思考&实现:
判别一个整数数组中的各元素的值,若大于0在输出该值,若小于等于0则输出0值(判断过程使用函数实现)
#include <stdio.h>
/**
* 判断并输出数组传递的值
*
* @param x 数组元素的值
*/
void printNum(int x){
if (x>0) {
printf("%d\t",x);
} else {
printf("0\t");
}
}
int main(int argc, const char * argv[]) {
int a[5]={1,-4,3,-8,9};
for (int i = 0; i<5; i++) {
printNum(a[i]);
}
return 0;
}
数组名作为函数参数
用数组名作为函数参数与用数组元素作实参有几点不同
1)用数组元素作很熟参数不要求形参也必须是数组元素,但是用数组名作函数参数时,则要求形参和相对应的实参都必须是类型相同的数组。
2)数组名还代表了该数组在内存中的起始位置,因此当数组名作函数参数时,实参与形参之间是“地址传递”,实参把该数组的起始地址传递给形参数组,两个数组共享一段内存空间,编译系统不再为形参数组分配存储单元。
数组名作为函数参数的注意点
1、形参数组和实参数组类型必须一致,否则将引起错误。
2、形参数组和实参数组的长度可以不同,因为在调用是知识传递首地址,不检查形参数组的长度,如果两者长度不一致,编译能通过,但程序执行结果将与实际不符,应该注意。
3、形参数组的长度可以不写,或者用一个变量来表示数组元素的个数。
4、多维数组也可以作为函数的参数。
5、C语言中规定,不管什么类型的数据,数据的内存地址在内存中占用8个字节。
冒泡排序和选择排序思想
1、冒泡排序
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把它们交换过来,走访数列的工作是重复地进行知道没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
有两种:
大数下沉 小数上浮
2、冒泡排序步骤
1)比较相邻的元素。
如果第一个比第二个大,就交换他们两个。
2)对每一对相邻元素作同样地工作,从开始第一队到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
3)针对所有的元素重复以上的步骤,除了最后一个。
4)持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
思考&实现
输入一组无序数据,使用冒泡排序法进行排序,并输出。
#include <stdio.h>
void maoPao(int arr[],int len){
int temp;
for (int i =0; i<len-1; i++) {
for (int j =0; j<len-1-i; j++) {
if (arr[j]>arr[j+1]) {
temp=arr[j];
arr[j]=arr[j+1];
arr[j+1]=temp;
}
}
}
}
int main(int argc, const char * argv[]) {
int a[10]={1,45,645,234,5682,3345,231,34,876,35};
printf("排序前数据是:\n");
for (int i = 0; i<10; i++) {
printf("%d\t",a[i]);
}
printf("\n排序后结果是:\n");
maoPao(a, 10);
for (int i = 0; i<10; i++) {
printf("%d\t",a[i]);
}
return 0;
}
2、选择排序
1、选择排序
选择排序(Selectionsort)
是一种简单直观地排序算法。它的工作原理如下:
首先在未排序序列中找到最小元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小元素,然后放到排序序列的下一位。以此类推,知道所有元素均排序完毕。
2、选择排序基本思想
代码 if ( a [ i ]>a [ j ] )则交换a [i ]和a[ j ]的值。
思考&实现1:
输入一组无序数据,使用选择排序法进行排序,并输出。
代码void selectChange(int arr[],int len){
int temp;
for (int i = 0; i<len -1; i++) {
for (int j = i + 1; j<len; j++) {
if (arr[i]>arr[j]) {
temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
}
}
}
二、折半查找思想
1、基本思路
在有序表中,取中间元素作为比较对象,若给定值与中间元素的要查找的数相等,则查找成功;
若给定值小于中间元素的要查找的数,则在中间元素的左半区继续查找;
若给定值大于中间元素的要查找的数,则在中间元素的饿右半区继续查找。不断重复上述查找过程,直到查找成功,或所查找的区域无数据元素,查找失败。
例子,猜一个1000内的数,先猜500,大了就是1~500之间,小了就是500~1000之间。
2、实现步骤
length位数组长度,key为要查找的值,arr位已知数组。
1)low = 1 ,high = length | 设置初始区间 |
2)当low>high时,返回查找失败信息 | 表空,查找失败 |
3)low<=hig,mid=(low+high)/2 | 取中点 |
a、若key<arr[mid], high = mid -1 ;转到2) | 查找在左半区进行 |
b、若key>arr[mid],low = mid + 1; 转到2) | 查找在右半区进行 |
c、若key =arr[mid],返回数据元素在表中的位置 | 查找成功 |
例子:已知有序表:
7 | 12 | 34 | 57 | 68 | 70 | 98 |
查找 12。
步骤:
arr[] | arr[0] | arr[1] | arr[2] | arr[3] | arr[4] | arr[5] | arr[6] |
数值 | 7 | 12 | 34 | 57 | 68 | 70 | 98 |
1)low = 1 , high = length = 7,key = 12;
2)low<high,所以mid = (1+7)/2=4 ;
- Key<arr[4](68),所以 high = mid -1 = 3;
- Low = 1,high = 3; low<high, mid = (1+3)/2=2 ;
- Key < arr[mid](34),所以high = mid -1=1;
- Low =1 , high = 1; low<=high, mid=(1+1)/2=1
- Key = arr[mid] 返回数据元素在表中位置,查找成功。
思考&实现1:
输入一组有序数据,使用折半查找法查找一个数据,并输出其位置。
/**
* 在数组中查找一个数,并输出它的位置。如果没有,输出没有这个数。
*
* @param arr 已知的有序数组
* @param len 数组的长度
* @param key 要查找的数。
*
* @return 数的位置,或者-1.
*/
int search(int arr[],int len,int key){
int low =0,high = len -1,mid;
while (low<=high) {
mid = (low+high)/2;
if (key<arr[mid]) {
high=mid -1;
} else if(key>arr[mid]) {
low = mid +1;
} else{
return mid;
}
}
return -1;
}
思考&实现2:
输入一组有序数据,使用折半查找法插入一个数据,返回要插入数据的位置。
假定插入5
1,3,4,6,8
/**
* 往已知有序数组中插入一个数,并输出位置
*
* @param arr 已知数组
* @param len 数组长度
* @param key 要插入的数
*
* @return 插入数的位置
*/
int putIn(int arr[],int len,int key){
int low =0,high = len -1,mid;
while (low<=high) {
mid = (low+high)/2;
if (key<arr[mid]) {
high=mid -1;
} else if(key>arr[mid]) {
low = mid +1;
} else{
return mid+1;
}
}
return mid;
}
三、二维数组
1、二维数组定义
二维数组定义的一般形式是:
类型说明符 数组名[常量表达式1][常量表达式2]
数据类型 数组名[第一维的长度(行)][第二维的长度(列)];
其中常量表达式1表示第一维下标的长度,常量表达式2表示第二维下标的长度。
例如 int a[3][4];
说明了一个三行四列的数组,数组名为a,其下标变量的类型位整型。该数组的下标变量共有3*4个。
可以看成是一个特殊的一维数组,一维有三个元素,每个元素又是一个有4个元素的数组。
2 、二维数组的初始化1)、定义的同时初始化
(1)完全初始化
第一维有2个元素第二维有3个元素
a、分段初始化:
Int a[2][3]={ {12,23,45},{1,2,3} }
12 | 23 | 45 |
1 | 2 | 3 |
b、连续赋值:
int a [2][3]={1,2,3,4,5,6};
大括号内的值按第二维元素个数分组,1,2,3为一组;
4,5,6为一组,第一组赋给第一维的第一个元素,第二组赋给第一维的第二个元素。
c、可以省略第一维
Int a [ ][3]={{1,2,3},{4,5,6},{7,8,9}};
int a [ ] [2]={1,2,3,4,5,6,7,8};按照连续赋值的原则,所以是4行2列的数组。
(2)部分初始化
a、
int a[3][4]={1};
结果是:
1 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
如果是int a [3][4]={0};
结果全是零,一般用于给数组初始化为0;
b、
int a[3][4]={{1},{2},{3}};
结果是:
1 | 0 | 0 | 0 |
2 | 0 | 0 | 0 |
3 | 0 | 0 | 0 |
c、
int a[3][4]={1,2,3,4,5};
第一维不能省,因为省了之后成了2行4列了。
结果是:
1 | 2 | 3 | 4 |
5 | 0 | 0 | 0 |
0 | 0 | 0 | 0 |
根据连续赋值的原理,1,2,3,4分成第一段,第二段就只有一个5,然后从第一个开始赋值,所以结果如上表。
二维数组中,有的方式第一维可以省,但是第二维不能省。
2 )、先定义后初始化
int a[3][4];
第一维下标:0 1 2;
第二维下标:0 1 2 3;
a[0][0] = 1;
3、二维数组遍历
二维数组的元素也称为双下标变量,其表示形式位:
数组名[第一位下标][第二维下标]
其中下标位整型常量或整型表达式。
例如:a[3][4] 数组a是三行四列的元素。
小标变量和数组说明在形式中有些相似,但这两者具有完全不同的含义。
数组说明的方括号中给出的是某一维的长度,即可取下标的最大值;
而数组元素中的下标是该元素在数组中的位置标识。
前者只能是常量,后者可以是常量、变量或表达式
思考&实现1:
一个学习小组有5个人,每个人有三门课的考试成绩。
如下表
学科|姓名 | 张 | 王 | 李 | 赵 | 周 |
C语言 | 80 | 61 | 59 | 85 | 76 |
OC语言 | 75 | 65 | 63 | 87 | 77 |
IOS开发 | 92 | 71 | 70 | 90 | 85 |
#include <stdio.h>
int main(int argc, const char * argv[]) {
int score[5][3] = {{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};
for (int i = 0; i<5; i++) {
for (int j =0; j<3; j++) {
printf("%d\t",score[i][j]);
}
printf("\n");
}
return 0;
}
4、 二维数组存储
1、二维数组存储
二维数组的下标在两个方向是变化,下标变量在数组中的位置也处于一个平面之中,但是存储器单元是按一维线性排列的。在一维存储器中存放二维数组,有两种方式:
1)、按行排列,即放完一行之后顺次放入第二行
2)、按列排列,即放完一列之后再顺次放入第二列。
存储方式:
1)计算机会给二维数组分配一块连续的存储空间。
2)数组名代表组的首地址从首地址位置,依次存入第1行、第2行···
3)每一行存储方式,从行首地址开始,依次存储行的第1个元素、第2个元素、第3个元素···
4)每个元素占用相同的字节数(取决与数组类型)
5)并且数组中元素之间的地址是连续的。
补充:
数组的首地址
数组的首地址 ==数组名 == &a[0] == &a[0][0]
2、二维数组的行数和列数计算
1)二维数组占用的总字节数?
a、总字节数 =每行占用的字节数之和。
b、总字节数 =元素的个数 *元素的类型 =行*列*sizeof(数组类型)
元素的个数 =行数 *列数
c、总字节数 = sizeof(数组名)
2)每一行的字节数如何计算?
Int a[2][2]={1,2,3,4};
a[0] | 1 | 2 |
a[1] | 3 | 4 |
a[0]是一个一维数组,所以计算每一行占用字节数 =sizeof(a[0]);
3)数组有多少行?
总字节数/每一行的字节数
sizeof(a)/ sizeof(a[0])
4)每一行有多少列?
列数 =行的总字节数/每个元素占用的字节(数组类型)
Len = sizeof(a[0]) / sizeof(int)
四、二维数组作为函数参数
1、二维数组元素作为函数参数
二维数组元素作为函数参数,相当于变量的值传递过程。
sum (score[0][1],score[3][3])
2、二维数组名作为函数参数
print_arr(score);
此处的score是一个常量,保存的是数组的首地址。
%p输出地址。
用数组名作为函数参数是地址传递。
注意事项:
1)类型和长度要匹配
2)二维数组作为函数的形参,可以不写第一维的长度。
看一维数组作为参数的注意事项,两者差不多。
几个应用:
思考&实现1:
一个学习小组有5个人,每个人有三门课的考试成绩。求每门课程的平均分和三门课的平均分。
学科|姓名 | 张 | 王 | 李 | 赵 | 周 |
C语言 | 80 | 61 | 59 | 85 | 76 |
OC语言 | 75 | 65 | 63 | 87 | 77 |
IOS开发 | 92 | 71 | 70 | 90 | 85 |
#include <stdio.h>
int main(int argc, const char * argv[]) {
int score[5][3] = {{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};
float sum;
float total = 0.0f;
for (int i = 0; i<3; i++) {
sum = 0;
for (int j = 0; j<5; j++) {
sum = sum + score[j][i];
}
total = total +sum/5;
printf("第%d门课的平均分是:%.2f",i+1,sum/5);
}
printf("三门课的平均分是:%.2f",total/3);
return 0;
}
思考&实现2:
有一个5*3的矩阵,要求编程序以求出其中值最大的那个元素的值及其所在的行号和列号。
i|j | j =0 | j =1 | j=2 | j=3 | j=4 |
I =0 | 80 | 61 | 59 | 85 | 76 |
I = 1 | 75 | 65 | 63 | 87 | 77 |
I =2 | 92 | 71 | 70 | 90 | 85 |
#include <stdio.h>
int main(int argc, const char * argv[]) {
int score[5][3] = {{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};
int max=0;
int maxHang=0;
int maxLie = 0;
max = score[0][0];
for (int i = 0; i<5; i++) {
for (int j = 0; j<3; j++) {
if (score[i][j]>max) {
max = score[i][j];
maxHang=i;
maxLie=j;
}
}
}
printf("最大数是%d\n在第%d行,第%d列",max,maxHang+1,maxLie+1);
return 0;
}
思考&实现3:
从键盘上接收两个参数分别存放到m,n中,使用m和n构成数组:
1)定一个函数使用i*j初始化a[i][j];
2)定义一个函数打印二维数组的每一个值。
/*
思考&实现1:
从键盘上接收两个参数分别存放到m,n中,使用m和n构成数组:
1)定一个函数使用i*j初始化a[i][j];
2)定义一个函数打印二维数组的每一个值。
思路:
1)定义变量
2)提示用户输入两个数
3)构建数组(m行n列)
4)调用初始化函数
5)调用打印数组的函数
初始化和打印都写成单独的函数。
*/
#include <stdio.h>
/**
* 给数组的所有元素的初始化
*
* @param m 行数
* @param n 列数
* @param a 传递的数组
*/
void init_arr(int m,int n,int a[m][n]){
for (int i =0; i<m; i++) {
for (int j =0; j<n; j++) {
a[i][j] = i*j;
}
}
}
/**
* 打印数组的所有元素的值
*
* @param m 行数
* @param n 列数
* @param a 传递的数组
*/
void print_arr(int m,int n,int a[m][n]){
//注意要先定义m和n,要不然数组a中m和n就无法使用。
for (int i =0; i<m; i++) {
for (int j =0; j<n; j++) {
printf("%d\t",a[i][j]);
}
printf("\n");
}
}
int main(int argc, const char * argv[]) {
int m,n;
printf("请输入两个数,构成一个数组,中间用逗号隔开!\n");
scanf("%d,%d",&m,&n);
int b[m][n];
// 传递值时,也要先传m和n的值,要不数组无法确定行数和列数
init_arr(m, n, b);
print_arr(m, n, b);
return 0;
}
《迷宫》伪代码实现
定义变量
1、定义变量,地图、存储用户输入的方向、小人的位置
2、先打印一遍地图
3、提示用户游戏玩法
循环控制
4、接受用户输入的方向
5、判断用户输入了什么方向
判断小人是否移动
6、判断小人是否能够移动
核心要知道小人下一个位置是否是路?
是路:
让小人开始移动,和空格交换。
重新记录小人的当前位置。
不是路:
什么也不干
判断小人是否走出来
判断y的值是否 == 5
提示走出迷宫。
break;游戏要结束
《迷宫》游戏优化后的代码
/*
《迷宫》游戏的优化,把内部多次使用的两个函数直接在外面定义成独立的函数。
使用的时候直接调用函数。
*/
#include <stdio.h>
//把地图数组的行数和列数定义成宏。
#define COL 6
#define ROW 6
/**
* 打印地图
*
* @param map1 地图的数组
*/
void print_map(char map1[COL][ROW]){
for (int i =0; i<COL; i++) {
for (int j =0; j<ROW; j++) {
printf("%c",map1[i][j]);
}
printf("\n");
}
}
/**
* 判断小人是否移动
*
* @param map 地图数组
* @param old_x 小人原来位置的X轴
* @param old_y 小人原来位置的Y轴
* @param new_x 小人要走位置的X轴
* @param new_y 小人要走位置的Y轴
*/
void personMove(char map[COL][ROW],int old_x,int old_y,int new_x,int new_y){
char temp;
temp=map[old_x][old_y];
map[old_x][old_y]=map[new_x][new_y];
map[new_x][new_y]=temp;
}
int main(int argc, const char * argv[]) {
char map[COL][ROW]={
{'#','#','#','#','#','#'},
{'#','0','#',' ',' ',' '},
{'#',' ','#','#',' ','#'},
{'#',' ',' ','#',' ','#'},
{'#','#',' ',' ',' ','#'},
{'#','#','#','#','#','#'}};
char dir;
char ch;
print_map(map);
//x和y是小人位置的下标
int x,y;
x=y=1;
printf("请输入一个方向:w或W表示上,s或S表示下,a或A表示左,d或D表示右,q或Q代表退出!\n");
while (1) {
scanf("%c",&dir);
scanf("%c",&ch);
switch (dir) {
case 'w':
case 'W':
if (map[x-1][y]==' ') {
personMove(map, x, y, x-1, y);
print_map(map);
x--;
}
break;
case 's':
case 'S':
if (map[x+1][y]==' ') {
personMove(map, x, y, x+1, y);
print_map(map);
x++;
}
break;
case 'A':
case 'a':
if (map[x][y-1]==' ') {
personMove(map, x, y, x, y-1);
print_map(map);
y--;
}
break;
case 'd':
case 'D':
if (map[x][y+1]==' ') {
personMove(map, x, y, x, y+1);
print_map(map);
y++;
}
break;
case 'q':
case 'Q':
return 0;
default:
break;
}
if (y==5) {
printf("恭喜你,你出来了!\n");
return 0;
}
}
return 0;
}