——Java培训、Android培训、iOS培训、.Net培训、期待与您交流! ——-
当xcode不提示输入的关键字时,按esc
二维数组
可以看做是一个特殊的一维数组,这个一维数组的每个元素又是一个一维数组
数据类型 数组名[第一维的长度(行)][第二维的长度(列)]
理解方法:
1. 特殊的一维数组,一维数组有两个元素[行数][列数]
2. 定义了[行数][列数]的一个矩阵
#include <stdio.h>
#define x = 6//宏定义后不能加;
int main(int argc, const char * argv[]) {
int a[2][3];
/*!
* 数组名不能和变量名同名
数组的长度可以是常量表达式
*/
int b[2][1+3];
int m = 3,n = 4;
int c[m][n];//Xcode特有的写法,其他编译器可能不支持
int arr[m];//可以使用宏定义
return 0;
}
二维数组初始化
//完全初始化和部分初始化
#include <stdio.h>
int main(int argc, const char * argv[]) {
int arr[2][3] = {{0,1,2},{3,4,5}};//2行3列,分段初始化:几行就分几个一维数组
//0 1 2
//3 4 5
int arr1[2][3] = {0,1,2,3,4,5};//计算机以3列的倍数进行截断
int arr2[][3] = {{0,1,2},{3,4,5}};//可以省略第一维
int arr3[][3] = {1,2,3,4,5,6};//计算机以3列的倍数进行截断
//部分初始化
int a[3][4] = {1};//后面11个全是0,一般情况下给数组初始化为全0
int a1[3][4] = {{1},{2},{3}};//没写的全是0,这种写法第一维可以省略a1[][4]
int a2[3][4] = {1,2,3,4};//第一行是1,2,3,4剩下全是0,这种写法第一维可以省略a2[][4]
//二维数组中第一维可以省略,第二维不能省
int a3[3][4];
a3[0][0] = 1;
a3[0][1] = 2;
return 0;
}
二维数组遍历
二维数组的元素也称为双下标变量
#include <stdio.h>
int main(int argc, const char * argv[]) {
int arr[4][3] = {1,2,3,4,5,6,2,3,4,4,3,2};
printf("arr[4][3] = {");
for (int i = 0; i < 4; i++) {//一维下标代表行数
printf("{");
for (int j = 0; j < 3; j++) {//二维下标代表列数,里层循环
if (j == 2) {
printf("%d",arr[i][j]);
}else
printf("%d,",arr[i][j]);
}
if (i == 3) {
printf("}");
}else
printf("},");
}
printf("}");
return 0;
}
二维数组存储
int m=3;
int a[m];
其他编译器里不允许,在其他编译器里只是给m先分了个4字节的内存空间,m的值再运行的时候才会查看到,所以编译不过去
xcode底层做了优化可以
存储方式:
1. 计算机给二维数组分配一块连续的存储空间
2. 数组名代表数组的首地址
3. 每一行存储方式从首地址还是一次存储
4. 每个元素占用相同的字节数
5. 并且数组中元素之间的地址是连续的
int a[2][2] = {1,2,3,4};
内存地址 内存单元
0x01 00000001 a[0][0]=1 a[0]
0x02 00000000
0x03 00000000
0x04 00000000
0x05 00000010 a[0][1]=2
0x06 00000000
0x07 00000000
0x08 00000000
0x09 00000011 a[1][0]=3 a[1]
0x0a 00000000
0x0b 00000000
0x0c 00000000
0x0d 00000100 a[1][1]=4
0x0e 00000000
0x0f 00000000
0x10 00000000
数组的首地址=第一行的地址=数组名=0x01=&a[0][0]
第二行的首地址=第二行第一个元素的地址=0x09=&a[1][0]
行间相差地址=列数*字节数
二维数组作为函数参数
1. 二维数组元素作为函数参数
score[1][2]此为变量,同变量作为函数参数,值传递
如:sum(score[1][0],score[2][3])都是变量作为函数参数
2. 二维数组名作为函数参数
score作为函数参数,同一维数组名作为函数参数,地址传递
print_arr(score)此时score是一个常量,保存的是数组的首地址
在函数里还是不能计算sizeof(score)的总长度,仍旧是计算的是8
#include <stdio.h>
void print_arr(int score[5][3]){
int len = sizeof(score);//仍旧和一维数组一样是8
printf("%d",len);
}
int main(int argc, const char * argv[]) {
int arr[5][3] = {{80,75,92},{61,65,71},{59,63,70},{85,87,90},{76,77,85}};
print_arr(arr);
return 0;
}
思考题:
从键盘上接收两个参数分别存放到m,n中,使用m和n构成数组:
1. 定义一个函数使用i*j初始化a[i][j]
2. 定义一个函数打印二维数组的每一个值
迷宫
伪代码的实现:
######
# ##
## #
# # #
# # ##
######
1. 定义变量
2. 初始化地图
3. 提示游戏玩法
4. 获取用户输入的方向数据
---要进行循环控制
5. 判断小人输入的方向
6. 判断小人是否能走
1. 如果是空,和小人位置互换,重新记录小人当前位置
2. 如果是墙小人不动
7. 如果y==5提示胜利
#include <stdio.h>
#define col 6//定义列
#define row 6//定义行
/*!
* @brief 打印地图
* @param map 地图的数组名
*/
void printMap(int map[row][col]){
for (int i = 0; i < row; i++) {
for (int j = 0; j < col; j++) {
printf("%c",map[i][j]);
}
printf("\n");
}
}
/*!
* @brief 实现了小人的移动
*
* @param map 地图数组
* @param oldX 小人位置原来X坐标
* @param oldY 小人位置原来Y坐标
* @param newX 小人将要走到的X坐标
* @param newY 小人将要走到的Y坐标
*
*/
void walk(int map[row][col],int oldX,int oldY,int newX,int newY){
char temp;
temp = map[oldX][oldY];
map[oldX][oldY] = map[newX][newY];
map[newX][newY] = temp;
}
int main(int argc, const char * argv[]) {
// 1. 定义变量
int map[row][col] = {
{'#','#','#','#','#','#'},
{'#','O','#','#',' ',' '},
{'#',' ','#','#',' ','#'},
{'#',' ',' ','#',' ','#'},
{'#','#',' ',' ',' ','#'},
{'#','#','#','#','#','#'},
};
char direction;//保存用户输入方向
int currentX = 1;
int currentY = 1;
char street = ' ';
// 2. 初始化地图
printMap(map);
// 3. 提示游戏玩法
printf("请控制小人移动:w、W上;s、S下;a、A左;d、D右;q退出\n");
// 4. 获取用户输入的方向数据
// ---要进行循环控制
while (1) {
scanf("%c",&direction);
getchar();//从缓冲区获取一个字符
// 5. 判断小人输入的方向
switch (direction) {
case 'w':
case 'W':
// 6. 判断小人是否能走
// 1. 如果是空,和小人位置互换,
if (map[currentX-1][currentY] == street) {
walk(map,currentX,currentY,currentX-1,currentY);
//重新记录小人当前位置
//如果能够移动,小人值一定变
currentX--;
}// 2. 如果是墙小人不动
break;
case 's':
case 'S':
// 6. 判断小人是否能走
// 1. 如果是空,和小人位置互换,
if (map[currentX+1][currentY] == street) {
walk(map,currentX,currentY,currentX+1,currentY);
//重新记录小人当前位置
//如果能够移动,小人值一定变
currentX++;
}// 2. 如果是墙小人不动
break;
case 'a':
case 'A':
// 6. 判断小人是否能走
// 1. 如果是空,和小人位置互换,
if (map[currentX][currentY-1] == street) {
walk(map,currentX,currentY,currentX,currentY-1);
//重新记录小人当前位置
//如果能够移动,小人值一定变
currentY--;
}// 2. 如果是墙小人不动
break;
case 'd':
case 'D':
// 6. 判断小人是否能走
// 1. 如果是空,和小人位置互换,
if (map[currentX][currentY+1] == street) {
walk(map,currentX,currentY,currentX,currentY+1);
//重新记录小人当前位置
//如果能够移动,小人值一定变
currentY++;
}// 2. 如果是墙小人不动
break;
case 'q':
case 'Q':
return 0;
break;
default:
break;
}
//重绘地图
printMap(map);
// 7. 如果y==5提示胜利
if(currentY == 5){
printf("WoW!You Win!\n");
break;
}
}
return 0;
}