【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)

news2024/11/27 12:58:31

 [导读]本系列博文内容链接如下:

【C++】做一个飞机空战小游戏(一)——使用getch()函数获得键盘码值

【C++】做一个飞机空战小游戏(二)——利用getch()函数实现键盘控制单个字符移动
【C++】做一个飞机空战小游戏(三)——getch()函数控制任意造型飞机图标移动

【C++】做一个飞机空战小游戏(四)——给游戏添加背景音乐(多线程技巧应用)

【C++】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置)

【C++】做一个飞机空战小游戏(六)——给两架飞机设置不同颜色(cout输出彩色字符、结构体使用技巧)

在第五节【C++】做一个飞机空战小游戏(五)——getch()控制两个飞机图标移动(控制光标位置)中实现了通过键盘控制两架飞机的效果,但是两架飞机颜色造型一样,很难区分,所以需要给两架飞机选用不同的颜色、不同造型,这样就好辨别了。

本节之前飞机只有位置、造型两个属性,所以可以用独立的变量来声明即可。随着程序设计的深入,飞机的属性越来越多,就需要构造飞机的结构体,把各项属性都放到飞机结构体中。这样,可以减少声明变量的个数,减少自定义函数的形参。使程序的逻辑性更清晰,代码量更少。

目录

一、结构体

(一)定义

(二)使用结构体需要注意几点

1、结构体是一种数据类型

2、结构体需要先构造后使用

3、结构体的成员也可以是结构体类型数据

4、结构体是可以扩展的

(三)参考博文

二、本文用到的结构体

(一)位置坐标结构体

1、构造形式

2、功能

3、用途

(二)飞机结构体

1、构造形式

2、功能

3、用途

三、优化程序

(一)声明数据类型

1、声明全局结构体数组

2、优化按键指令存储枚举变量

(二)已有自定义函数的优化

1、形参数量减少

2、返回型函数类型减少

(三)新增自定义函数

1、新增获取按键键值线程函数

2、新增彩色字符输出函数

3、新增隐藏光标函数

(四)优化后的程序代码

1、主函数

2、头文件control_plane.h

3、库函数control_plane.cpp

五、运行效果


一、结构体

(一)定义

结构体就是一个可以包含不同数据类型的一个结构,它是一种可以自己定义的数据类型,它的特点和数组主要有两点不同,首先结构体可以在一个结构中声明不同的数据类型。第二,相同结构的结构体变量是可以相互赋值的,而数组是做不到的,因为数组是单一数据类型的数据集合,它本身不是数据类型(而结构体是),数组名称是常量指针,所以不可以做为左值进行运算,所以数组之间就不能通过数组名称相互复制了,即使数据类型和数组大小完全相同。

(二)使用结构体需要注意几点

1、结构体是一种数据类型

结构体就是把若干种数据类型的放到一起,构造了一个新的数据类型。所以关于结构体变量的操作和其他的数据类型有好多相似的地方。

声明变量的过程实际就是到内存中划分一片存储空间给这个变量使用,变量名就是这片空间的标记符号,不同的数据类型所占空间不同,所以声明变量的时候需要明确数据类型。结构体变量的声明后,其获得的空间就是结构体内所有成员所需的空间。

2、结构体需要先构造后使用

结构体是用户自己根据需求定制的一种数据类型,不是系统就有的数据类型,所以必须先构造一个结构体数据类型,然后再用这个结构体数据类型声明变量,再对变量进行其他的操作。

3、结构体的成员也可以是结构体类型数据

也就是结构体是可以嵌套的,还可以多层嵌套。

4、结构体是可以扩展的

结构体构造完成后,还可以进行增加、减少或者改变成员。

(三)参考博文

关于结构体基础知识介绍的博文有很多,本文不在详细介绍,具体内容可以参考以下博文:

c语言基础语法六——结构体(完结)_卖酒的小码农的博客-CSDN博客

二、本文用到的结构体

(一)位置坐标结构体

1、构造形式

//定义坐标结构体 
typedef struct{
	int x;
	int y;
} Location;

2、功能

这个结构体数据类型的功能是用来存放屏幕上点的坐标。Location为结构体类型名称,其有两个整形的成员:x,y,分别代表x坐标和y坐标。

3、用途

可以用来存储飞机、炮弹、和其他字符信息要显示的位置。

(二)飞机结构体

1、构造形式

//定义飞机结构体 
typedef struct{
	Location location;	
	int color;
	int icon;
	direction_cmd keycmd;
}Plane;

2、功能

这个结构体数据类型的功能是用来存储飞机属性信息的。Plane为结构体类型名称,其有1个Location类型的成员location,用来存储飞机坐标;1个int型的成员color,用来存储飞机的颜色;1个int型的成员icon,用来存储飞机的造型;1个direction_cmd形的成员keycmd,用来存储飞机接收到的键盘指令。

注意:direction_cmd是本例定义的一个枚举型的数据类型,其内部暂时存储了飞机所能接受的"上、下、左、右"和“无”4个键盘指令名称。

typedef  enum {none_cmd,up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd; 

3、用途

这个结构体的用途就是声明飞机,声明后可以通过改变其成员(属性)的值,定制出风格不同的飞机。还可以在程序里根据属性值的不同做出不同的反应,呈现不同的状态,具有不同的信息,做出不同的动作。

三、优化程序

声明了飞机结构体之后,位置信息、按键指令信息、飞机图标信息、颜色信息都在结构体之内了,以上4个信息都不用单独声明了,声明一个结构体就都包含了。另外,两个飞机就可以用一个结构体数组来表示,飞机的序号可以用数组的角标区分。

(一)声明数据类型

1、声明全局结构体数组

声明全局Plane plane[num_plane],用于存放和传递各种信息。采用数组方式,给赋值带了很大便利,减少代码量。

#define num_plane 2	//飞机架数
extern Plane plane[num_plane];

2、优化按键指令存储枚举变量

typedef  enum {none_cmd,up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd; 

枚举变量里增加“none_cmd”选项,方向指令只保留一组,不再区分是哪个飞机的指令,使指令更加通用。

(二)已有自定义函数的优化

1、形参数量减少

目前形参只有Plane一个结构体类型了。

//声明刷新飞机位置函数
void show_plane(Plane plane);
 
//获取键盘指令
void key(void);
 
//更新每架飞机的坐标
void plane_location_update(void); 

//初始化函数(设置飞机的颜色、形状) 
void init(void);

2、返回型函数类型减少

因为函数运行后的结果都存在全局Plane结构体中了,所以函数不需要各种返回结果。

(三)新增自定义函数

1、新增获取按键键值线程函数

之前的按键获取函数在主线程中,按键按下后再执行位置更新和画面更新,如果没有按键按下,主程序就一直处于等待按键按下的状态,后边的程序都执行不了。游戏后边需要增加炮弹的功能,需要一直更新炮弹的位置,所以需要把按键程序单放到一个线程里。主线程里只保留位置更新和画面更新功能。

//定义获取按键线程函数
void* thread_key(void* arg);
void getkey();

2、新增彩色字符输出函数

//输出有颜色字符函数
template<typename T>	//T表示任何可以被cout输出的类型 
void ColorCout(T t, const int ForeColor = 7, const int BackColor = 0);

3、新增隐藏光标函数

//隐藏光标函数
HANDLE han = GetStdHandle(-11);
void hide(){
	CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = 0;
	cursor.dwSize = 1;
	SetConsoleCursorInfo(han,&cursor);
}

隐藏光标函数,可以不再界面上不显示光标所在位置,更新画面时不会出现光标,减少闪烁感。

(四)优化后的程序代码

1、主函数

#include "control_plane.h"
using namespace std; 

Plane plane[num_plane];
 
int main(int argc, char** argv) {	
	init();	//初始化					 
 
	bgmusic();//播放背景音乐
	getkey();
	
	while(1)					//循环等待键盘指令 
	{
		for(int i=0;i<num_plane;i++)
		{
			show_plane(plane[i]);	//刷新飞机1图标
		}
		if(plane[0].keycmd!=none_cmd ||plane[1].keycmd!=none_cmd)
		{
			system("cls");
		}
		
		plane_location_update();	
	}
	return 0; 	
}

2、头文件control_plane.h

#ifndef CONTROL_PLANE_H
#define CONTROL_PLANE
#include <iostream>
#include <string>
#include<stdlib.h>
#include<windows.h>
#include <pthread.h>//导入线程头文件库
#include <mmsystem.h> //导入声音头文件库
#pragma comment(lib,"winmm.lib")//导入声音的链接库
#define _CRT_SECURE_NO_WARNINGS 
using namespace std;
 
#define t_b 0  	//图形显示区域上侧边界 
#define l_b 0	//图形显示区域左侧边界
#define r_b 100	//图形显示区域右侧边界
#define b_b 20	//图形显示区域下侧边界

#define num_plane 2	//飞机架数 

 
//定义飞机造型 
const string icon_plane1[]={"    ■","■  ■  ■","■■■■■","■  ■  ■","    ■","  ■■■"};
const string icon_plane2[]={"    ■","■  ■  ■","■■■■■","    ■","  ■■■","■■■■■"};
 
//定义坐标结构体 
typedef struct{
	int x;
	int y;
} Location;

 
//定义移动方向命令枚举类型 
typedef  enum {none_cmd,up_cmd,down_cmd,left_cmd,right_cmd} direction_cmd; 

//定义飞机结构体 
typedef struct{
	Location location;
	int color;
	int icon;
	direction_cmd keycmd;
}Plane;

extern Plane plane[num_plane];
 
//声明刷新飞机位置函数
void show_plane(Plane plane);
 
//获取键盘指令 
void key(void);
 
//更新所有飞机坐标
void plane_location_update(void);
 
//初始化函数 
void init(void);

//播放背景音乐线程 
void* thread_bgmusic(void* arg);
void play_bgmusic();
void bgmusic();

//获取按键指令线程
void* thread_key(void* arg);
void getkey();

//输出彩色字符函数
template<typename T>	//T表示任何可以被cout输出的类型 
void ColorCout(T t, const int ForeColor = 7, const int BackColor = 0);
 
#endif

3、库函数control_plane.cpp

#include <iostream>
#include "conio.h"
#include <string>
#include "control_plane.h"
#include<windows.h>
using namespace std;


//彩色输出函数
template<typename T>	//T表示任何可以被cout输出的类型
void ColorCout(T t, const int ForeColor = 7, const int BackColor = 0)
{
	//	0 = 黑色	1 = 蓝色	 2 = 绿色	 3 = 浅绿色		 4 = 红色	 5 = 紫色	 6 = 黄色	 7 = 白色
	//	8 = 灰色	9 = 淡蓝色	10 = 淡绿色	11 = 淡浅绿色	12 = 淡红色	13 = 淡紫色	14 = 淡黄色	15 = 亮白色
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), ForeColor + BackColor * 0x10);
	cout << t;
	SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 7);
}


//隐藏光标函数
HANDLE han = GetStdHandle(-11);
void hide(){
	CONSOLE_CURSOR_INFO cursor;
	cursor.bVisible = 0;
	cursor.dwSize = 1;
	SetConsoleCursorInfo(han,&cursor);
}
 
//初始化函数 
void init(void)
{
	plane[0].location={2*r_b/3,b_b};
	plane[1].location={r_b/3,b_b};
	
	plane[0].color=1;
	plane[1].color=2;
	
	plane[0].icon=1;
	plane[1].icon=2;
	
	for(int i=0;i<num_plane;i++)
		{

			system("cls");
			show_plane(plane[i]);	//刷新飞机图标
			plane[i].keycmd=none_cmd;		
		}
	hide();//隐藏光标
}
 


//********************************************************************************
 //以下三个函数为获得按键指令线程函数 
//********************************************************************************

void* thread_key(void* arg)
{
	while(1)
	{
		key();			//获取按键指令
	}
}
void getkey()
{
	pthread_t tid; 
  	pthread_create(&tid, NULL, thread_key, NULL);
}

//获取键盘指令函数
void key(void)
{
	int key_value1,key_value2;			//声明两个变量,存放键值 
	key_value1=getch();					//先获取第一个码值 
	
	
	if(key_value1==224)					//如果第一个码值为224,则进行第二个码值的判断 
		{
			key_value2=getch();			//先获取第二个码值
			
			switch(key_value2)
			{
				case 72:				//向上方向键 
					plane[0].keycmd=up_cmd;
					break;
				case 80:				//向下方向键
					plane[0].keycmd=down_cmd;
					break;
				case 75:				//向左方向键
					plane[0].keycmd=left_cmd;
					break;
				case 77:				//向右方向键
					plane[0].keycmd=right_cmd;
					break;
			}
			
		}
		else
		{
			switch(key_value1)
			{
				case 119:				//向上方向键 
					plane[1].keycmd=up_cmd;
					break;
				case 115:				//向下方向键
					plane[1].keycmd=down_cmd;
					break;
				case 97:				//向左方向键
					plane[1].keycmd=left_cmd;
					break;
				case 100:				//向右方向键
					plane[1].keycmd=right_cmd;
					break;
			}
		}		
}


//********************************************************************************
 //以下三个函数为播放背景音乐功能 
//********************************************************************************
 
 //播放一遍背景音乐 
 void play_bgmusic() {  
 
	mciSendString(TEXT("open hero.mp3 alias s1"),NULL,0,NULL);
	mciSendString(TEXT("play s1"),NULL,0,NULL);
 
	Sleep(153*1000);//153*1000意思是153秒,是整首音乐的时长 
	mciSendString(TEXT("close S1"),NULL,0,NULL); 
  
}
 
//循环播放音乐线程函数 
void* thread_bgmusic(void* arg) //
{ 
  while(1)
  {  	
  	play_bgmusic();
  }
} 
 
//创建音乐播放线程,开始循环播放音乐 
void bgmusic()
{
	pthread_t tid; 
  	pthread_create(&tid, NULL, thread_bgmusic, NULL);
}
 
 
void gotoxy(int x, int y) {
	COORD pos = { x,y };
	HANDLE hOut = GetStdHandle(STD_OUTPUT_HANDLE);//获取标准输出设备句柄
	SetConsoleCursorPosition(hOut, pos);//两个参数分别指定哪个窗口,具体位置
}
 
 
//飞机图标刷新函数 
void show_plane(Plane plane)		//预先定义字符定位显示函数,x是列坐标,y是行坐标,原点(x=0,y=0)位于屏幕左上角 
{
	int x,y;
	int i,j;
	int rows;
	x=plane.location.x;
	y=plane.location.y;
	
	switch(plane.icon)
	{
		case 1://第一种造型 
			rows=sizeof(icon_plane1)/sizeof(icon_plane1[0]);
			for(i=0;i<rows;i++)				 
			{
				gotoxy(x,y+i);				
				ColorCout(icon_plane1[i],plane.color);
			}
			break;
		case 2://第二种造型 
			rows=sizeof(icon_plane2)/sizeof(icon_plane2[0]);
			for(i=0;i<rows;i++)				
			{
				gotoxy(x,y+i);				
				ColorCout(icon_plane2[i],plane.color);
			}
			break;				
	}
}


 
 
//更新两个飞机的坐标 
void plane_location_update(void)
{ 	
	for(int i=0;i<2;i++)
	{
		if(plane[i].keycmd!=none_cmd) 
		{
			int x,y;
 			x=plane[i].location.x;
 			y=plane[i].location.y;
 			switch(plane[i].keycmd)
			{
				case up_cmd:
					y--;				//字符上移一行,行值y减1
					if(y<t_b)			//限定y值最小值为0
					{
						y=t_b;
					}
					break;
				case down_cmd:
					y++;				//字符下移一行,行值y加1
					if(y>b_b)			//限定y高度 
					{
						y=b_b;
					}
					break;
				case left_cmd:
					x--;				//字符左移一列,列值x减1
					if(x<l_b)
					{
						x=l_b;			//限定x最小值为0; 
					}
					break;
				case right_cmd:
					x++;				//字符右移一列,列值x加1
					if(x>r_b)
					{
						x=r_b;			//限定x宽度
					}
					break;
				
			}
			plane[i].location.x=x;
 			plane[i].location.y=y;
 			plane[i].keycmd=none_cmd;	
		}
					
	} 		
} 

五、运行效果

(未完待续) 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/844203.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

docker安装neo4j

参考文章&#xff1a; 1、Mac 本地以 docker 方式配置 neo4j_neo4j mac docker_Abandon_first的博客-CSDN博客 2、https://www.cnblogs.com/caoyusang/p/13610408.html 安装的时候&#xff0c;参考了以上文章。遇到了一些问题&#xff0c;记录下自己的安装过程&#xff1a; …

ABP:BackgroundJob/Quartz 结合业务实现定时发送

需求描述&#xff1a;我在使用ABP框架&#xff0c;现在想实现一个定时任务功能&#xff0c;描述&#xff1a;每天八点调用特定接口&#xff0c;调用n次后结束不再调用。相关的数据都来自于一个特定的实体“fuck”。 解决方案&#xff1a;可以使用ABP框架自带的定时任务功能来实…

浅聊Cesium.js 后处理原理

浅聊Cesium.js 后处理原理 使用例子: const stages viewer.scene.postProcessStages;const silhouette Cesium.PostProcessStageLibrary.createSilhouetteStage() silhouette.enabled true; stages.add(silhouette);silhouette.uniforms.color Cesium.Color.LIME;涉及到相…

linux内网穿透应用场景有哪些?快解析有什么用处?

随着网络技术的不断发展&#xff0c;无论是工作上还是在生活中人们对网络的依赖和需求越来越高。Linux内网穿透作为一种创新的解决方案&#xff0c;为我们提供了无限可能。 首先我们了解一下Linux操作系统。Linux是一套免费使用和自由传播的类Unix操作系统&#xff0c;是一个基…

流量卡线上销户全教程,剩余的话费还有可能给你退回来!

线上就可以注销手机卡你知道吗&#xff1f;目前三大运营商都开通了线上销户业务了&#xff0c;而且用不完的话费还可以退回来&#xff0c;建议大家点赞收藏起来&#xff0c;以免有需要的时候找不到了&#xff0c;大家好&#xff0c;我是流量卡葫芦妹。 ​ OK&#xff0c;不多废…

进程、线程、协程

目录 进程、线程、协程的概念 进程、线程、协程的上下文切换 使用协程的注意事项 协程与线程、进程的区别 进程、线程、协程的概念 进程&#xff1a; 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程…

redis原理 1:鞭辟入里 —— 线程 IO 模型

Redis 是个单线程程序&#xff01;这点必须铭记。 也许你会怀疑高并发的 Redis 中间件怎么可能是单线程。很抱歉&#xff0c;它就是单线程&#xff0c;你的怀疑暴露了你基础知识的不足。莫要瞧不起单线程&#xff0c;除了 Redis 之外&#xff0c;Node.js 也是单线程&#xff0c…

封装上传文件组件(axios,onUploadProgress,取消请求)

目录 定时模拟进度条 方法 A.axios B.xhr 取消请求​​​​​​​ 完整代码 A.自定义上传组件 B.二次封装组件 情况 增加cancelToken不生效&#xff0c;刷新页面 进度条太快->设置浏览器网速 定时模拟进度条 startUpload() {if (!this.file) return;const totalS…

AWS 中文入门开发教学 49- S3 - 区域间复制

知识点 S3 存储桶内容在全球区域间进行复制官网 https://docs.aws.amazon.com/zh_cn/AmazonS3/latest/userguide/replication.html 实战演习 在东京区建立存储桶 Name: woyaofuzhi启用版本控制(完成区域间复制必须开启版本控制) 在新加坡区建立存储桶 Name: woyaofuzhibac…

科技感响应式管理系统后台登录页ui设计html模板

做了一个科技感的后台管理系统登录页设计&#xff0c;并且尝试用响应式布局把前端html写了出来&#xff0c;发现并没有现象中的那么容易&#xff0c;chrome等标准浏览器都显示的挺好&#xff0c;但IE11下面却出现了很多错位&#xff0c;兼容起来还是挺费劲的&#xff0c;真心不…

【Python从入门到进阶】31、使用JSONPath解析淘票票网站地区接口数据

接上篇《30、JSONPath的介绍和使用》 上一篇我们介绍了JSONPath的基础和具体使用&#xff0c;本篇我们来具体使用JSONPath&#xff0c;来解析淘票票网站的地区接口数据。 一、引言 1、JsonPath的作用和用途&#xff1f; JsonPath是一种用于在JSON数据中进行查询和提取的表达…

Python测试框架pytest:测试用例、查找子集、参数化、跳过

Pytest是一个基于python的测试框架&#xff0c;用于编写和执行测试代码。pytest主要用于API测试&#xff0c;可以编写代码来测试API、数据库、UI等。 pytest是一个非常成熟的全功能的Python测试框架&#xff0c;主要有以下几个优点&#xff1a; 简单灵活&#xff0c;容易上手。…

3D数字孪生技术在工业制造中的应用

工业生产是现代工业生产和城市化建设的重要组成部分&#xff0c;工业生产逐渐批量化和自动化&#xff0c;利用数字孪生3D可视化技术对工厂生产的环境、设备、管道和仪表等元素在虚拟世界中模拟和重建&#xff0c;实现工业生产的管理、规划、设计和运营数字化可视化管理。 提高生…

利用openTCS实现车辆调度系统(五)openTCS WEB接口及扩展

上一篇介绍了RMI接口的使用&#xff0c;但是RMI接口只有java可以使用&#xff0c;不能前端直接调用。openTCS最新版本中新增了很多WEB接口&#xff0c;openTCS启动后即可调用。web接口文档地址 默认地址前缀为&#xff1a;localhost:55200/v1 例如&#xff0c;获取车辆列表。 …

JVM系统优化实践(24):ZGC(一)

您好&#xff0c;这里是「码农镖局」CSDN博客&#xff0c;欢迎您来&#xff0c;欢迎您再来&#xff5e; 截止到目前&#xff0c;算上ZGC&#xff0c;Java一共有九种类型的GC&#xff0c;它们分别是&#xff1a; 1、Serial GC 串行/作用于新生代/复制算法/响应速度优先/适用于单…

分享一个霓虹灯拨动开关

先看效果&#xff1a; 再看代码&#xff08;查看更多&#xff09;&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title> 霓虹灯拨动开关</title><style>* {border: 0;box-sizin…

【linux】安装pytorch3d

写在开头 不要看网上的博客安装&#xff0c;直接参考官方安装文档去安装。 坑 坑1&#xff1a;安装pytorch3d后torch.cuda用不了 使用下面的命令安装后 conda install pytorch3d会提示安装下面的包&#xff0c;注意pytorch和torchvision都是cpu版本的&#xff0c;这样就会…

以太网帧格式与吞吐量计算

以太网帧结构 帧大小的定义 以太网单个最大帧 6&#xff08;目的MAC地址&#xff09; 6&#xff08;源MAC地址&#xff09; 2&#xff08;帧类型&#xff09; 1500{IP数据包[IP头&#xff08;20&#xff09;DATA&#xff08;1480&#xff09;]} 4&#xff08;CRC校验&#xff…

【福建事业单位-资料分析】01 数学推理-基础-特征-非特征数列

【福建事业单位-资料分析】01 数学推理-基础-特征-非特征数列 一、基础数列总结 二、特征数列2.1 多重数列项数多&#xff0c;多于7项总结 2.2机械划分①小数;ab②大数字多&#xff08;三位数、四位数&#xff09;&#xff0c;达到一半或者以上总结 2.3分数数列大通分总结 2.4幂…

【MySQL】事务的多版本并发控制(MVCC)

目录 一、数据库并发的三种场景二、MVCC2.1 三个记录隐藏字段2.2 undo log&#xff08;撤销日志&#xff09;2.3 模拟MVCC2.3.1 模拟更新&#xff08;update&#xff09;2.3.1 模拟删除&#xff08;delete&#xff09;2.3.1 模拟插入&#xff08;insert&#xff09;2.3.1 模拟查…