python 之路200行Python代码写了个打飞机游戏

Posted 梦子mengy7762

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了python 之路200行Python代码写了个打飞机游戏相关的知识,希望对你有一定的参考价值。

先看一下项目结构

\\

“”"

PlayPlane/

|-- bin/

| |-- main.py 程序运行主体程序

|-- config/

| |-- settings.py 程序配置(例如: 游戏背景音乐的加载等)

|-- material 程序素材放置(打飞机游戏素材放置)

|-- …

|-- src/ 程序主体模块存放

| |-- init.py

| |-- bullet.py 我方飞机发射子弹实现代码存放

| |-- enemy.py 敌方飞机实现代码存放

| |-- plane.py 我方飞机实现代码存放

|-- manage.py 程序启动文件

|-- README.md

“”"

再晒下项目成果图

实现步骤

一、首先在 config/settings.py 中进行以下功能的实现

  • 游戏初始化
  • 游戏混音器初始化
  • 背景音乐初始化
  • 我方飞机挂了音乐
  • 敌方飞机挂了音乐
  • 子弹发射音乐
  • View Code?

#! /usr/bin/env python

-- coding: utf-8 --

importpygame

pygame.init() # 游戏初始化

pygame.mixer.init() # 混音器初始化

游戏背景音乐

pygame.mixer.music.load(“material/sound/game_music.wav”)

pygame.mixer.music.set_volume(0.2)

子弹发射音乐

bullet_sound =pygame.mixer.Sound(“material/sound/bullet.wav”)

bullet_sound.set_volume(0.2)

我方飞机挂了的音乐

me_down_sound =pygame.mixer.Sound(“material/sound/game_over.wav”)

me_down_sound.set_volume(0.2)

敌方飞机挂了的音乐

enemy1_down_sound =pygame.mixer.Sound(“material/sound/enemy1_down.wav”)

enemy1_down_sound.set_volume(0.2)

config/settings.py

注:游戏素材滑动到文章底部点击链接即可下载

二、小试牛刀

飞机和子弹都是可移动的,那么怎么实现让它们动起来呢(我方飞机可以玩家进行操控,敌机就是随机性的出现,子弹暂由我方飞机发射)。

在Pygame中,所有移动对象都可看做是一个精灵(sprite),精灵之间能够进行相互的交互通信,例如如何让碰撞检测更加精准等等。这里还是要推荐下小编的Python学习喂鑫*(同音):‘’七六二,四五九,五一零‘’不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份2021最新的Python资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。

那么先让我们先在屏幕上制作一个游戏板,根据 settings.py 配置,并让它有声音播放,首先我们在 bin/main.py 中这么写:

我们可以直接运行它,那么我们会看到以下画面,并且还会有激情的声音吆!!!但是我们要将文件配置为绝对路径才可以运行,因为刚刚在settings中的加载的音乐文件为相对路径。

  • View Code?

#! /usr/bin/env python

-- coding: utf-8 --

importsys

fromconfig.settings import*

\\

bg_size =480, 852 # 初始化游戏背景大小(宽, 高)

screen =pygame.display.set_mode(bg_size) # 设置背景对话框

pygame.display.set_caption(“飞机大战”) # 设置标题

background =pygame.image.load(os.path.join(BASE_DIR, “material/image/background.png”)) # 加载背景图片,并设置为不透明

\\

defmain():

pygame.mixer.music.play(loops=-1) # loops 对应的值为 -1 则音乐会无限循环播放

whileTrue:

绘制背景图

screen.blit(background, (0, 0))

响应用户的操作(一定要有响应的用户操作)

forevent inpygame.event.get():

ifevent.type==12: # 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出

pygame.quit()

sys.exit()

再而我们将背景图像并输出到屏幕上面

pygame.display.flip()

if__name__ ==‘main’:

main()

接下来呢,我们将要制作我方飞机,敌方飞机和子弹如何让它们展示在游戏画板上,继而让它们变得可移动起来,请看代码实现方案…

从游戏画板上添加飞机,首先我们应怎样在屏幕上输出飞机???

上述讲过,pygame中的 sprite(精灵)可使一张图片或者一个静态物体动起来,那么制作飞机需要考虑并做些什么呢?

  1. 飞机的初始位置
  2. 通过按键 上下左右 来调控飞机的位置移动
  3. 飞机只能呆在制作的游戏画板中
  4. 飞机的速度
  5. 飞机死亡的加载
  6. 设定一个状态标识飞机的存活
  7. 让飞机具有动态的喷气式效果

那么如何实现以上的功能呢?接下来结合上述的示例代码我们先将我方飞机绘制到画板上方,并且我们通过按键 J 判定我方飞机的存活状态为死亡,绘制飞机的死亡画面并重置飞机

  • View Code?

“”"

创建飞机

在pygame中, 所有可移动的对象均叫可看作一个精灵(sprite)

该类并实现了碰撞方法 spritecollide

我方飞机和敌方飞机指定掩膜属性以及生存状态标志位 添加 self.mask 属性(可以实现更精准的碰撞效果)这里还是要推荐下小编的Python学习喂鑫*(同音):‘’七六二,四五九,五一零‘’不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份2021最新的Python资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。

“”"

倒入精灵模块, 使飞机可以动起来

importpygame

\\

classOurPlane(pygame.sprite.Sprite):

def__init__(self, bg_size):

super(OurPlane, self).init()

确定我方飞机背景图(有俩张,可以让它们不停的切换,形成动态效果)

self.image_one =pygame.image.load(“material/image/hero1.png”)

self.image_two =pygame.image.load(“material/image/hero2.png”)

获取我方飞机的位置

self.rect =self.image_one.get_rect()

本地化背景图片的尺寸

self.width, self.height =bg_size[0], bg_size[1]

获取飞机图像的掩膜用以更加精确的碰撞检测

self.mask =pygame.mask.from_surface(self.image_one)

定义飞机初始化位置,底部预留60像素

self.rect.left, self.rect.top =(self.width -self.rect.width) //2, (self.height -self.rect.height -60)

设置飞机移动速度

self.speed =10

设置飞机存活状态(True为存活, False为死亡)

self.active =True

加载飞机损毁图片

self.destroy_images =[]

self.destroy_images.extend(

[

pygame.image.load(“material/image/hero_blowup_n1.png”),

pygame.image.load(“material/image/hero_blowup_n2.png”),

pygame.image.load(“material/image/hero_blowup_n3.png”),

pygame.image.load(“material/image/hero_blowup_n4.png”)

]

)

defmove_up(self):

“”"

飞机向上移动的操作函数,其余移动函数方法类似

“”"

ifself.rect.top > 0: # 如果飞机尚未移动出背景区域

self.rect.top -=self.speed

else: # 若即将移动出背景区域,则及时纠正为背景边缘位置

self.rect.top =0

defmove_down(self):

“”"

飞机向下移动

“”"

ifself.rect.bottom < self.height -60:

self.rect.top +=self.speed

else:

self.rect.bottom =self.height -60

defmove_left(self):

“”"

飞机向左移动

“”"

ifself.rect.left > 0:

self.rect.left -=self.speed

else:

self.rect.left =0

defmove_right(self):

“”"

飞机向右移动

“”"

ifself.rect.right < self.width:

self.rect.right +=self.speed

else:

self.rect.right =self.width

defreset(self):

初始化飞机(飞机挂了, 初始化到初始位置)

self.rect.left, self.rect.top =(self.width -self.rect.width) //2, (self.height -self.rect.height -60)

重置飞机的存活状态

self.active =True

上面的代码写了一个 我们的飞机 (OurPlane) 类,它初始化了一些属性以及 上下左右 移动的方法和重置方法,接下来将要运用它展示到游戏画板上面

由于飞机是一直存在的,接下我们主程序 main 下面的死循环中这样写

\\

def main():    
pygame.mixer.music.play(loops=-1)  
# loops 对应的值为 -1 则音乐会无限循环播放    
our_plane = OurPlane(bg_size)  
# 初始化    
switch_image = False  
# 定义飞机的切图效果标识    
while True:        
# 绘制背景图        
screen.blit(background, (0, 0))        
# 飞机状态是存活        
if our_plane.active:            
if switch_image:                
screen.blit(our_plane.image_one, our_plane.rect)            
else:                
screen.blit(our_plane.image_two, our_plane.rect)            
switch_image = not switch_image  
# 让切图状态不停的变换        
else:            
pass        
# 响应用户的操作(一定要有响应的用户操作)        
for event in pygame.event.get():            
if event.type == 12:  
# 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出                
pygame.quit()                
sys.exit()        
# 再而我们将背景图像并输出到屏幕上面        
pygame.display.flip()if __name__ == '__main__':    main()

1.在屏幕上绘制飞机

\\

def main():    
pygame.mixer.music.play(loops=-1)  
# loops 对应的值为 -1 则音乐会无限循环播放    
our_plane = OurPlane(bg_size)  
# 初始化    
switch_image = False  
# 定义飞机的切图效果标识   
while True:        
# 绘制背景图        
screen.blit(background, (0, 0))        
# 飞机状态是存活        
if our_plane.active:            
if switch_image:                
screen.blit(our_plane.image_one, our_plane.rect)            
else:                
screen.blit(our_plane.image_two, our_plane.rect)            
switch_image = not switch_image  # 让切图状态不停的变换        
else:            
pass        
# 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)        key_pressed = pygame.key.get_pressed()        
if key_pressed[K_w] or key_pressed[K_UP]:            
our_plane.move_up()        
if key_pressed[K_s] or key_pressed[K_DOWN]:            
our_plane.move_down()        
if key_pressed[K_a] or key_pressed[K_LEFT]:            
our_plane.move_left()        
if key_pressed[K_d] or key_pressed[K_RIGHT]:            
our_plane.move_right()        
# 响应用户的操作(一定要有响应的用户操作)        
for event in pygame.event.get():            
if event.type == 12:  
# 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出                
pygame.quit()                
sys.exit()        
# 再而我们将背景图像并输出到屏幕上面        
pygame.display.flip()if __name__ == '__main__':    main()

2.让飞机上下左右动起来

\\

def main():    
pygame.mixer.music.play(loops=-1)  
# loops 对应的值为 -1 则音乐会无限循环播放    
our_plane = OurPlane(bg_size)  
# 初始化    
switch_image = False  
# 定义飞机的切图效果标识    
our_plane_destroy_index = 0    
while True:        
# 绘制背景图        
screen.blit(background, (0, 0))        
# 飞机状态是存活(如果按键 为 J, 让飞机死亡并绘制爆炸效果)        
if our_plane.active:            
if switch_image:                
screen.blit(our_plane.image_one, our_plane.rect)            
else:                
screen.blit(our_plane.image_two, our_plane.rect)            
switch_image = not switch_image  
# 让切图状态不停的变换        
else:            
"""            
飞机死亡也是进行按顺序的图片切换, 那么在死循环之外定义索引            
"""            
me_destroy_index = (our_plane_destroy_index + 1) % 4            
if me_destroy_index == 1:                
me_down_sound.play()  
# 爆炸声音效果                
our_plane.reset()  
# 初始化飞机            
if our_plane_destroy_index >= len(our_plane.destroy_images):                
our_plane_destroy_index = 0            
else:                screen.blit(our_plane.destroy_images[our_plane_destroy_index], our_plane.rect)            
our_plane_destroy_index += 1        
# 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)        
key_pressed = pygame.key.get_pressed()        
if key_pressed[K_w] or key_pressed[K_UP]:            
our_plane.move_up()        
if key_pressed[K_s] or key_pressed[K_DOWN]:            
our_plane.move_down()        
if key_pressed[K_a] or key_pressed[K_LEFT]:            
our_plane.move_left()        
if key_pressed[K_d] or key_pressed[K_RIGHT]:            
our_plane.move_right()        
# 按键为 j 飞机更改存活标识        
if key_pressed[K_j]:            
our_plane.active = False        
# 响应用户的操作(一定要有响应的用户操作)        
for event in pygame.event.get():            
if event.type == 12:  
# 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出                
pygame.quit()                
sys.exit()        
# 再而我们将背景图像并输出到屏幕上面        
pygame.display.flip()

3.按键为 j 绘制飞机的死亡状态

那么上述的功能都已经实现了,接下来就开始真正的"打飞机"

三、接下来可以制作我方飞机,敌方战机,子弹等,这些功能均在 src/ 目录下实现

  • 我方飞机根据按键上下左右进行移动,初始化位置,喷气式图片加载切换及重置效果等

\\

#! /usr/bin/env python# -*- coding: utf-8 -*-"""    
创建飞机    
在pygame中, 所有可移动的对象均叫可看作一个精灵(sprite)    
该类并实现了碰撞方法 spritecollide    
我方飞机和敌方飞机指定掩膜属性以及生存状态标志位 添加 self.mask 属性(可以实现更精准的碰撞效果)"""# 倒入精灵模块, 使飞机可以动起来import pygameclass OurPlane(pygame.sprite.Sprite):    
def __init__(self, bg_size):        
super(OurPlane, self).__init__()        
# 确定我方飞机背景图        
self.image_one = pygame.image.load("material/image/hero1.png")        
self.image_two = pygame.image.load("material/image/hero2.png")        
# 获取我方飞机的位置        
self.rect = self.image_one.get_rect()        
# 本地化背景图片的尺寸        
self.width, self.height = bg_size[0], bg_size[1]        
# 获取飞机图像的掩膜用以更加精确的碰撞检测        
self.mask = pygame.mask.from_surface(self.image_one)        
# 定义飞机初始化位置,底部预留60像素        
self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)        
# 设置飞机移动速度        
self.speed = 10        
# 设置飞机存活状态(True为存活, False为死亡)        
self.active = True        
# 加载飞机损毁图片        
self.destroy_images = []        
self.destroy_images.extend(            [                pygame.image.load("material/image/hero_blowup_n1.png"),                pygame.image.load("material/image/hero_blowup_n2.png"),                pygame.image.load("material/image/hero_blowup_n3.png"),                pygame.image.load("material/image/hero_blowup_n4.png")            ]        )    def move_up(self):        """        
飞机向上移动的操作函数,其余移动函数方法类似        """        
if self.rect.top > 0:  
# 如果飞机尚未移动出背景区域            
self.rect.top -= self.speed        
else:  # 若即将移动出背景区域,则及时纠正为背景边缘位置            
self.rect.top = 0    
def move_down(self):        
if self.rect.bottom < self.height - 60:            
self.rect.top += self.speed        
else:            
self.rect.bottom = self.height - 60    
def move_left(self):        
if self.rect.left > 0:            
self.rect.left -= self.speed        
else:            
self.rect.left = 0    
def move_right(self):        
if self.rect.right < self.width:            
self.rect.right += self.speed        
else:            
self.rect.right = self.width    
def reset(self):        
# 初始化飞机(飞机挂了, 初始化到初始位置)        
self.rect.left, self.rect.top = (self.width - self.rect.width) // 2, (self.height - self.rect.height - 60)        
self.active = Truesrc/plane.py

src/plane.py

  • 敌方飞机随机移动出现及重置(制作出我方飞机之后,敌机和子弹其实都是大同小异的)
  • #! /usr/bin/env python # -- coding: utf-8 -- “”" 定义敌机 “”" from random import randint import pygame class SmallEnemy(pygame.sprite.Sprite): “”" 定义小飞机敌人 “”" def init(self, bg_size): super(SmallEnemy, self).init() self.image = pygame.image.load(“material/image/enemy1.png”) self.rect = self.image.get_rect() self.width, self.height = bg_size[0], bg_size[1] self.mask = pygame.mask.from_surface(self.image) # 获取飞机图像的掩膜用以更加精确的碰撞检测 self.speed = 2 # 定义敌机出现的位置, 保证敌机不会在程序已开始就立即出现 self.rect.left, self.rect.top = ( randint(0, self.width - self.rect.width), randint(-5 * self.rect.height, -5), ) self.active = True # 加载飞机损毁图片 self.destroy_images = [] self.destroy_images.extend( [ pygame.image.load(“material/image/enemy1_down1.png”), pygame.image.load(“material/image/enemy1_down2.png”), pygame.image.load(“material/image/enemy1_down3.png”), pygame.image.load(“material/image/enemy1_down4.png”) ] ) def move(self): “”" 定义敌机的移动函数 :return: “”" if self.rect.top < self.height: self.rect.top += self.speed else: self.reset() def reset(self): “”" 当敌机向下移动出屏幕时, 以及敌机死亡 :return: “”" self.rect.left, self.rect.top = (randint(0, self.width - self.rect.width), randint(-5 * self.rect.height, 0)) self.active = Truesrc/enemy.py
  • 子弹按照我方飞机正中上方发射及频率调控,重置

\\

#! /usr/bin/env python# -*- coding: utf-8 -*-"""    
子弹的实现"""import pygameclass Bullet(pygame.sprite.Sprite):    
def __init__(self, position):        
super(Bullet, self).__init__()        
self.image = pygame.image.load("material/image/bullet1.png")        
self.rect = self.image.get_rect()        
self.rect.left, self.rect.top = position        
self.speed = 30        
self.active = True        
self.mask = pygame.mask.from_surface(self.image)    
def move(self):        """        
子弹移动, 超出屏幕范围, 则设置死亡        :
return:        """        
if self.rect.top < 0:            
self.active = False        
else:            
self.rect.top -= self.speed    
def reset(self, position):        """        
复位函数        
:param position:        :
return:        """        
self.rect.left, self.rect.top = position        
self.active = Truesrc/bullet.py

src/bullet.py

在上面的内容中,使用面向对象的形式制作了游戏中可移动的对象并继承 pygame.sprite.Sprite

四、然后在 bin/main.py 中进行主体功能的实现

  • 初始化背景图及大小
  • 我方飞机移动及发射子弹
  • 敌方飞机移动
  • 我方飞机和敌方飞机碰撞检测
  • 键盘按键监测效果
  • 我方飞机和敌方飞机挂了效果绘制

\\

import sysfrom pygame.locals import *from config.settings import *from src.plane import OurPlanefrom src.enemy import SmallEnemyfrom src.bullet import Bulletbg_size = 480, 852  
# 初始化游戏背景大小(宽, 高)screen = pygame.display.set_mode(bg_size)  
# 设置背景对话框pygame.display.set_caption("飞机大战")  
# 设置标题background = pygame.image.load("material/image/background.png")  
# 加载背景图片,并设置为不透明# 获取我方飞机our_plane = OurPlane(bg_size)def add_small_enemies(group1, group2, num):    """    
添加小型敌机    
指定个敌机对象添加到精灵组(sprite.group)    
参数group1、group2是两个精灵组类型的形参,用以存储多个精灵对象(敌机)。    
需要注意的一点是group既然是特定的精灵组结构体,在向其内部添加精灵对象时需要调用其对应的成员函数add()    
:return:    """    
for i in range(num):        
small_enemy = SmallEnemy(bg_size)        
group1.add(small_enemy)        
group2.add(small_enemy)def main():    
# 响应音乐    
pygame.mixer.music.play(-1)  
# loops 接收该参数, -1 表示无限循环(默认循环播放一次)    
running = True    
switch_image = False  
# 切换飞机的标识位(使飞机具有喷气式效果)    
delay = 60  # 对一些效果进行延迟, 效果更好一些    
enemies = pygame.sprite.Group()  
# 生成敌方飞机组(一种精灵组用以存储所有敌机精灵)    
small_enemies = pygame.sprite.Group()  
# 敌方小型飞机组(不同型号敌机创建不同的精灵组来存储)    
add_small_enemies(small_enemies, enemies, 4)  
# 生成若干敌方小型飞机    
# 定义子弹, 各种敌机和我方敌机的毁坏图像索引    
bullet_index = 0    
e1_destroy_index = 0    
me_destroy_index = 0    
# 定义子弹实例化个数    
bullet1 = []    
bullet_num = 6    
for i in range(bullet_num):        
bullet1.append(Bullet(our_plane.rect.midtop))    
while running:        
# 绘制背景图        
screen.blit(background, (0, 0))        
# 微信的飞机貌似是喷气式的, 那么这个就涉及到一个帧数的问题        
clock = pygame.time.Clock()        
clock.tick(60)        
# 绘制我方飞机的两种不同的形式        
if not delay % 3:            
switch_image = not switch_image        
for each in small_enemies:            
if each.active:                
# 随机循环输出小飞机敌机                
for e in small_enemies:                    
e.move()                    
screen.blit(e.image, e.rect)            
else:                
if e1_destroy_index == 0:                    
enemy1_down_sound.play()                screen.blit(each.destroy_images[e1_destroy_index], each.rect)                e1_destroy_index = (e1_destroy_index + 1) % 4                
if e1_destroy_index == 0:                    
each.reset()        
# 当我方飞机存活状态, 正常展示        
if our_plane.active:            
if switch_image:                
screen.blit(our_plane.image_one, our_plane.rect)            
else:                
screen.blit(our_plane.image_two, our_plane.rect)            
# 飞机存活的状态下才可以发射子弹            
if not (delay % 10):  
# 每十帧发射一颗移动的子弹                
bullet_sound.play()                
bullets = bullet1                bullets[bullet_index].reset(our_plane.rect.midtop)                
bullet_index = (bullet_index + 1) % bullet_num            
for b in bullets:                
if b.active:  # 只有激活的子弹才可能击中敌机                    
b.move()                    
screen.blit(b.image, b.rect)                    
enemies_hit = pygame.sprite.spritecollide(b, enemies, False, pygame.sprite.collide_mask)                    
if enemies_hit:  
# 如果子弹击中飞机                        
b.active = False  # 子弹损毁                        
for e in enemies_hit:                            
e.active = False  # 小型敌机损毁        
# 毁坏状态绘制爆炸的场面        
else:            
if not (delay % 3):                screen.blit(our_plane.destroy_images[me_destroy_index], our_plane.rect)                me_destroy_index = (me_destroy_index + 1) % 4                
if me_destroy_index == 0:                    
me_down_sound.play()                    
our_plane.reset()        
# 调用 pygame 实现的碰撞方法 spritecollide (我方飞机如果和敌机碰撞, 更改飞机的存活属性)        
enemies_down = pygame.sprite.spritecollide(our_plane, enemies, False, pygame.sprite.collide_mask)        
if enemies_down:            
our_plane.active = False            
for row in enemies:                
row.active = False        
# 响应用户的操作        
for event in pygame.event.get():            
if event.type == 12:  
# 如果用户按下屏幕上的关闭按钮,触发QUIT事件,程序退出                
pygame.quit()                
sys.exit()        
if delay == 0:            
delay = 60        
delay -= 1        
# 获得用户所有的键盘输入序列(如果用户通过键盘发出“向上”的指令,其他类似)        
key_pressed = pygame.key.get_pressed()        
if key_pressed[K_w] or key_pressed[K_UP]:            
our_plane.move_up()        
if key_pressed[K_s] or key_pressed[K_DOWN]:            
our_plane.move_down()        
if key_pressed[K_a] or key_pressed[K_LEFT]:            
our_plane.move_left()        
if key_pressed[K_d] or key_pressed[K_RIGHT]:            
our_plane.move_right()        
# 绘制图像并输出到屏幕上面        
pygame.display.flip()

bin/main.py

这里还是要推荐下小编的Python学习喂鑫*(同音):‘’七六二,四五九,五一零‘’不管你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份2021最新的Python资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。

五、畅汗淋漓,一气呵成打飞机

\\

from bin.main import main

\\

if name == ‘main’:

“”"

环境: python3 + pygame

running 起来就可以打飞机了O(∩_∩)O~.

“”"

main()

最终效果!

以上是关于python 之路200行Python代码写了个打飞机游戏的主要内容,如果未能解决你的问题,请参考以下文章

Python之路—200行Python代码搞了个打飞机游戏!!

女友晚安之后依然在线:python男友用20行代码写了个小工具

Python写了个疫情信息快速查看工具

Python写了个疫情信息快速查看工具(附源码)

python统计代码总行数(代码行空行注释行)

一个User表的增删改查,我写了近200行代码