基于Python的飞机大战游戏

学习目标

  • 了解 飞机大战游戏的规则

  • 理解 面向对象思想,会独立设计游戏的类与模块

  • 掌握 pygame模块的使用

1.1 游戏介绍

飞机大战是一款由腾讯公司微信团队推出的软件内置的小游戏,这款游戏画面简洁有趣,规则简单易懂,操作简便易上手,在移动应用兴起之初曾风靡一时。

1.1.1 游戏介绍

飞机大战游戏主要以太空主题的画面为游戏背景,由玩家通过键盘控制英雄飞机向敌机总部发动进攻,在进攻的过程中既可以让英雄飞机发射子弹或炮弹击毁敌机以赢取分数,也可以拾取道具以增强自己的战斗力,一旦被敌机撞毁就结束游戏。

飞机大战游戏包含众多游戏元素,例如,大小各异的飞机、连发3颗的子弹、左上角的游戏分数等,其中主要的元素如图所示。

飞机大战游戏中的主要元素可以归纳为背景、英雄飞机、敌机、道具、分数和奖励、关卡设定这几大类,各类中游戏元素的具体说明如下。

1.背景 整个游戏窗口的背景是一张星空图像,该背景图像会缓缓地向下持续移动,使玩家产生一种英雄飞机向上飞行的错觉。

2.英雄飞机 英雄飞机是由玩家控制的飞机,是飞机大战游戏的主角,其相关说明具体如下。

(1)英雄飞机在游戏开始时显示在屏幕下方的中央位置。

(2) 英雄飞机在出场后的3秒内处于无敌状态,此时它不会被任何敌机撞毁,也不会撞毁任何敌机。

(3)玩家可以通过方向键(↑、↓、←、→)控制英雄飞机在屏幕范围内向上方、下方、左方和右方移动。 英雄飞机是由玩家控制的飞机,是飞机大战游戏的主角,其相关说明具体如下。

(4) 英雄飞机出场后每隔0.2秒会自动连续发射3颗子弹,关于子弹的特征和行为具体如下: 特征:子弹的速度为12,杀伤力为1。 行为:子弹由英雄飞机头部的正上方位置发射,沿屏幕垂直方向向上飞行;子弹被发射时需要播放发射子弹的音效;子弹在飞行途中若击中敌机,会对敌机造成伤害;子弹若已飞出屏幕且飞行途中未击中任何敌机,会被销毁。 英雄飞机是由玩家控制的飞机,是飞机大战游戏的主角,其相关说明具体如下。

(5) 英雄飞机出场后默认会携带3颗炸弹,玩家按下字母b时会引爆1枚炸弹,炸弹数量减1;炸弹数为0时,无法再使用炸弹。

(6) 英雄飞机带有多个动画和音效。当飞机飞行时,显示飞行动画;当飞机被敌机撞毁时,显示被撞毁动画,并播放被撞毁音效;当飞机升级时,播放升级音效。

英雄飞机是由玩家控制的飞机,是飞机大战游戏的主角,其相关说明具体如下。

(7) 英雄飞机具有多条生命。英雄飞机的初始生命为3;英雄飞机被敌机击中时,命数减1;英雄飞机得分每增加10万,命数加1;英雄飞机的生命为0时,游戏结束。英雄飞机的命数会实时地显示在游戏界面的右下方位置。

3.敌机 飞机大战游戏中敌机的机型小、中、大三种,各机型均有生命值、速度、分值、图片和音效等多个特征,且不同类型的敌机所具有的特征也不尽相同,后续在设计类时会有详细说明。 飞机大战中的敌机具有以下行为:

(1)敌机出现在游戏窗口顶部的随机位置。

(2)敌机按照各自不同的速度,沿垂直方向向游戏窗口的下方飞行。

(3)若敌机与英雄飞机相撞,则会击毁英雄飞机。

飞机大战中的敌机具有以下行为:

(4)若敌机被子弹击中,则敌机的生命值需要减去子弹的伤害度,此时根据敌机的生命值可以分如下两种情况进行处理: 如果敌机的生命值大于 0,那么显示敌机被击中图片(若有被击中图片),让敌机继续向屏幕下方飞行。 如果敌机的生命值等于0,那么播放敌机被撞毁动画与被撞毁音效。在被撞毁动画播放过程中,该敌机不会在屏幕上移动;在被撞毁动画播放完成后,该敌机被设为初始状态,跳转到第(1)步继续执行。

飞机大战中的敌机具有以下行为:

(5)若敌机飞出了游戏窗口且飞行途中没有被击毁,该敌机被设为初始状态。 值得一提的是,正在播放被撞毁动画的敌机是已经被摧毁的敌机,它既不能被子弹击中,也不能撞击英雄飞机。

4.道具 在游戏过程中,道具每隔30秒会从游戏窗口上方的随机位置向下飞出,一旦飞出的过程中碰撞英雄飞机,就会被英雄飞机拾取。飞机大战游戏有两种道具:炸弹补给和子弹增强,关于这两种道具的功能描述如表所示。

道具名称功能描述速度播放音效
炸弹补给英雄飞机拾取后,炸弹数量加15
子弹增强英雄飞机拾取后,发射的子弹由单排改为双排,且持续时长20秒5

5.分数和奖励 当英雄飞机通过子弹或炸弹击毁敌机时,会获得与敌机分值相对应的分数,并将获得的分数实时地显示在游戏窗口的左上方。同一局游戏的分数会不断累加,并在下一局开始时自动清零。 系统会记录玩家历次游戏所得到的最高分,并在游戏暂停和结束时显示在游戏窗口上。

6.关卡设定 飞机大战游戏一共设立了3个关卡,依次是关卡1、关卡2和关卡3,其中关卡1为起始关卡。在英雄飞机的得分超过当前关卡的预设分值之后,游戏会自动进入下一个关卡。关卡越高难度越高,敌机数量和种类越多,速度也更快。3 个关卡的具体设定如表所示。

关卡名称分值范围小敌机数量(速度)中敌机数量(速度)大敌机数量(速度)
关卡 1< 1000016(1 ~ 3)0(1)0(1)
关卡 2< 5000024(1 ~ 5)2(1)0(1)
关卡 3>= 5000032(1 ~ 7)4(1 ~ 3)2(1)

1.1.2 游戏典型场景

飞机大战游戏的典型事件组成了各个典型场景,除了游戏进行中的场景之外,还包括游戏开始、飞机碰撞、游戏暂停、游戏结束几个场景。

1.2 项目准备

明确了飞机大战游戏之后,进入开发工作之前,我们需要先完成分析与设计等准备工作,以明确项目的实现方式和内部结构等。

1.2.1 类设计

根据游戏介绍分析可知,飞机大战游戏有众多游戏元素,为方便统一管理游戏元素,我们按游戏元素的职责进行归类,各类的名称及说明如表所示。

分类类名说明
游戏类Game负责整个游戏的流程
指示器面板类HUBPanel负责统一管理游戏状态、游戏分数、炸弹数量、生命值以及文本提示等与游戏数据或状态相关的内容
音乐播放类MusicPlayer负责背景音乐和音效的播放
游戏背景类Background负责显示游戏的背景图像
状态按钮类StatusButton负责显示游戏的状态按钮
飞机类Plane表示游戏中的飞机,包括英雄飞机和敌机
子弹类Bullet表示英雄飞机发射的子弹
道具类Supply负责管理炸弹补给和子弹增强道具
文本标签类Label负责显示游戏窗口上的文本

飞机大战游戏项目中提炼出的类及类之间的继承关系如图所示。

1.2.2 模块设计

在设计程序时,我们既要考虑程序的设计理念和设计思想,又要考虑程序的结构。结构设计的原则是代码模块化、容易扩展和维护。因此,可将飞机大战游戏项目划分为4个模块:game.py、game_items.py、game_hud.py和game_music.py,各模块的说明如表所示。

模块说明
game.py游戏主模块,封装Game类并负责启动游戏。
game_items.py游戏元素模块,封装英雄飞机、子弹、敌机、道具等游戏元素类,并定义全局变量。
game_hud.py游戏面板模块,封装指示器面板类。
game_music.py游戏音乐模块,封装音乐播放器类。

1.2.3 创建项目

打开PyCharm工具,新建一个名称为“飞机大战”的项目。 在飞机大战项目中依次建立game.py、game_items.py、game_hud.py和game_music.py四个文件,并且将资源文件夹“res”复制到飞机大战目录下。创建好的项目文件结构如图所示。

图中的res目录包含三个子目录:images、sound和font,子目录分别放置了游戏中使用的图片、声音和字体素材。

11.2.4 下载集成pygame模块

1.3 游戏框架搭建

准备工作完成之后,便可以进入项目的实现阶段。游戏框架搭建是实现项目的第一步,它会按照游戏的完整流程搭建整个框架,如此便可以直接向框架内填充游戏的内容。

1.3.1 游戏类的设计

游戏类(Game)负责整个游戏的流程,它需要包含游戏中的主要元素,设计后的类图如图所示。

关于游戏类的属性和方法的说明具体如下。 1.Game类的属性 Game类的属性按作用的不同可以分为游戏属性和精灵(表示显示图像的对象,游戏窗口中看到的每个单独图像或者一行文本都可以看作一个精灵,例如,英雄飞机、一颗子弹、分数标签等)组属性。

(1)游戏属性

属性说明
main_window游戏主窗口,初始大小为 (480, 700)
is_game_over游戏结束标记,初始为 False
is_pause游戏暂停标记,初始为 False
hero英雄精灵,初始显示在游戏窗口中间靠下位置
hud_panel指示器面板,负责显示与游戏状态以及数据相关的内容,包括状态图像、游戏得分、炸弹数量、英雄命数,以及游戏暂停或结束时显示在游戏窗口中央位置的提示信息等
player音乐播放器,负责播放背景音乐和游戏音效

(2)精灵组属性 游戏类中定义的精灵组属性如表所示。

属性说明
all_group所有精灵组,存放所有要显示的精灵,用于屏幕绘制和更新位置
enemies_group敌机精灵组,存放所有敌机精灵对象,用于检测子弹击中敌机以及敌机撞击英雄
supplies_group道具精灵组,存放所有道具精灵对象,用于检测英雄飞机拾取道具

关于游戏类的属性和方法的说明具体如下。

2.Game类的方法 Game类封装了多个方法,分别用于创建游戏元素、管理游戏的流程、监听系统事件等。

Game类中定义的方法如表所示。

方法说明
reset_game()重置游戏。在开启新一轮游戏之前,将游戏属性恢复到初始值
create_enemies()创建敌机精灵。在新游戏开始或者关卡晋级后,根据当前游戏级别创建敌机精灵
create_supplies()创建道具。游戏开始后每隔 30 秒随机投放炸弹补给或子弹增强道具
start()开始游戏。创建时钟对象并且开启游戏循环,在游戏循环中监听事件、更新精灵位置、绘制精灵、更新显示、设置刷新帧率
event_handler()事件监听。监听并处理每一次游戏循环执行时发生的事件,避免游戏循环中的代码过长
check_collide()碰撞检测。监听并处理每一次游戏循环执行时是否发生精灵与精灵之间的碰撞,例如,子弹击中敌机、英雄拾取道具、敌机撞击英雄等

明确了游戏类的设计之后,便可以开始游戏框架的搭建工作。游戏框架的实现过程如下。 1.定义游戏窗口尺寸的全局变量 2.实现Game类的基础代码 3.在主程序中启动游戏 4.使用空格键切换游戏状态

1.3.2 游戏框架实现

明确了Game类的设计后,便可以开始游戏框架的搭建工作。游戏框架的实现过程如下。

1.声明游戏窗口尺寸的全局变量

在game_items模块中,声明一个表示游戏窗口尺寸的全局矩形对象SCREEN_RECT

import pygame
# 游戏窗口区域(矩形区域),起点坐标和终点坐标
SCREEN_RECT=pygame.Rect(0,0,480,700)

2.实现Game类的基础代码

在game模块中定义Game类,并实现构造方法(_ _ init _ _)和重置游戏方法(reset_game)

import pygame
from game_items import *class Game(object):"""游戏类的构造方法"""def __init__(self):# 设置游戏主窗口self.main_window=pygame.display.set_mode(SCREEN_RECT.size)# 设置标题pygame.display.set_caption("飞机大战")# 定义游戏状态属性self.is_game_over=False #游戏结束标记self.is_pause=False #游戏暂停标记"""重置游戏方法"""def reset_game(self):self.is_game_over = False  # 游戏结束标记self.is_pause = False  # 游戏暂停标记

在Game类中定义event_handler()方法,用于监听游戏循环中发生的事件,若监听到退出事件,则返回True,否则返回Flalse

"""事件监听
return:如果监听到退出事件,返回True,否则返回False"""
def event_handler(self):for event in pygame.event.get():# 游戏退出事件if event.type == pygame.QUIT:return True# 键盘退出按钮被触发elif event.type==pygame.KEYDOWN and event.key == pygame.K_ESCAPE:return Truereturn False

在Game类中定义start()方法。start()方法用于开始游戏,该方法中先定义时钟对象,再开启游戏循环

"""开始游戏"""
def start(self):clock=pygame.time.Clock() # 游戏时钟while True: # 开始游戏循环if self.event_handler(): # 当事件返回为True,则表示退出游戏,返回为空return pygame.display.update() # 更新游戏显示clock.tick(60) # 设置游戏刷新帧率

以上方法的循环体中首先调用了event_handler()方法监听事件,然后调用了pygame.display.update()方法更新显示,最后调用tick()方法设置刷新帧率,设置后再保证动画效果流畅的前提下,降低了CPU负荷。

3.在主程序中启动游戏

在game模块的末尾增加以下代码,实现创建游戏对象并且启动游戏的功能

if __name__ =="__main__":# 初始化游戏pygame.init()# 创建游戏对象,开启游戏Game().start()# 设置按下esc键退出游戏pygame.quit()

运行游戏,可以看到创建成功的游戏主窗口,此时按下“Esc”键或者单击关闭按钮都可以退出程序。

4.使用空格键切换游戏状态

调整event_handler()方法。在事件监听的循环体中,增加对空格键按键事件的监听,并在监听到空格键时切换游戏状态

# 键盘空格键被触发
elif event.type==pygame.KEYDOWN and event.key==pygame.K_SPACE:if self.is_game_over: # 如果游戏已经结束self.reset_game() # 则重新开始else:self.is_pause=not self.is_pause # 否则切换为暂停状态/恢复游戏

在游戏循环语句中增加判断游戏状态的代码,若游戏已经结束,则使用print()方法输出游戏结束状态的描述文字,若游戏暂停,则使用print()方法输出游戏暂停状态的描述文字,若游戏正在进行中,则使用print()方法输出游戏状态的描述文字。

"""开始游戏"""
def start(self):clock=pygame.time.Clock() # 游戏时钟while True: # 开始游戏循环if self.event_handler(): # 当事件返回为True,则表示退出游戏,返回为空return#判断游戏状态if self.is_game_over:print("游戏已经结束,按空格键重新开始……")elif self.is_pause:print("游戏已暂停,按空格键继续……")else:print("游戏进行中……")pygame.display.update() # 更新游戏显示clock.tick(60) # 设置游戏刷新频率

运行游戏,不断按下空格键,可以看到控制台中有关游戏状态提示文字的显示及变化。

需要说明的是,若需要测试游戏结束后使用空格键重新开始游戏的功能,可以先将构造方法的is_game_over属性暂时设置为True,再进行测试。

1.4 游戏背景和英雄飞机

飞机大战项目需要管理众多游戏对象(例如敌机、英雄飞机、子弹等),并且实现众多动画(例如英雄飞机飞行动画,飞机碰撞动画等),使用精灵和精灵组来管理这些游戏对象的显示和动画效果是再合适不过了。 接下来,本节为大家介绍游戏精灵类,带领大家绘制游戏背景和英雄飞机,并实现游戏背景的滚动动画。

1.4.1 介绍精灵和精灵组

pygame专门提供了两个类:Sprite和Group,分别表示精灵和精灵组,其中精灵代表显示图像的游戏对象,精灵组代表保存和管理一组精灵的容器。Sprite和Group类中包含一些便于操作的属性或方法,具体介绍如下。

1.Sprite类 Sprite是一个表示游戏对象的基类,该类中提供的常用属性和方法如表所示。

类型名称说明
属性image记录从磁盘加载的图片内容或者字体渲染的文本内容,注意:子类中必须指定
属性rect记录 image 要显示在游戏窗口的矩形区域,注意:子类中必须指定
方法update(*args)默认什么都不做,子类可以根据需求重写,以改变精灵的位置rect 或者显示内容image
方法add(*groups)将精灵添加到指定的精灵组(多值)
方法remove(*groups)将精灵从指定的精灵组(多值)移除
方法kill()将精灵从所有精灵组移除

值得一提的是,Sprite只是一个基类,实际开发中需要派生一个Sprite的子类,通过子类创建精灵对象。

2.Group类 Group是一个包含若干精灵的容器类,该类中提供了一些管理精灵的常用方法,关于这些方法的说明如表所示。

名称说明
update(*args)组内所有精灵调用update(*args) 方法,一次改变所有精灵的位置rect 或显示内容image
draw(surface)将组内所有精灵的 image 绘在 surface 的 rect 矩形区域,实现在游戏窗口中一次绘制多个精灵的功能
sprites()返回精灵组中所有精灵的列表
add(*sprites)向精灵组中添加指定的精灵(多值)
remove(*sprites)从精灵组中移除指定的精灵(多值)
empty()清空精灵组中所有的精灵

1.4.2 派生游戏精灵子类

按照pygame官方文档的建议,我们在实际开发中不能直接使用Sprite类,而是要使用Sprite类派生的子类。 pygame官方文档规定了Sprite类子类的注意事项,具体如下。

  • 子类可以重写update()方法。

  • 子类必须为image和rect属性赋值。

  • 子类的构造方法能够接收任意数量的精灵组对象,以将创建完的精灵对象添加到指定的精灵组中。

  • 子类的构造方法中必须调用父类的构造方法,如此才能向精灵组中添加精灵。

在game_items模块中定义pygame.sprite.Sprite的子类GameSprite,GameSprite类的类图如图所示。

GameSprite类定义了飞机大战游戏项目中大部分精灵类的通用特征和功能,它将作为其他精灵类的基类来使用。

"""游戏精灵类"""
class GameSprite(pygame.sprite.Sprite):res_path="./res/images/" # 图片资源路径def __init__(self,image_name,speed,*groups):"""构造方法:param image_name:要加载的图片文件名:param speed:移动速度,0表示静止:param groups:要添加到的精灵组,不传值则不添加"""super().__init__(*groups)#加载图像self.image=pygame.image.load(self.res_path+image_name)# 获得图片尺寸大小self.rect=self.image.get_rect() # 默认再左上角self.speed=speed # 保存移动速度def update(self,*args):"""更新精灵位置,默认再垂直方向移动"""self.rect.y +=self.speed

GameSprite类定义了飞机大战游戏项目中大部分精灵类的通用特征和功能,它将作为其他精灵类的基类来使用。

1.4.3 绘制游戏背景和英雄飞机

1.按照Game类的类图,我们需要在Game类的构造方法中: 创建 3 个精灵组 创建背景精灵 创建英雄精灵

# 精灵组属性
self.all_group = pygame.sprite.Group()  # 所有精灵组
self.enemies_group = pygame.sprite.Group()  # 敌机精灵组
self.supplies_group = pygame.sprite.Group()  # 道具精灵组
#创建精灵
#创建背景精灵,向下方移动
GameSprite("background.png",1,self.all_group)
#英雄精灵,静止不动
hero=GameSprite("me1.png",0,self.all_group)
hero.rect.center=SCREEN_RECT.center #显示在屏幕中央

2.在判断游戏状态之后、更新显示之前需要增加负责绘制和更新所有精灵的代码。

"""开始游戏"""
def start(self):clock=pygame.time.Clock() # 游戏时钟while True: # 开始游戏循环if self.event_handler(): # 当事件返回为True,则表示退出游戏,返回为空return#判断游戏状态if self.is_game_over:print("游戏已经结束,按空格键重新开始……")elif self.is_pause:print("游戏已暂停,按空格键继续……")else:#更新all_gourp中所有精灵内容self.all_group.update()# 绘制all_group中的所有精灵self.all_group.draw(self.main_window)pygame.display.update() # 更新游戏显示clock.tick(60) # 设置游戏刷新频率

运行游戏,可以在游戏窗口中看到缓缓向下移动的星空背景和英雄飞机,如图所示。

<

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

修改表空间对应数据文件的大小

Oracle从入门到总裁:​​​​​​https://blog.csdn.net/weixin_67859959/article/details/135209645 表空间与数据文件紧密相连&#xff0c;相互依存&#xff0c;创建表空间的时候需设置数据文件大小。 在后期实际应用中&#xff0c;如果实际存储的数据量超出事先设置的数据…

小红书·电商运营课:小红书开店流程,小红书电商如何运营(18节视频课)

课程目录 第1节课:学习流程以及后续实操流程注意事项 第2节课:小红书店铺类型解析以及开店细节 第3节课:小红书电商运营两种玩法之多品店铺解析 第4节课:小红书电商运营两种玩法之单品店铺解析 第5节课:选品课(多品类类目推荐) 第6节课:选品课(多品类类目推荐) 第7节课:…

为啥我说英语能决定程序员的天花板?

看到知乎有这样的一个问题&#xff0c;作为程序员的你&#xff0c;大学最后悔没有好好学哪门课&#xff1f; 很多人回答《软件工程》、《线性代数》、《微积分》等&#xff0c;各种都有。。 但我觉得&#xff0c;这些课都很重要&#xff0c;但没学好不妨碍自学。 其实对程序…

【强训笔记】day20

NO.1 思路&#xff1a;先判断能对砍几个回合&#xff0c;取最小值&#xff0c;因为回合数是整数&#xff0c;所以可能存在都大于0的情况&#xff0c;再判断一下如果都存活就再对砍一次&#xff0c;直到一家存活或者都死亡。 代码实现&#xff1a; #include<iostream>u…

IDEA 常见设置问题

OutOfMemoryError IDEA 第一次运行项目时&#xff0c;会报错误 - java.lang.OutOfMemoryError: Java heap space / insufficient memory&#xff0c;解决办法是&#xff1a; 将图示部分由默认的 700 改为 2048。 import * 工程lint检查时不允许使用import *&#xff0c;IDE…

基恩士PLC-KV5500基础入门

一、准备工作&#xff1a; 1.准备的东西&#xff1a;一个基恩士PLC-KV5500模块。两个自复位开关&#xff0c;24v LED灯一个&#xff0c;24v开关电源一个&#xff0c;KV5500端子台IO线缆&#xff1b;有编程软件的电脑一台。 编程软件&#xff1a; 基恩士PLC-KV5500接线图&…

wordpress主题 7B2 PRO主题5.4.2免授权直接安装

内容目录 一、详细介绍二、效果展示1.部分代码2.效果图展示 三、学习资料下载 一、详细介绍 WordPress 资讯、资源、社交、商城、圈子、导航等多功能商用主题&#xff1a;B2 PRO 其设计风格专业且时尚&#xff0c;功能十分强大&#xff0c;包括多栏布局、自定义页面、强大的主…

redis的双写一致性

双写一致性问题 1.先删除缓存或者先修改数据库都可能出现脏数据。 2.删除两次缓存&#xff0c;可以在一定程度上降低脏数据的出现。 3.延时是因为数据库一般采用主从分离&#xff0c;读写分离。延迟一会是让主节点把数据同步到从节点。 1.读写锁保证数据的强一致性 因为一般放…

品鉴中的价值认知:如何理解红酒在生活中的地位与意义

红酒作为一种富有文化内涵的产品&#xff0c;在人们的生活中扮演着重要的角色。品鉴云仓酒庄雷盛红酒不仅是对其品质的欣赏&#xff0c;更是对其中蕴含的价值认知的认同。通过品鉴红酒&#xff0c;我们可以理解其在生活中的地位与意义&#xff0c;以及它所传递的文化和精神价值…

[数据集][目标检测]管道焊缝质量检测数据集VOC+YOLO格式1134张2类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1134 标注数量(xml文件个数)&#xff1a;1134 标注数量(txt文件个数)&#xff1a;1134 标注…

一文彻底搞清楚MySQL的主键、外键、约束和各种索引

0.前言 主键用于唯一标识表中每一行数据&#xff0c;外键用于建立表与表之间关联关系&#xff0c;约束用于限制表中数据的规则&#xff0c;索引用于加速查询。 文章目录 0.前言1. 主键1.1. 在创建表时定义主键1.2. 在已有表中添加主键 2. 外键2.1. 在创建表时定义外键2.2. 在已…

【QVariant类型剖析】

QVariant类型剖析 &#x1f31f; 官方文档中给出的定义&#x1f31f; 特性&#x1f338;QVariant实战应用&#x1f338;项目成果展示 &#x1f31f; 官方文档中给出的定义 &#x1f4d8;Because C forbids unions from including types that have non-default constructors or…