C语言初阶④(数组)知识点+编程作业(三子棋,冒泡排序)(上):https://developer.aliyun.com/article/1512982
2.3 二维数组的使用
同样是通过下标的方式,利用两个 for 循环打印
#include<stdio.h> int main() { int arr[3][4] = { 0 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("arr[%d][%d] = %d\n", i, j, arr[i][j]); } } return 0; }
二维数组在内存中的存储
#include<stdio.h> int main() { int arr[3][4] = { 0 }; for (int i = 0; i < 3; i++) { for (int j = 0; j < 4; j++) { printf("&arr[%d][%d] = %p\n", i, j, &arr[i][j]); } } return 0; }
运行结果如下:
仔细检视运行结果,我们可以分析到其实二维数组在内存中也是连续存存放的;
(并且可以理解是横着存放的,而不是像图一样竖着)
2.4 数组作为函数参数
数组名是首元素的地址(有两个例外)
例外1:
sizeof(数组名) 计算的是整个数组的大小
#include<stdio.h> int main() { int arr[10] = { 0 }; printf("%d\n", sizeof(arr));//40 return 0; }
例外2:
& 数组名 表示整个数组,取出的是整个数组的地址
(这时+1跳过的就是整个数组)
下面的练习至少冒泡排序看看(三子棋能看的话就看看,下一篇会实现一个扫雷的游戏)
课后练习:
- 冒泡排序(重点)
写一个bubble_sort函数,使其可以升序排序输入的10个整数。
冒泡排序核心思想:两两相邻元素进行比较,满足条件则交换;
① 先确认趟数;
② 写下一趟冒泡排序的过程;
③ 最后进行交换;
动图:
注意事项:
① int arr [ ] 本质上是指针,int * arr ;
② 数组传参时,实际上传递的是数组的首元素地址;
③ sz 变量不能在 bubble_sort内部计算,需要在外部计算好再传递进去;
#include<stdio.h> void bubble_sort(int arr[], int sz) { for (int i = 0;i < sz - 1;i++)// size-1表示:最后一趟区间中只剩余1个元素,该趟冒泡可以省略 { int flag = 1; for (int j = 0;j < sz - i - 1;j++) { if (arr[j] > arr[j + 1]) { int tmp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = tmp; flag = 0; // 如果本次冒泡中,元素没有交换,则本次开始冒泡时,数据已经有序了 //后面的冒泡可以不用进行了(此时flag为1,跳出循环) } } if (flag) { break; } } } int main() { int arr[10] = { 0 }; int sz = sizeof(arr) / sizeof(arr[0]); for (int i = 0;i < sz;i++) { scanf("%d", &arr[i]); } bubble_sort(arr, sz); printf("排序后:\n"); for (int i = 0;i < sz;i++) { printf("%d ", arr[i]); } return 0; }
2. 数组操作
【题目内容】
创建一个整形数组,完成对数组的操作
- 实现函数init() 初始化数组为全0
- 实现print() 打印数组的每个元素
- 实现reverse() 函数完成数组元素的逆置。
要求:自己设计以上函数的参数,返回值。
#include<stdio.h> void init(int arr[], int sz) { for (int i = 0;i < sz;i++) { arr[i] = 0; } } void print(int arr[], int sz) { for (int i = 0;i < sz;i++) { printf("%d ", arr[i]); } printf("\n"); } void reverse(int arr[], int sz) { int left = 0, right = sz - 1; while(left < right) { int tmp = arr[left]; arr[left] = arr[right]; arr[right] = tmp; left++; right--; } } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9,10 }; int sz = sizeof(arr) / sizeof(arr[0]); printf("逆序和初始化前:"); print(arr, sz); printf("逆序后:"); reverse(arr, sz); print(arr, sz); init(arr, sz); printf("初始化后:"); print(arr, sz); return 0; }
3. 交换数组
【题目内容】
将数组A中的内容和数组B中的内容进行交换。(数组一样大)
#include<stdio.h> void print(int arr[], int sz) { for (int i = 0;i < sz;i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr1[] = { 0,1,2,3,4 }; int arr2[] = { 5,6,7,8,9 }; int sz = sizeof(arr1) / sizeof(arr1[0]); printf("交换前:\n"); print(arr1, sz); print(arr2, sz); for(int i=0;i<sz;i++) { int tmp = arr1[i]; arr1[i] = arr2[i]; arr2[i] = tmp; } printf("交换后:\n"); print(arr1, sz); print(arr2, sz); return 0; }
4. 三子棋
先把菜单和大纲列出来,后面在实现三子棋游戏的函数。
#include<stdio.h> void menu() { printf("*****************************************\n"); printf("************** 1. paly **************\n"); printf("************** 0. exit **************\n"); printf("*****************************************\n"); } int main() { int input = 0; do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: printf("三子棋游戏\n"); break; case 0: printf("退出游戏\n"); break; default: printf("输入错误;重新输入:\n"); break; } } while (input); }
然后就看着game里面的函数一个个实现了,想说的都放在代码注释了
test.c(游戏的测试)
#include"game.h" void menu() { printf("*****************************************\n"); printf("************** 1. paly **************\n"); printf("************** 0. exit **************\n"); printf("*****************************************\n"); } void game() { //数据存储,二维数组 char board[ROW][COL] = { 0 }; //棋盘:chessboard 行:row,列:column,defind定义的符号通常大写用来区分 //符号和函数的定义放在game.h //初始化棋盘成空格 init_board(board, ROW, COL); //打印棋盘 print_board(board, ROW, COL); //ret==什么,游戏就结束了 //玩家赢 - '*' //电脑赢 - '#' //平局 - 'g' //继续 - 'r' //落子和判断输赢 char ret = 0; while(1) { //玩家下棋: player_move(board, ROW, COL); print_board(board, ROW, COL); ret=is_win(board, ROW, COL); if (ret != 'r') { break; } //电脑下棋: computer_move(board, ROW, COL); print_board(board, ROW, COL); ret = is_win(board, ROW, COL); if (ret != 'r') { break; } } if (ret == '*') { printf("恭喜你赢了!\n"); } else if (ret == '#') { printf("恭喜电脑赢了emm\n"); } else { printf("平局 gg!\n"); } } int main() { //随机数种子 srand((unsigned int)time(NULL)); int input = 0; do { menu(); printf("请选择:"); scanf("%d", &input); switch (input) { case 1: game(); break; case 0: printf("退出游戏\n"); break; default: printf("输入错误;重新输入:\n"); break; } } while (input); return 0; }
game.h(放置函数的声明)
#include<stdio.h>//头文件的包含 #include<time.h>//time() #include<stdlib.h>//rand() #define ROW 3 //可以把两个3换成任意数字 #define COL 3 //能下,但是判断输赢写死了,只能判断3*3的 //初始化成空格棋盘函数 void init_board(char board[ROW][COL],int row,int col); //打印棋盘函数 void print_board(char board[ROW][COL], int row, int col); //玩家下棋函数 void player_move(char board[ROW][COL], int row, int col); //电脑随机下棋函数 void computer_move(char board[ROW][COL], int row, int col); //判断棋盘是否满函数(平局)(在判断输赢函数内使用) int is_full(char board[ROW][COL], int row, int col); //判断输赢函数 char is_win(char board[ROW][COL], int row, int col);
game.c(放置函数的实现)
#include"game.h" //初始化成空格棋盘函数 void init_board(char board[ROW][COL], int row, int col) { for (int i = 0;i < ROW;i++) { for (int j = 0;j < COL;j++) { board[i][j] = ' '; } } } //打印棋盘函数 void print_board(char board[ROW][COL], int row, int col) { for (int i = 0;i < row;i++) { //打印数据和竖线 for (int j = 0;j < col;j++) { printf(" %c ", board[i][j]); if (j < col - 1) printf("|"); } printf("\n"); //打印横线 if (i < row - 1)//比行少一段 { for (int j = 0;j < col;j++) { printf("---"); //和列一样 if (j < col - 1) { printf("|");//比列少一个 } } printf("\n"); } } } //玩家下棋函数 void player_move(char board[ROW][COL], int row, int col) { int x = 1, y = 1; printf("请输入你下的坐标(行 列,空格分开):\n"); while(1) { scanf("%d %d", &x, &y); if (x >= 1 && x <= row && y >= 1 && y <= col) { if (board[x - 1][y - 1] == ' ') { board[x - 1][y - 1] = '*'; printf("玩家下:\n"); break; } else { printf("坐标已被占用,请重新输入:\n"); } } else { printf("坐标非法,重新输入:\n"); } } } //电脑随机下棋函数 void computer_move(char board[ROW][COL], int row, int col) { printf("电脑下:\n"); int x = 1, y = 1; while(1) { x = rand() % row; y = rand() % col; if (board[x][y] == ' ') { board[x][y] = '#'; break; } } } //判断棋盘是否满函数(平局)(在判断输赢函数内使用) int is_full(char board[ROW][COL], int row, int col) { for (int i = 0;i < row;i++) { for (int j = 0;j < col;j++) { if (board[i][j] == ' ') { return 0; } } } return 1; } //判断输赢/平局函数 char is_win(char board[ROW][COL], int row, int col) { //判断行 for (int i = 0; i < row; i++) { if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][1] != ' ') { return board[i][1]; } } //判断列 for (int i = 0; i < col; i++) { if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[1][i] != ' ') { return board[1][i]; } } //两条对角线 if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[1][1] != ' ') { return board[1][1]; } if (board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[1][1] != ' ') { return board[1][1]; } //判断平局 if (is_full(board, row, col) == 1)//判断棋盘是否满函数 { return 'g'; } //继续 return 'r'; }
本篇完。