学习视频: b站比特c语言就业班
数组
数组:一组相同类型元素的集合。
一.一维数组的创建和初始化。
创建
数组元素类型 数组名 常量表达式;
int arr[8];
c99支持变长数组,即可以是变量表达式。
数组可以完全初始化,也可以不完全初始化。
int arr[]={1,2,3,4,5}; ----->根据初始化内容确认数组内元素的个数。
char arr[5]={‘a’,‘b’,‘c’}; ------>未初始化位置:arr[4]=arr[5]=‘0’即‘\0’。等同于:char arr[5]=“abc”;
int arr[1]={ 1 };------>第一个初始化为1,其他默认填充为0。
[]内是:数组内元素个数。但数组的下标是从0开始的。
计算数组元素个数:
int sz=sizeof(arr)/size(arr[0]);
用数组占用的总字节数,除以一个数组元素占用的字节数。
因为数组存储的元素,因为类型不同,占用的字节不同。
存储
数组在内存中是连续存放的。
%p:打印地址。按地址的格式打印,十六进制。总共8位(或其倍数,编译器),1位十六进制代表4个二进制位,即32个二进制位大小。不满8位,以0填充。
%x:打印十六进制。不填充0。
小地址:低地址。随下标的增加,地址由低到高变化。
数组名:数组首元素地址。
输出
数组打印依靠循环
二.二维数组。
创建及初始化
按顺序初始化
按行初始化
二维数组行数可省略,根据初始化情况确定
存储
二维数组在内存中连续存储,换行也连续。
即:二维数组,只在思维时存在行列,但其在内存中连续。可以arr++连续输出。
数组作为函数参数:数组名是数组首元素的地址
例外:
- sizeof(arr):此处arr表示整个数组,计算整个数组的大小,单位B
- &arr:取整个数组的地址。与单个arr[]的长度不一样,这表示了整个数组存储空间的长度,其加1为加整个数组的长度
冒泡排序
原理:
数学思维:数学表达,i从1开始计数。
n个元素,共进行n-1趟冒泡排序
第一趟,有n个元素待排序,要比较n-1次
第二趟,有n-1个元素待排序,要比较n-2次
第i趟,有n-i+1个元素待排序,要比较n-i次。
总结:n个元素,共进行i=n-1趟冒泡排序。
第i趟排序,共有n-i+1个元素参与排序,需要比较j=n-i次
数组:数组的下标i从0开始计数。
n个元素,共进行n-2(i由1到0)趟冒泡排序
第0趟,有n个元素待排序,要比较n-1次
第1趟,有n-1个元素待排序,要比较n-2次
第i趟,有n-i个元素待排序,要比较n-i-1次。
总结:n个元素,共进行i<n-1趟冒泡排序。
第i趟排序,共有n-i个元素参与排序,需要比较j<n-i-1次(i由数学转到数组。j也由1到0,也需数学转到数组,如需比较2次,则j=0,1,j<2即可)
void bubble_sort(int arr[],int sz) {
//此处arr本质是指针
//int sz = sizeof(arr) / sizeof(arr[0]);
//若将arr的地址传进来再算数组长度,实际上算的是指针,即:4/4=1
int temp = 0;
//两两相邻的元素进行比较
for (int i = 0; i < sz-1; i++) {//趟数,每一趟
for (int j = 0; j < sz-i-1; j++) {//其中某一趟
if (arr[j+1] < arr[j]) {
temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
}
int main() {
int arr[] = { 9,8,7,6,5,4,3,2,1,0 };
int sz = sizeof(arr) / sizeof(arr[0]);
//冒泡排序
bubble_sort(arr,sz);//数组名:传递数组首元素的地址
for (int i = 0; i < 10; i++) {
printf("%d", arr[i]);
}
return 0;
}
三子棋
数组传参,形参2种:数组的大小行可以省略
1.数组形式:int arr[10] 或 int arr[]
2.指针形式:int *arr
test.c
//测试游戏的逻辑
//写函数主体
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"//引入:用户自定义头文件
void game() {
char ret='c';//接收游戏状态
//数组存储数据
char board[ROW][COL];
//初始化棋盘
IntiBoard(board, ROW, COL);
//打印棋盘
DisplayBoard(board, ROW, COL);
while (1) {
//玩家下棋
PlayMove(board, ROW, COL);
//判断玩家赢:
ret = IsWin(board, ROW, COL);
if (ret != 'c')//c:游戏继续
break;
//电脑下棋
ComputerMove(board, ROW, COL);
//判断电脑赢
ret = IsWin(board, ROW, COL);
if (ret != 'c')
break;
//平局
ret = IsWin(board, ROW, COL);
if (ret != 'c')
break;
}
if (ret == '*')
printf("你赢了!\n");
else if (ret == '#')
printf("电脑赢了!\n");
else
printf("平局!\n");
DisplayBoard(board, ROW, COL);
}
void menu() {
printf("******************\n");
printf("------0.play------\n");
printf("------1.exit------\n");
printf("******************\n");
}
int main() {
int input = 0;
srand((unsigned int)time(NULL));
do {
menu();
printf("选择:>");
scanf("%d", &input);
switch(input) {
case 1:
printf("游戏开始:\n");
game();
break;
case 0:
printf("游戏结束!");
break;
default:
printf("错误,重新选择:\n");
break;
}
} while (input);
return 0;
}
game.c
//函数实现
//写用户自定义函数
#define _CRT_SECURE_NO_WARNINGS
#include "game.h"
//初始化
void IntiBoard(char board[ROW][COL], int row, int col) {
int i = 0, j = 0;
for (; i < row; i++) {
for (j = 0; j < col; j++) {
board[i][j] = ' ';
}
}
}
//打印
void DisplayBoard(char board[ROW][COL], int row, int col) {
不通用
//int i = 0;
//for (; i < row; i++) {
// printf(" %c | %c | %c \n", board[i][0], board[i][1], board[i][2]);
// if(i < row - 1)
// printf("---|---|---\n");
//}
//通用
int i = 0, j = 0;
for (; i < row; i++) {
//打印内容
for (j = 0; j < col; j++) {
printf(" %c ", board[i][j]);
if (j < col - 1)
printf("|");
}
printf("\n");
//分隔
if (i < row - 1) {
for (j = 0; j < col; j++) {
printf("---");
if(j<col-1)
printf("|");
}
printf("\n");
}
}
}
//玩家下棋
void PlayMove(char board[ROW][COL], int row, int col) {
int x = 0, y = 0;
while (1) {
printf("玩家输入坐标:");
scanf("%d%d", &x, &y);
//判断坐标合法性
if (x > 0 && x <= row && y > 0 && y <= col) {
//判断坐标是否被占用
if (board[x - 1][y - 1] == ' ') {
board[x - 1][y - 1] = '*';
DisplayBoard(board, ROW, COL);
break;
}
else
printf("坐标被占用,重新输入:\n");
}
else {
printf("非法!重新输入:\n");
}
}
}
//电脑下棋
void ComputerMove(char board[ROW][COL], int row, int col) {
printf("电脑下:");
//生成坐标
//rand()%数:即取[0,数)
while (1) {
int x = rand()%row;//0,1,2
int y = rand()%col;//0,1,2
//判断占用
if (board[x][y] == ' ') {
board[x][y] = '#';
printf("\n");
DisplayBoard(board, ROW, COL);
break;
}
}
}
//判断棋盘满格
int IsFull(char board[ROW][COL], int row, int col) {
int i = 0, j = 0;
for (; i <= row; i++) {
for (j = 0; j <= col; j++) {
if (board[i][j] == ' ') {
return 0;//棋盘不满
}
}
}
return 1;//棋盘满了
}
//判断游戏状态
char IsWin(char board[ROW][COL], int row, int col) {
int i = 0, temp = 0;
for (; i < row; i++) {//判断3行
if (board[i][0] == board[i][1] && board[i][1] == board[i][2] && board[i][2] != ' ') {
return board[i][0];
}
}
for (i = 0; i < col; i++) {//判断3列
if (board[0][i] == board[1][i] && board[1][i] == board[2][i] && board[2][i] != ' ') {
return board[0][i];
}
}
//判断对角线
if (board[0][0] == board[1][1] && board[1][1] == board[2][2] && board[2][2] != ' ' || board[0][2] == board[1][1] && board[1][1] == board[2][0] && board[2][0] != ' ') {
return board[1][1];
}
//判断平局:棋盘满了
temp = IsFull(board, row, col);
if (temp) {
return 'q';
}
//继续
return 'c';
}
game.h
//函数声明
//符号声明、头文件包含、函数声明
//头文件包含
#include <stdio.h>
#include<time.h>//time
#include<stdlib.h>//srand,rand
//字符定义
#define ROW 3
#define COL 3
//声明函数
void IntiBoard(char board[ROW][COL], int row, int col);//初始化棋盘
void DisplayBoard(char board[ROW][COL], int row, int col);//输出棋盘
void PlayMove(char board[ROW][COL], int row, int col);//玩家下棋
void ComputerMove(char board[ROW][COL], int row, int col);//电脑下棋
char IsWin(char board[ROW][COL], int row, int col);//判断游戏状态