20254123 2025-2026-2 《Python程序设计》实验4报告
课程:《Python程序设计》
班级: 2541
姓名: 刘浩丞
学号:20254123
实验教师:王志强
实验日期:2026年6月8日
必修/选修: 专选课
一、实验内容
Python综合应用:爬虫、数据处理、可视化、机器学习、神经网络、游戏、网络安全等。
例如:编写从社交网络爬取数据,实现可视化舆情监控或者情感分析。
例如:利用公开数据集,开展图像分类、恶意软件检测等
例如:利用Python库,基于OCR技术实现自动化提取图片中数据,并填入excel中。
例如:爬取天气数据,实现自动化微信提醒
例如:利用爬虫,实现自动化下载网站视频、文件等。
例如:编写小游戏:坦克大战、贪吃蛇、扫雷等等
注:在Windows/Linux系统上使用VIM、PDB、IDLE、Pycharm等工具编程实现。
要求:
(1)程序能运行,功能丰富(至少5个功能)。(需求提交源代码,并建议录制程序运行的视频)15分
(2)综合实践报告,要体现实验分析、设计、实现过程、结果等信息,格式规范,逻辑清晰,结构合理。20分。
(3)在实践报告中,需要对全课进行总结,并写课程感想体会、意见和建议等。10分
二、实验分析
(一)问题分析
本次实验要求能力较为综合,是对课堂所学的一次全方位总结与实践。为了给老师呈现出较好的效果(不被老师拷打),选择了编写小游戏类的选题,且更贴合Python图形化编程的学习内容,并且本人较为喜欢坦克大战的游戏,故设计之。
(二)选题分析
坦克大战游戏实验需要综合运用Pygame的图形绘制、碰撞检测与事件驱动机制,将通过面向对象设计将坦克、子弹、墙壁等实体封装为独立类,并且要设计支持单人、双人合作及对战三种模式。为保证流畅对战,还需要调试了移动冲突与碰撞逻辑。该实践可以加深对游戏循环、状态机及实时交互的理解,验证了Python在小型游戏开发中的可行性与高效性。
三、实验设计
(一)实验模块设计
| 模块名称 | 文件/类名 | 主要职责 |
| 初始化与常量模块 | 全局常量 | 定义屏幕尺寸、颜色、速度、冷却帧数等游戏参数 |
| 墙体生成模块 | generate_random_walls() | 根据关卡等级随机生成砖墙,确保安全区域无墙 |
| 爆炸特效模块 | Explosion | 管理爆炸动画的半径、透明度及生命周期 |
| 坦克基类 | Tank | 封装坦克的坐标、方向、移动、射击、绘制等通用行为 |
| 玩家坦克类 | PlayerTank | 继承自Tank,添加生命值、无敌状态、键盘控制、分数统计 |
| 敌方坦克类 | EnemyTank | 继承自Tank,实现随机移动、随机转向、自动射击的简单AI |
| 子弹类 | Bullet | 管理子弹位置、方向、存活状态及所有者(用于对战模式) |
| 墙体类 | Wall | 管理砖墙的存在状态及绘制 |
| 游戏主控类 | Game | 整合所有模块,管理状态机(菜单/游戏中)、事件循环、碰撞检测、胜负判定 |
| 菜单界面模块 | draw_menu(), handle_menu_events() | 绘制按钮和选项,处理鼠标选择关卡、敌人数、游戏模式 |
| 碰撞处理模块 | handle_collisions() | 检测子弹与墙壁、子弹与坦克的碰撞,触发墙破坏、坦克受伤/死亡、爆炸特效及加分 |
| 坦克分离算法 | separate_tanks() | 强制推开重叠的坦克,防止卡死 |
| 主循环模块 | run() | 驱动游戏主循环,调用更新与绘制函数,维持帧率 |
(二)核心功能
- 游戏模式
单人模式:一名玩家(绿色坦克,方向键+空格)与AI敌方坦克对战。
双人合作模式:两名玩家(绿:WASD+空格;青:方向键+右Shift)共同对抗AI。
双人对战模式:两名玩家互相射击,无敌方坦克。 - 关卡难度系统
等级1:敌方速度2,射击延迟60帧,随机砖墙约15块。
等级2:敌方速度3,射击延迟45帧,随机砖墙约30块。
等级3:敌方速度3,射击延迟30帧,随机砖墙约50块。 - 随机障碍生成
每关重新生成砖墙位置,障碍数量随难度递增。
避开玩家和敌方出生点及其周围3×3区域,防止出生即被卡。 - 坦克操作与射击
移动:四方向独立控制,支持斜向移动(分轴处理)。
射击:独立于移动按键(空格/右Shift),子弹有冷却时间(15帧)。
无敌帧:玩家被击中后短暂无敌(90帧),期间闪烁显示。 - 碰撞与物理系统
坦克与边界、墙体、其他坦克的碰撞检测(移动时实时检测)。
子弹与墙体碰撞:墙体被摧毁(alive=False)。
子弹与坦克碰撞:
玩家子弹击中敌方 → 敌方消失,玩家加分(100分/个),播放爆炸特效。
敌方子弹击中玩家 → 玩家生命减1,若生命归零则死亡;合作模式下任一玩家死亡不影响另一玩家。
对战模式下,玩家子弹击中对方玩家 → 对方生命减1,生命归零则游戏结束并显示胜者。 - 生命与分数系统
每个玩家初始3条命,界面实时显示生命值。
合作/单人模式显示总分,双人对战不显示分数,只显示胜利方。 - 游戏流程控制
菜单界面:鼠标选择关卡(1-3)、敌方数量(3/5/7)、模式(单人/合作/对战),点击START开始。
游戏中:ESC键返回菜单,R键(游戏结束后)重新开始当前关卡的同一配置。
胜利/失败判定:
合作/单人:全灭敌方坦克 → 胜利;所有玩家生命归零 → 失败。
对战:某一玩家生命归零 → 另一方胜利。 - 视觉与特效
坦克绘制不同颜色及炮管方向指示。
无敌闪烁效果。
爆炸动画(橙色圆逐渐放大并淡出)。
砖墙纹理(棕色填充+灰色边框)。
(三)实现过程
源代码已分拆至下面的实验过程中
1.搭建Pygame环境
调用 pygame.init() 激活所有Pygame模块;定义屏幕宽高(800×600)、网格大小(40×40)、帧率(60 FPS);预设颜色RGB值和游戏参数(移动速度、子弹速度、冷却帧数、无敌帧数等);计算地图网格数量(20列 × 15行)。
点击查看代码
import pygame
import sys
import random
import math
# ---------- 初始化 ----------
pygame.init()
# ---------- 常量 ----------
SCREEN_WIDTH = 800
SCREEN_HEIGHT = 600
GRID_SIZE = 40
FPS = 60
# 颜色
COLOR_BLACK = (0, 0, 0)
COLOR_WHITE = (255, 255, 255)
COLOR_GREEN = (0, 255, 0)
COLOR_RED = (255, 0, 0)
COLOR_YELLOW = (255, 255, 0)
COLOR_GRAY = (128, 128, 128)
COLOR_BROWN = (160, 82, 45)
COLOR_ORANGE = (255, 165, 0)
COLOR_BLUE = (0, 0, 255)
COLOR_CYAN = (0, 255, 255)
# 游戏参数
BASE_ENEMY_SPEED = 2
BASE_ENEMY_SHOOT_DELAY = 60
PLAYER_SPEED = 4
BULLET_SPEED = 8
PLAYER_SHOOT_DELAY = 15
INVINCIBLE_DURATION = 90
MAP_WIDTH = SCREEN_WIDTH // GRID_SIZE # 20
MAP_HEIGHT = SCREEN_HEIGHT // GRID_SIZE # 15
点击查看代码
# ---------- 坦克基类绘制 ----------
class Tank:
def __init__(self, x, y, direction, color, speed, is_player=False):
self.x = x
self.y = y
self.direction = direction
self.color = color
self.speed = speed
self.is_player = is_player
self.width = GRID_SIZE
self.height = GRID_SIZE
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.shoot_cooldown = 0
def draw(self, screen):
pygame.draw.rect(screen, self.color, self.rect)
# 绘制炮管
if self.direction == 'up':
start = (self.x + self.width//2, self.y)
end = (self.x + self.width//2, self.y - 10)
elif self.direction == 'down':
start = (self.x + self.width//2, self.y + self.height)
end = (self.x + self.width//2, self.y + self.height + 10)
elif self.direction == 'left':
start = (self.x, self.y + self.height//2)
end = (self.x - 10, self.y + self.height//2)
else: # right
start = (self.x + self.width, self.y + self.height//2)
end = (self.x + self.width + 10, self.y + self.height//2)
pygame.draw.line(screen, COLOR_YELLOW, start, end, 4)
# ---------- 墙体绘制 ----------
class Wall:
def __init__(self, grid_x, grid_y):
self.grid_x = grid_x
self.grid_y = grid_y
self.x = grid_x * GRID_SIZE
self.y = grid_y * GRID_SIZE
self.rect = pygame.Rect(self.x, self.y, GRID_SIZE, GRID_SIZE)
self.alive = True
def draw(self, screen):
if self.alive:
pygame.draw.rect(screen, COLOR_BROWN, self.rect)
pygame.draw.rect(screen, COLOR_GRAY, self.rect, 2)
点击查看代码
class Tank:
# ... 接上面的 Tank 类
def update_rect(self):
self.rect.topleft = (self.x, self.y)
def move(self, dx, dy, walls, other_tanks):
# 水平移动
if dx != 0:
new_x = self.x + dx
new_rect = pygame.Rect(new_x, self.y, self.width, self.height)
can_move = True
# 边界
if new_x < 0 or new_x + self.width > SCREEN_WIDTH:
can_move = False
# 墙体
for wall in walls:
if new_rect.colliderect(wall.rect):
can_move = False
break
# 其他坦克
for tank in other_tanks:
if new_rect.colliderect(tank.rect):
can_move = False
break
if can_move:
self.x = new_x
# 垂直移动
if dy != 0:
new_y = self.y + dy
new_rect = pygame.Rect(self.x, new_y, self.width, self.height)
can_move = True
if new_y < 0 or new_y + self.height > SCREEN_HEIGHT:
can_move = False
for wall in walls:
if new_rect.colliderect(wall.rect):
can_move = False
break
for tank in other_tanks:
if new_rect.colliderect(tank.rect):
can_move = False
break
if can_move:
self.y = new_y
self.update_rect()
return True
# ---------- 坦克分离算法(在Game类中) ----------
class Game:
def separate_tanks(self, max_iter=5):
all_tanks = [p for p in self.players if p.alive] + self.enemies
for _ in range(max_iter):
any_overlap = False
for i in range(len(all_tanks)):
for j in range(i+1, len(all_tanks)):
t1, t2 = all_tanks[i], all_tanks[j]
if t1.rect.colliderect(t2.rect):
any_overlap = True
dx = t1.rect.centerx - t2.rect.centerx
dy = t1.rect.centery - t2.rect.centery
if dx == 0 and dy == 0:
dx, dy = 1, 1
length = math.hypot(dx, dy)
dx /= length
dy /= length
push = 3
t1.x += dx * push
t1.y += dy * push
t2.x -= dx * push
t2.y -= dy * push
t1.x = max(0, min(SCREEN_WIDTH - t1.width, t1.x))
t1.y = max(0, min(SCREEN_HEIGHT - t1.height, t1.y))
t2.x = max(0, min(SCREEN_WIDTH - t2.width, t2.x))
t2.y = max(0, min(SCREEN_HEIGHT - t2.height, t2.y))
t1.update_rect()
t2.update_rect()
if not any_overlap:
break
点击查看代码
class Bullet:
def __init__(self, x, y, direction, is_player, owner=None):
self.x = x - 3
self.y = y - 3
self.direction = direction
self.is_player = is_player
self.owner = owner
self.width = 6
self.height = 6
self.rect = pygame.Rect(self.x, self.y, self.width, self.height)
self.speed = BULLET_SPEED
self.alive = True
def update(self):
if self.direction == 'up':
self.y -= self.speed
elif self.direction == 'down':
self.y += self.speed
elif self.direction == 'left':
self.x -= self.speed
else:
self.x += self.speed
self.rect.topleft = (self.x, self.y)
if (self.x + self.width < 0 or self.x > SCREEN_WIDTH or
self.y + self.height < 0 or self.y > SCREEN_HEIGHT):
self.alive = False
def draw(self, screen):
pygame.draw.rect(screen, COLOR_YELLOW, self.rect)
class Tank:
# ... 接上面 Tank 类
def can_shoot(self):
return self.shoot_cooldown == 0
def shoot(self, bullet_group):
if not self.can_shoot():
return None
center_x = self.x + self.width // 2
center_y = self.y + self.height // 2
bullet = Bullet(center_x, center_y, self.direction, self.is_player, owner=self)
bullet_group.append(bullet)
return bullet
点击查看代码
class EnemyTank(Tank):
def __init__(self, x, y, speed, shoot_delay):
super().__init__(x, y, random.choice(['up', 'down', 'left', 'right']), COLOR_RED, speed, is_player=False)
self.shoot_cooldown = random.randint(0, shoot_delay//2)
self.change_dir_counter = random.randint(30, 90)
self.shoot_delay = shoot_delay
def update(self, walls, other_tanks, bullet_group):
if self.shoot_cooldown > 0:
self.shoot_cooldown -= 1
self.change_dir_counter -= 1
if self.change_dir_counter <= 0:
self.direction = random.choice(['up', 'down', 'left', 'right'])
self.change_dir_counter = random.randint(30, 90)
dx, dy = 0, 0
if self.direction == 'up':
dy = -self.speed
elif self.direction == 'down':
dy = self.speed
elif self.direction == 'left':
dx = -self.speed
else:
dx = self.speed
if dx != 0 or dy != 0:
self.move(dx, dy, walls, other_tanks)
if self.can_shoot() and random.randint(1, 100) < 3:
self.shoot(bullet_group)
self.shoot_cooldown = self.shoot_delay
点击查看代码
class Game:
def __init__(self):
self.state = "MENU" # "MENU" 或 "PLAYING"
# ... 其他初始化
def run(self):
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
if self.state == "MENU":
self.handle_menu_events(event)
else:
self.handle_game_events(event)
if self.state == "MENU":
self.draw_menu()
else:
self.update_game()
self.draw_game()
self.clock.tick(FPS)
def handle_menu_events(self, event):
if event.type == pygame.MOUSEBUTTONDOWN:
pos = pygame.mouse.get_pos()
# 按钮区域判断(见步骤7)
if self.buttons["start"].collidepoint(pos):
self.reset_game()
self.state = "PLAYING"
def handle_game_events(self, event):
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
self.state = "MENU"
if event.key == pygame.K_r and self.game_over:
self.reset_game()
点击查看代码
class Game:
def __init__(self):
self.selected_level = 1
self.selected_enemy_count = 3
self.selected_mode = "SINGLE" # "SINGLE", "COOP", "VS"
# 按钮矩形
self.buttons = {
"level_down": pygame.Rect(220, 150, 40, 40),
"level_up": pygame.Rect(300, 150, 40, 40),
"enemy_down": pygame.Rect(220, 220, 40, 40),
"enemy_up": pygame.Rect(300, 220, 40, 40),
"mode_single": pygame.Rect(140, 290, 100, 40),
"mode_coop": pygame.Rect(260, 290, 100, 40),
"mode_vs": pygame.Rect(380, 290, 100, 40),
"start": pygame.Rect(300, 400, 200, 50)
}
def reset_game(self):
# 根据模式创建玩家
self.players.clear()
if self.selected_mode == "SINGLE":
p1 = PlayerTank((MAP_WIDTH//2 - 1)*GRID_SIZE, (MAP_HEIGHT-2)*GRID_SIZE,
COLOR_GREEN, {
'left': pygame.K_LEFT, 'right': pygame.K_RIGHT,
'up': pygame.K_UP, 'down': pygame.K_DOWN,
'shoot': pygame.K_SPACE
}, player_id=1)
self.players.append(p1)
elif self.selected_mode == "COOP":
p1 = PlayerTank((MAP_WIDTH//2 - 2)*GRID_SIZE, (MAP_HEIGHT-2)*GRID_SIZE,
COLOR_GREEN, {
'left': pygame.K_a, 'right': pygame.K_d,
'up': pygame.K_w, 'down': pygame.K_s,
'shoot': pygame.K_SPACE
}, player_id=1)
p2 = PlayerTank((MAP_WIDTH//2 + 1)*GRID_SIZE, (MAP_HEIGHT-2)*GRID_SIZE,
COLOR_CYAN, {
'left': pygame.K_LEFT, 'right': pygame.K_RIGHT,
'up': pygame.K_UP, 'down': pygame.K_DOWN,
'shoot': pygame.K_RSHIFT
}, player_id=2)
self.players.extend([p1, p2])
else: # VS
p1 = PlayerTank((MAP_WIDTH//2 - 2)*GRID_SIZE, (MAP_HEIGHT-2)*GRID_SIZE,
COLOR_GREEN, {
'left': pygame.K_a, 'right': pygame.K_d,
'up': pygame.K_w, 'down': pygame.K_s,
'shoot': pygame.K_SPACE
}, player_id=1)
p2 = PlayerTank((MAP_WIDTH//2 + 1)*GRID_SIZE, (MAP_HEIGHT-2)*GRID_SIZE,
COLOR_CYAN, {
'left': pygame.K_LEFT, 'right': pygame.K_RIGHT,
'up': pygame.K_UP, 'down': pygame.K_DOWN,
'shoot': pygame.K_RSHIFT
}, player_id=2)
self.players.extend([p1, p2])
# 根据关卡设置敌方参数(仅在非VS模式)
if self.selected_mode != "VS":
if self.selected_level == 1:
enemy_speed = BASE_ENEMY_SPEED
enemy_shoot_delay = BASE_ENEMY_SHOOT_DELAY
elif self.selected_level == 2:
enemy_speed = 3
enemy_shoot_delay = int(BASE_ENEMY_SHOOT_DELAY * 0.75)
else:
enemy_speed = 3
enemy_shoot_delay = int(BASE_ENEMY_SHOOT_DELAY * 0.5)
# 生成敌方坦克...
点击查看代码
def generate_random_walls(level, safe_cells):
wall_counts = {1: 15, 2: 30, 3: 50}
count = wall_counts.get(level, 15)
all_cells = [(x, y) for x in range(MAP_WIDTH) for y in range(MAP_HEIGHT)]
available = [cell for cell in all_cells if cell not in safe_cells]
chosen = random.sample(available, min(count, len(available)))
walls = []
for (gx, gy) in chosen:
walls.append(Wall(gx, gy))
return walls
# 在 Game.reset_game() 中调用
def reset_game(self):
# 确定安全格子(玩家和敌方初始位置及其周围)
safe_cells = set()
# 玩家区域
player_start_positions = [...]
for (gx, gy) in player_start_positions:
for dx in range(-1, 2):
for dy in range(-1, 2):
nx, ny = gx+dx, gy+dy
if 0 <= nx < MAP_WIDTH and 0 <= ny < MAP_HEIGHT:
safe_cells.add((nx, ny))
# 敌方区域(非VS模式)
if self.selected_mode != "VS":
enemy_start_positions = [(3,2), (8,2), (13,2), (5,5), (10,5), (2,8), (15,8)]
for i in range(min(self.selected_enemy_count, len(enemy_start_positions))):
gx, gy = enemy_start_positions[i]
for dx in range(-1, 2):
for dy in range(-1, 2):
nx, ny = gx+dx, gy+dy
if 0 <= nx < MAP_WIDTH and 0 <= ny < MAP_HEIGHT:
safe_cells.add((nx, ny))
# 生成随机墙体
self.walls = generate_random_walls(self.selected_level, safe_cells)
点击查看代码
class Game:
def draw_game(self):
self.screen.fill(COLOR_BLACK)
# 绘制墙壁、坦克、子弹、爆炸(略)
# UI文本
y = 10
for i, p in enumerate(self.players):
label = f"P{i+1}" if self.selected_mode != "SINGLE" else "Player"
lives = p.lives if p.alive else 0
lives_text = self.font.render(f"{label} Lives: {lives}", True, COLOR_WHITE)
self.screen.blit(lives_text, (10, y))
y += 30
if self.selected_mode != "VS":
total_score = sum(p.score for p in self.players)
score_text = self.font.render(f"Score: {total_score}", True, COLOR_WHITE)
self.screen.blit(score_text, (10, y))
enemies_text = self.font.render(f"Enemies: {len(self.enemies)}", True, COLOR_WHITE)
self.screen.blit(enemies_text, (10, y+30))
# 游戏结束文字
if self.game_over:
msg = self.winner_text + " Press R / ESC"
color = COLOR_GREEN if "win" in self.winner_text.lower() or "Victory" in self.winner_text else COLOR_RED
text = self.big_font.render(msg, True, color)
rect = text.get_rect(center=(SCREEN_WIDTH//2, SCREEN_HEIGHT//2))
self.screen.blit(text, rect)
pygame.display.flip()
点击查看代码
# 在 Game.update_game() 中,移动前后调用分离函数
def update_game(self):
if self.game_over:
return
self.separate_tanks() # 移动前分离
keys = pygame.key.get_pressed()
all_tanks = self.enemies + [p for p in self.players if p.alive]
for p in self.players:
if p.alive:
other = [t for t in all_tanks if t is not p]
p.update(keys, self.walls, other, self.bullets)
for e in self.enemies:
other = [t for t in all_tanks if t is not e]
e.update(self.walls, other, self.bullets)
for b in self.bullets:
b.update()
self.handle_collisions()
self.separate_tanks() # 移动后再次分离,防止重叠
五、全课内容总结
1.Python的含义
Python是一种跨平台、面向对象的高级程序设计语言,具有简洁、易读、丰富的第三方库等特点。它可以运行在Windows、Linux等多种操作系统上,变量无需提前声明类型,由系统自动推导。此外,我们还了解了Python的发展背景、应用场景及开发环境的搭建。
2.基础语法
注释:单行用 #,多行用 """。
保留字:像 if、else、for、def 这些不能拿来当变量名。
数据类型:整数、浮点数、字符串、布尔值、复数啥的,还可以用 int() 4.这种强行转换。
输入输出:input() 用来接收用户输入,print() 用来输出。
运算符:加减乘除、取余、比较、逻辑运算等。
代码规范:Python用缩进来表示代码块,这个写的时候要特别注意。
3.流程控制
条件判断:if、elif、else,根据条件走不同分支。
循环:while 循环,for 循环。
控制关键字:break 跳出循环,continue 跳过本次,pass 占位。
4.序列
列表:用 [],有序、可以改,能增删改查。
元组:用 (),有序、不能改。
字典:用 {},键值对形式,有点像查字典。
集合:也是 {},但里面的元素不能重复,而且无序。
切片:比如 sname[0:3:2],第一个数字是起始位置,第二个是结束位置(不包含),第三个是步长,左闭右开。
排序:list.sort() 直接改原列表,sorted() 会生成一个新副本。
5.字符串与正则表达式
字符串就是一串字符,用引号包起来。
可以用下标和切片来取一部分:字符串[起始:结束],下标从0开始。
常用方法:split() 分割、join() 合并、replace() 替换、strip() 去空格、count() 统计出现次数、find() 查找位置、upper()/lower() 大小写转换。
正则表达式:用来匹配或替换字符串。
6.函数
用 def 定义函数。
参数:有位置参数、关键字参数、默认参数,还有可变参数。
返回值用 return,可以一次返回多个值。
7.其他技术
socket:Socket=IP+端口
Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求,使主机间或者一台计算机上的进程间可以通讯。
爬虫:爬取 + 解析。
用到的技术:网络请求模块、解析库;如果网站有反爬虫,可以通过加请求头信息等方式绕过。
(能回忆起来的就这些,求老师放过)
六、感想体会与建议
(一)感想体会
作为一个文科生,从对理科“深恶痛绝”到开开心心上Python,这门课真的给我留下了很深的印象。虽然只靠一学期的公选课可能只能学到一些皮毛,但确实已经带我对Python这门语言有了基本的了解,让我在未来面对Python的应用时可以有备而来,这对于数字化时代下的文科生是宝贵的能力。每次上课,我都会为代码的成功运行而欣喜,虽然它并不是我亲自写的,但我真切感受到我作为一个文科生,与严谨的代码和数字并不是永远割裂开的。每次经过老师指导调试代码的时候,我知道我虽然和老师不在同一个维度上,但在这时候想要写好代码精进自己的作业的心是真切的。快乐的时光总是短暂的,最后的课上老师放着电教四门口的丁香与桃花,不由得有些小破防,感慨着“年年岁岁花相似,岁岁年年人不同”,那就只能把幽默风趣热情温柔严谨细致的老师留给学弟学妹了(doge)。
(二)建议
老师真的已经超级超级好了,真的是为我们带来了更适合文科宝宝体质的Python课,如果硬要说建议的话,对于Python的基础功能和语言能不能设计一些实操类的小项目,让同学们能多动动手加深一下印象呢。剩下的真的没什么了,再要说就是老师一定要多喝热水,注意休息(
真的非常非常感谢老师啊,最后祝老师身体健康、事业顺利、家庭幸福、喜乐安宁!

浙公网安备 33010602011771号