一维数组
一维数组的创建与初始化
数组–一组相同类型元素的集合;
数组的创建方式:type name [const_num]
int arr[8] //方括号里面一定是常量表达式 int arr[int n=8] 这样是错误的
char ch[10]
C99支持变长数组,就是说方括号里面可以是变量;
数组的初始化:在创建数组的同时给数组的内容一些合理初始值(初始化);
#include <stdio.h>
#include <string.h>
int main()
{
char chone[5] = { 'b','i','t' };
char chtwo[] = { 'b','i','t' };
char chthree[] = "bit";
char chfour[5]="bit";
printf("%d\n", strlen(chthree)); 3
printf("%d\n", strlen(chtfour)); 3
printf("%d\n", sizeof(chthree)); 4
printf("%d\n", sizeof(chfour)); 5
printf("%d %d %d %d", strlen(chone), sizeof(chone),strlen(chtwo), sizeof(chtwo));
// 3 5 58 3
return 0;
“str”:------s t r \0 类似于后面自己带\0
{‘s’‘t’‘t’}:------s t r
strlen遇到\0停止计数,不包括\0
注意:strlen在{}的情况下,如果确定在已知空间的大小里面计算字符串长度,是有几个算几个,但是如果不是在确定空间计算的话,那就是陈生一个随机数;
在“”这种情况下,直接计算字符个数就可以了;
sizeof计算需要的存储空间
注意:在确定内存空间里面,其数值就是内存空间大小;
在不确定内存空间里面,如果是“xx”类型,是字符数+1,如果是{},就是字符数的大小;
一维数组的使用
1.数组的使用下表来访问的;
2.数组的大小可以通过计算得到;int szcd=sizeof(arr)/sizeof(arr[0]);
%p:是按地址格式打印的;
%x:十六进制格式打印;
示例:打印数组元素的地址:
nt main()
{
int i = 0;
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
for (i = 0; i <=10; i ++ )
{
printf("%p\n", &arr[i]);
}
}
1.一维数组在内存中连续存放的;
2.随着数组下标的增长,地址是由低到高变化的;
数组名是数组首元素的地址:
*地址可以找到存放在该内存的数据;
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int* arrp = arr;
int i = 0;
for (i = 1; i <= 10; i++)
{
printf("%d\n", *arrp);
arrp++;
}
}
二维数组的创建与初始化
二维数组的创建:int arr[m][n]----创建一个m行n列的二维数组
二维数组的初始化:创建的同时给数组赋值;
示例:
int arr[3][4]={1,2,3,4,5,6,7,8,9,10,11,12} //自动排列
int arr[3][4]={1,2,3,4,5,6} //不完全初始化,后面补零
int arr[3][4]={{1,2}{3.4}{5,6}} //每一行当做一个一维数组,3可以省略
二维数组的行数可以省略,会自动分配;
二维数组的使用也是利用下标寻找的;
打印二维数组中的元素;
int main()
{
int arr[3][4] = { 0 };
int i = 0;
int j = 0;
for (i = 0; i < 3; i++)
{
for (j = 0; j < 4; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
return 0;
}
二维数组在内存中的存储也是连续的,跨行也是连续的—但实际上,应该也是一维形式存在的;

得出这样的结论有什么用:
1.因为数组在内存中的存储是连续的(一横排的形式),必须要知道第二行从哪里开始的,所以必须要知道列数,行数可以省略;
2.只要拿到首元素的地址,因为是连续的,就可以得到所有元素的内容;
#include <stdio.n>
int main()
{
int arr[3][4] = { 0 };
int* parr = &arr;
for (int i = 1; i <= 12; i++)
{
printf("%d ", *parr);
parr++;
if (i % 4 == 0) //多理解理解
{
printf("\n");
}
}
return 0;
}
注意:二维数组第一行的数组名是arr[0],二维数组第二行的数组名是arr[1]…
数组作为函数参数
在写代码的过程中,将数组作为参数传给函数;
示例:实现一个冒泡排序–函数将一个整形数组排序;
两两相邻的元素进行比较,可能的话,需要进行交换;
N个数字进行N-1趟冒泡排序;
#include <stdio.h>
#include <string.h>
void bubble_sort(int arry[],int szz) //升序冒泡
{
for (int i = 0; i <= szz; i++)
{
int temp = 0; // 设置一个临时变量
for (int j = 0; j < szz - 1-i; j++) //这才是一趟 ,-i是因为后面几个不用动;
{
if (arry[j] > arry[j + 1])
{
temp = arry[j];
arry[j] = arry[j + 1];
arry[j + 1] = temp;
}
}
}
}
int main()
{
int arr[9] = { 4,5,9,6,2,1,3,8,7 };
int sz = sizeof(arr) / sizeof(arr[0]); //确定趟数
bubble_sort(arr,sz); //实际传递的的是数组首元素地址;
for (int i = 0; i < 9; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
需要注意的是:传数组参数实际传递的是数组首位元素的首地址,无法在函数里面计算元素个数;
形参数组在函数内部无法求函数个数;
传数组参数实际传递的是数组首位元素的首地址,但有两个例外:
1.sizeof(数组名):此时数组名表示的是整个数组—计算的是整个数组的大小,单位是字节;
2.&数组名:此时数组名表示的也是整个数组—取出的是整个数组的地址(在数值上等于首元素地址)
代码示例:
int main()
{
int arr[10] = { 4,5,9,6,2,1,3,8,7,10 };
printf("%p\n", arr); //打印的是首元素地址
printf("%p\n", arr+1); //数组中下一个元素的地址
printf("%p\n", &arr); //打印的是数组地址
printf("%p\n", &arr+1); //数组之外下一个地址,等于原地址+4*10
return 0;
}

数组作为函数形参的时候:1.数组形式—2.指针形式
示例:三子棋—分模块实现(拆分代码)
test.c-----测试游戏的逻辑
game.h------关于游戏相关的函数声明,符号声明,头文件的包含
game.c------游戏相关函数的实现
#define _CRT_SECURE_NO_WARNINGS
#define ROW 5
#define COL 5
#include <stdio.h>
#include <string.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("**-----------------------------------------**\n");
printf("|| 菜 单 选 项 ||\n");
printf("||*****************************************||\n");
printf("||*****************************************||\n");
printf("|| ||\n");
printf("|| 一: 三 子 棋 游 戏 ||\n");
printf("|| ||\n");
printf("|| 二: 扫 雷 游 戏 ||\n");
printf("|| ||\n");
printf("|| 零: 退 出 游 戏 ||\n");
printf("|| ||\n");
printf("||*****************************************||\n");
printf("||*****************************************||\n");
printf("||-----------------------------------------||\n");
printf("\n");
}
initialize(char chessboardd[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
chessboardd[i][j] = ' ';
}
}
}
void displaychess(char chessboardd[ROW][COL], int row, int col)
{
for (int i = 0; i < row; i++)
{
for (int j = 0; j < col; j++)
{
printf(" %c ", chessboardd[i][j]);
if (j < col - 1) //最后一列不需要打印|
{
printf("|");
}
}
printf("\n");
//打印分行符
if (i < row-1)
{
int m = 0;
for (m = 0; m < col; m++)
{
printf("---");
if (m < col - 1) //打印几次的意思
{
printf("|");
}
}
}
printf("\n");
}
}
void playermove(char chessboardd[ROW][COL], int row, int col)
{
int x = 0;
int y = 0;
while (1)
{
printf("玩家下棋:");
printf("\n");
printf("\n");
printf("请输入坐标 x and y:");
scanf("%d %d", &x, &y);
printf("\n");
printf("\n");
//判断合法性
if ((x >= 1 && x <= row) && (y >= 1 && y <= col))
{
//正式下棋,判断坐标是否被占用
if (chessboardd[x-1][y-1] == ' ') //这里出过错,
{
chessboardd[x - 1][y - 1] = '*';
break;
}
else
{
printf("坐标已被占用,请重新输入!\n");
}
}
else
{
printf("非法坐标,请重新输入!\n");
}
}
}
void computermove(char chessboardd[ROW][COL], int row, int col)
{
printf("computer下棋:\n");
printf("\n");
while (1)
{
int x = rand() % row; //%一个数,产生的的数都在0----数-1
int y = rand() % col;
//判断坐标合法性
//正式下棋,判断坐标是否被占用
if (chessboardd[x][y] == ' ')
{
chessboardd[x][y] = '+';
break;
}
}
}
int isfull(char chessboardd[ROW][COL], int row, int col)
{
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (chessboardd[i][j] == ' ')
{
return 0;
}
}
}
return 1;
}
char iswin(char chessboardd[ROW][COL], int row, int col)
{
int i = 0;
//判断三行
for (i = 0; i < row; i++)
{
if (chessboardd[i][0] == chessboardd[i][1] && chessboardd[i][1] == chessboardd[i][2] && chessboardd[i][0] != ' ')
{
return chessboardd[i][0];
}
}
//判断三列
for (i = 0; i < col; i++)
{
if (chessboardd[0][i] == chessboardd[1][i] && chessboardd[1][i] == chessboardd[2][i] && chessboardd[0][i] != ' ')
{
return chessboardd[0][i];
}
}
//判断对角线
if (chessboardd[0][0] == chessboardd[1][1] && chessboardd[1][1] == chessboardd[2][2] && chessboardd[1][1] != ' ')
{
return chessboardd[1][1];
}
if (chessboardd[0][2] == chessboardd[1][1] && chessboardd[1][1] == chessboardd[2][0] && chessboardd[1][1] != ' ')
{
return chessboardd[1][1];
}
//判断平局
//棋盘满则返回1
int ret = isfull(chessboardd, ROW, COL);
if (ret == 1)
{
return 'Q';
}
//继续
return 'C';
}
char iswinpro(char chessboardd[ROW][COL], int row, int col) //判断几个子能赢?
{
// 思路为统计该行上的字符个数,如果为ROW或COL个那就是成功了
int count = 0;
//计算行中的 * 个数
int i = 0;
int j = 0;
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (chessboardd[i][j] == '*')
{
count++;
}
}
//一行结束了,获胜的话就返回,没有获胜就count归零,重新计算
if (count == row)
{
return '*';
break; //用加吗?
}
else
{
count = 0;
}
}
//计算行中的 + 个数
for (i = 0; i < row; i++)
{
for (j = 0; j < col; j++)
{
if (chessboardd[i][j] == '+')
{
count++;
}
}
//一行结束了,获胜的话就返回,没有获胜就count归零,重新计算
if (count == row)
{
return '+';
break; //用加吗?
}
else
{
count = 0;
}
}
//计算列中的 * 个数
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (chessboardd[j][i] == '*')
{
count++;
}
}
//一行结束了,获胜的话就返回,没有获胜就count归零,重新计算
if (count == col)
{
return '*';
break; //用加吗?
}
else
{
count = 0;
}
}
//计算列中的 * 个数
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (chessboardd[j][i] == '*')
{
count++;
}
}
//一行结束了,获胜的话就返回,没有获胜就count归零,重新计算
if (count == col)
{
return '*';
break; //用加吗?
}
else
{
count = 0;
}
}
//计算列中的 + 个数
for (i = 0; i < col; i++)
{
for (j = 0; j < row; j++)
{
if (chessboardd[j][i] == '+')
{
count++;
}
}
//一行结束了,获胜的话就返回,没有获胜就count归零,重新计算
if (count == col)
{
return '+';
break; //用加吗?
}
else
{
count = 0;
}
}
//判断 * 对角线1
int m = 0;
int n = 0;
for (m = 0, n = 0; m < row && n < col; m++, n++)
{
if (chessboardd[m][n] == chessboardd[0][0]) //问题就出现在一个;号
{
count++;
}
}
if (count == row)
{
return '*';
}
else
{
count = 0;
}
//判断 + 对角线1
int q = 0;
int w = 0;
for (q = 0, w = 0; q < row && w < col; q++, w++)
{
if (chessboardd[q][w] == '+')
{
count++;
}
}
if (count == row)
{
return '+';
}
else
{
count = 0;
}
//判断 * 对角线2
int e = 0;
int r = 0;
for (e = 0, r = col - 1; e < row && r >= 0 ; e++, r--)
{
if (chessboardd[e][r] == '*')
{
count++;
}
}
if (count == row)
{
return '*';
}
else
{
count = 0;
}
//判断 + 对角线2
int t = 0;
int y = 0;
for (t = 0, y = col - 1; t < row && y >= 0; t++, y--)
{
if (chessboardd[t][y] == '+')
{
count++;
}
}
if (count == row)
{
return '+';
}
else
{
count = 0;
}
//平局---调用isfull函数
int ssl = isfull(chessboardd, ROW, COL);
if (ssl == 1)
{
return 'Q';
}
//继续
return 'C';
}
void game_sanziqi()
{
//创建一个 ROW*COL 大小的棋盘----用来存放数据
int chessboard[ROW][COL];
//初始化棋盘,全部置 空格,显示为空
initialize(chessboard, ROW, COL); //传递参数的时候,行可以省略,列不可以省略
//打印棋盘
displaychess(chessboard, ROW, COL); //一维数组都可以省略
char ret = 0;
//下棋过程
while (1)
{
//玩家下棋
playermove(chessboard, ROW, COL);
//显示玩家下棋后的棋盘
displaychess(chessboard, ROW, COL);
ret = iswinpro(chessboard, ROW, COL);
if (ret != 'C')
{
break;
}
//电脑下棋--生成随机数
computermove(chessboard, ROW, COL);
//显示电脑下棋后的棋盘
displaychess(chessboard, ROW, COL);
ret = iswinpro(chessboard, ROW, COL);
if (ret != 'C')
{
break;
}
}
if (ret == '*')
{
printf("玩家 win !\n");
printf("\n");
displaychess(chessboard, ROW, COL);
}
else if(ret == '+')
{
printf("电脑 win !\n");
printf("\n");
displaychess(chessboard, ROW, COL);
}
else
{
printf("平 局 !!!\n");
}
Sleep(2000);
}
int main()
{
int key = 0;
srand((unsigned int)time(NULL)); //引用头文件stdlib与time
//可以一直玩游戏,采用do while循环语句
do
{
menu();
printf("请输入您选择的数字:");
scanf("%d", &key);
Sleep(1000);
switch (key)
{
case 1:
printf("\n");
printf("三子棋游戏正在加载中,请稍后...");
Sleep(2000);
printf("\n");
printf("\n");
game_sanziqi();
break;
case 2:
printf("\n");
//game_saopei();
printf("扫雷游戏正在加载中,请稍后...\n");
break;
default:
printf("\n");
printf("输入有误,请重新输入:\n");
}
printf("\n\n");
Sleep(1000);
}
while(key);
return 0;
}
示例:扫雷游戏的实现
#define _CRT_SECURE_NO_WARNINGS
#define ROW 9
#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("*************************************\n");
printf("********1. 扫 雷 游 戏 *******\n");
printf(" \n");
printf("********0. 退 出 游 戏 *******\n");
printf("*************************************\n");
printf("\n");
printf("\n");
}
void initialize(char schessboard[ROWS][COLS], int rows, int cols, char SET) //二维数组记得传递行列数
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
schessboard[i][j] = SET; //第一个棋盘初始化夫妇
}
}
}
void displaychessboard(char schessboard[ROWS][COLS], int row, int col)
{
//加上行标列标
for (int m = 0; m <= col; m++)
{
printf("%d ", m);
}
printf("\n");
for (int i = 0; i < row; i++)
{
printf("%d", i + 1);
for (int j = 0; j < col; j++)
{
printf(" %c", schessboard[i][j]); //棋盘并没有变化,只是打印的
}
printf("\n");
}
}
void setmine(char schessboard[ROWS][COLS], int row, int col)
{
int count = 10;
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
//只要不是雷,就可以放置一个雷
if (schessboard[x][y] == '0')
{
schessboard[x][y] = '1';
count--; //只有放置成功才算成功一次
}
}
}
void game_saolei()
{
//creat the chess board
//创建两个二维数组,一个存放布置好雷的信息,一个存放排查出雷的信息的信息
//9*9,应该创建11*11的数组,为了排查雷信息时不越界;
char schessboard1[ROWS][COLS]; //存放布置好雷的信息---
char schessboard2[ROWS][COLS]; //存放排查出雷的信息的信息--专门用来显示的
//initialize the chess board
initialize(schessboard1, ROWS, COLS,'0');//---------初始化为0---11*11都要初始化
initialize(schessboard2, ROWS, COLS,'*');//---------初始化为*---11*11都要初始化
//打印一下棋盘,只要打印 9*9 的棋盘即可
//其实第一个棋盘不用打印
printf("********* 扫 雷 底 盘 ********\n");
displaychessboard(schessboard1, ROW, COL); //schessboard1依然是11*11的数组
Sleep(2500);
printf("********* 扫 雷 显 盘 ********\n");
displaychessboard(schessboard2, ROW, COL);
//布置雷
setmine(schessboard1, ROW, COL); //给底盘布置雷
//显示布雷后的底盘
displaychessboard(schessboard1, ROW, COL); //schessboard1依然是11*11的数组
//排查雷
}
int main()
{
srand((unsigned int)time(NULL));
int key = 0;
do
{
menu();
printf("请输入要选择的数字:");
scanf("%d", &key);
printf("\n");
switch (key)
{
case 1:
printf("正在加载扫雷游戏,请稍等...\n");
printf("\n");
printf("\n");
game_saolei();
break;
case 0:
printf("正在退出游戏...");
break;
default:
printf("输入有误,请重新输入!");
break;
}
} while (key);
return 0;
}
示例:扫雷游戏
(int)count +48 = ‘ count ’ //整型变为字符型
#define _CRT_SECURE_NO_WARNINGS
#define ROW 9
#define COL 9
#define easecount 10
//#define COL 9
//#define COL 9
#define ROWS ROW+2
#define COLS COL+2
#include <stdio.h>
#include <windows.h>
#include <stdlib.h>
#include <time.h>
void menu()
{
printf("*************************************\n");
printf("********1. 扫 雷 游 戏 *******\n");
printf(" \n");
printf("********0. 退 出 游 戏 *******\n");
printf("*************************************\n");
printf("\n");
printf("\n");
}
void initialize(char schessboard[ROWS][COLS], int rows, int cols, char SET) //二维数组记得传递行列数
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
{
schessboard[i][j] = SET; //第一个棋盘初始化夫妇
}
}
}
void displaychessboard(char schessboard[ROWS][COLS], int row, int col) //行标列标弄清楚
{
//加上行标列标
for (int m = 0; m <= col; m++)
{
printf("%d ", m);
}
printf("\n");
for (int i = 1; i <= row; i++)
{
printf("%d", i );
for (int j = 1; j <= col; j++)
{
printf(" %c", schessboard[i][j]); //棋盘并没有变化,只是打印的
}
printf("\n");
}
}
void setmine(char schessboard[ROWS][COLS], int row, int col)
{
int count = 10;
while (count)
{
int x = rand() % 9 + 1;
int y = rand() % 9 + 1;
//只要不是雷,就可以放置一个雷
if (schessboard[x][y] == '0')
{
schessboard[x][y] = '1'; //算是字符1
count--; //只有放置成功才算成功一次
}
}
}
int get_number_schessboard1(char schessboardd1[ROWS][COLS], int x, int y)
{
return schessboardd1[x - 1][y - 1] +
schessboardd1[x - 1][y] +
schessboardd1[x - 1][y + 1] +
schessboardd1[x][y - 1] +
schessboardd1[x][y + 1] +
schessboardd1[x + 1][y - 1] +
schessboardd1[x + 1][y] +
schessboardd1[x + 1][y + 1] - 8 * '0';
//返回的是int类型的个数,字符1的 ASCII 值 - 字符0的ASCII值得到的是1整型值--然后全部相加
}
void findmine(char schessboardd1[ROWS][COLS], char schessboardd2[ROWS][COLS], int row, int col)
{
int num = 0; //排完雷以后,结束游戏的变量
while (num < row*col - easecount)
{
//输入排查的坐标
//是雷就被炸死了/////不是雷,显示周边几个雷
int x = 0;
int y = 0;
printf("请输入排查雷的坐标 x 和 y :");
printf("\n");
scanf("%d %d", &x, &y);
//判断输入坐标的合法性
if ((x >= 1 && x <= 9) && (y >= 1 && y <= 9))
{
if (schessboardd1[x][y] == '1')
{
printf("有雷,你被炸死了\n");
printf("\n");
//显示底盘,雷的分布
displaychessboard(schessboardd1, row, col);
printf("\n");
break;
}
else if (schessboardd1[x][y] == '0')
//不是雷,统计周围有几个雷
{
int number = get_number_schessboard1(schessboardd1, x, y);
//字符 0 的 ASCII 码值为48,字符1的ASCII值为49
schessboardd2[x][y] = number + '0';
displaychessboard(schessboardd2, row, col);
printf("\n");
num++;
}
}
else
{
printf("坐标不合法,请重新输入!\n"); //发现是一个循环
}
}
if (num == row * col - easecount)
{
printf("恭喜您排完所有的雷,获得胜利!!!\n");
displaychessboard(schessboardd1, ROW, COL);
}
}
void game_saolei()
{
//creat the chess board
//创建两个二维数组,一个存放布置好雷的信息,一个存放排查出雷的信息的信息
//9*9,应该创建11*11的数组,为了排查雷信息时不越界;
char schessboard1[ROWS][COLS]; //存放布置好雷的信息---
char schessboard2[ROWS][COLS]; //存放排查出雷的信息的信息--专门用来显示的
//initialize the chess board
initialize(schessboard1, ROWS, COLS,'0');//---------初始化为0---11*11都要初始化
initialize(schessboard2, ROWS, COLS,'*');//---------初始化为*---11*11都要初始化
//打印一下棋盘,只要打印 9*9 的棋盘即可
//其实第一个棋盘不用打印
//printf("********* 扫 雷 底 盘 ********\n");
//displaychessboard(schessboard1, ROW, COL); //schessboard1依然是11*11的数组
//Sleep(2500);
printf("********* 扫 雷 显 盘 ********\n");
displaychessboard(schessboard2, ROW, COL);
//布置雷
setmine(schessboard1, ROW, COL); //给底盘布置雷
//显示布雷后的底盘
//
displaychessboard(schessboard1, ROW, COL); //schessboard1依然是11*11的数组
printf("\n");
//排查雷
findmine(schessboard1, schessboard2, ROW, COL);//从底盘排查出来的信息,放到显盘中
}
int main()
{
srand((unsigned int)time(NULL));
int key = 0;
do
{
menu();
printf("请输入要选择的数字:");
scanf("%d", &key);
printf("\n");
switch (key)
{
case 1:
printf("正在加载扫雷游戏,请稍等...\n");
printf("\n");
printf("\n");
game_saolei();
break;
case 0:
printf("正在退出游戏...");
break;
default:
printf("输入有误,请重新输入!");
break;
}
} while (key);
return 0;
}
本文详细介绍了C语言中一维和二维数组的创建、初始化以及使用方法,包括数组的内存存储、初始化方式、长度计算、地址访问、以及在函数中的传递。此外,还探讨了如何通过数组实现冒泡排序,并展示了三子棋游戏的代码实现,以及扫雷游戏的基本流程。内容涵盖数组的基础知识和实际应用。
1万+

被折叠的 条评论
为什么被折叠?



