diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..94a25f7
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第10讲识图精灵/50识图精灵讲义.pdf b/第10讲识图精灵/50识图精灵讲义.pdf
new file mode 100644
index 0000000..a5bf4c6
Binary files /dev/null and b/第10讲识图精灵/50识图精灵讲义.pdf differ
diff --git a/第10讲识图精灵/识图精灵.png b/第10讲识图精灵/识图精灵.png
new file mode 100644
index 0000000..9cde2b4
Binary files /dev/null and b/第10讲识图精灵/识图精灵.png differ
diff --git a/第10讲识图精灵/课堂成果/安装第三方库.py b/第10讲识图精灵/课堂成果/安装第三方库.py
new file mode 100644
index 0000000..88730ac
--- /dev/null
+++ b/第10讲识图精灵/课堂成果/安装第三方库.py
@@ -0,0 +1,5 @@
+# 点击运行【安装第三方库.py】,即可安装本课用到的第三方库
+
+import pip
+pip.main(['install','baidu-aip'])
+pip.main(['install','chardet'])
\ No newline at end of file
diff --git a/第10讲识图精灵/课堂成果/花.png b/第10讲识图精灵/课堂成果/花.png
new file mode 100644
index 0000000..18d4788
Binary files /dev/null and b/第10讲识图精灵/课堂成果/花.png differ
diff --git a/第10讲识图精灵/课堂成果/识图精灵.py b/第10讲识图精灵/课堂成果/识图精灵.py
new file mode 100644
index 0000000..0638780
--- /dev/null
+++ b/第10讲识图精灵/课堂成果/识图精灵.py
@@ -0,0 +1,45 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+
+from aip import AipImageClassify # 调用百度智能模块中图像识别类方法
+
+# 填写个人的授权使用信息
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+
+# 准备【图像识别器】
+client = AipImageClassify(APP_ID, API_KEY, SECRET_KEY)
+
+# 读取图片文件并返回二进制数据
+def read_img(file):
+ with open(file, "rb") as f:
+ return f.read()
+
+# 调用【图像识别器】并返回结果
+def find_img(img):
+ # 返回的信息是字典类型,结果保存在键‘result’的值中
+ return client.advancedGeneral(img)
+
+# 打印识别结果
+def print_result(res):
+ if 'result' in res:
+ for i in res['result']:
+ if i['score'] >= 0.6:
+ print(f"结果为 {i['keyword']} , 相似度为 {i['score']*100:.2f}% ")
+ else:
+ # 失败响应提示信息
+ print(f"识别失败, 错误码: {res.get('error_code')}, 错误信息: {res.get('error_msg')}")
+
+# 主函数
+data = read_img("花.png")
+result = find_img(data)
+print(f"API返回结果:{result}\n")
+print_result(result)
+print('识别完毕')
+
diff --git a/第11讲语音识别与合成/51语音识别与合成讲义.pdf b/第11讲语音识别与合成/51语音识别与合成讲义.pdf
new file mode 100644
index 0000000..17cabe8
Binary files /dev/null and b/第11讲语音识别与合成/51语音识别与合成讲义.pdf differ
diff --git a/第11讲语音识别与合成/语音识别与合成.png b/第11讲语音识别与合成/语音识别与合成.png
new file mode 100644
index 0000000..7998c3c
Binary files /dev/null and b/第11讲语音识别与合成/语音识别与合成.png differ
diff --git a/第11讲语音识别与合成/课堂成果/安装第三方库.py b/第11讲语音识别与合成/课堂成果/安装第三方库.py
new file mode 100644
index 0000000..7b45a13
--- /dev/null
+++ b/第11讲语音识别与合成/课堂成果/安装第三方库.py
@@ -0,0 +1,7 @@
+# 点击运行【安装第三方库.py】,即可安装本课用到的第三方库
+
+import pip
+pip.main(['install','pyaudio'])
+pip.main(['install','keyboard'])
+pip.main(['install','baidu-aip'])
+pip.main(['install','chardet'])
\ No newline at end of file
diff --git a/第11讲语音识别与合成/课堂成果/录音工具.py b/第11讲语音识别与合成/课堂成果/录音工具.py
new file mode 100644
index 0000000..5939e03
--- /dev/null
+++ b/第11讲语音识别与合成/课堂成果/录音工具.py
@@ -0,0 +1,48 @@
+# 按下's'开始录制,按下'q'停止录制,文件存为'pyaudio.wav'
+
+import pyaudio
+import wave
+import keyboard
+
+# 从麦克风录制音频并保存到指定文件
+
+# 创建 PyAudio 对象
+p = pyaudio.PyAudio()
+# 打开音频流,设置格式、声道数、采样率等参数
+stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=1024)
+# 创建一个空列表用于存储录制的音频数据
+frames = []
+# 打印提示信息,表示开始录制
+print("Press 's' to start recording...")
+# 等待用户按下 's' 键开始录制
+keyboard.wait('s')
+# 打印提示信息,表示开始录制
+print("Recording...")
+# 开始录制
+while True:
+ # 从音频流中读取 1024 个数据样本
+ data = stream.read(1024)
+ # 将数据添加到 frames 列表中
+ frames.append(data)
+ # 检查是否按下 'q' 键结束录制
+ if keyboard.is_pressed('q'):
+ break
+# 打印提示信息,表示录制已停止
+print("Recording stopped.")
+# 停止音频流
+stream.stop_stream()
+# 关闭音频流
+stream.close()
+# 终止 PyAudio 对象
+p.terminate()
+# 打开文件,以写入模式打开
+wf = wave.open("pyaudio.wav", 'wb')
+# 设置音频的声道数、采样宽度和采样率
+wf.setnchannels(1)
+wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
+wf.setframerate(16000)
+# 将 frames 列表中的所有数据连接成一个字节串,并写入文件
+wf.writeframes(b''.join(frames))
+# 关闭文件
+wf.close()
+print("Done")
\ No newline at end of file
diff --git a/第11讲语音识别与合成/课堂成果/语音合成.py b/第11讲语音识别与合成/课堂成果/语音合成.py
new file mode 100644
index 0000000..aba431e
--- /dev/null
+++ b/第11讲语音识别与合成/课堂成果/语音合成.py
@@ -0,0 +1,37 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+
+from aip import AipSpeech
+
+# 定义常量
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+
+# 准备【语音合成器】
+client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
+
+# 要合成的文本
+text = "你好,我是P仔,很高兴认识你"
+
+# 调用【语音合成器】
+res = client.synthesis(text, 'zh', 1, {
+ 'vol': 5, # 音量
+ 'per': 0, # 发音人
+ 'spd': 5 # 语速
+})
+print(res)
+
+# 判断调用是否成功
+if not isinstance(res, dict):
+ # 获取合成音频结果
+ with open('save.mp3', 'wb') as f:
+ f.write(res)
+ print('音频文件保存成功')
+else:
+ print('调用失败, 错误码: %s, 错误信息: %s' % (res['err_no'], res['err_msg']))
diff --git a/第11讲语音识别与合成/课堂成果/语音识别.py b/第11讲语音识别与合成/课堂成果/语音识别.py
new file mode 100644
index 0000000..6e6285c
--- /dev/null
+++ b/第11讲语音识别与合成/课堂成果/语音识别.py
@@ -0,0 +1,36 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+
+from aip import AipSpeech
+
+# 定义常量
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+
+# 准备【语音识别器】
+client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
+
+# 定义要识别的语音文件
+file = 'pyaudio.wav'
+
+# 读取音频文件
+def read_audio(file):
+ with open(file, 'rb') as f:
+ return f.read()
+
+# 调用【语音识别器】
+res = client.asr(read_audio(file), 'wav', 16000, {
+ 'dev_pid': 1537 # 普通话识别
+})
+
+# 打印返回结果
+if 'result' in res:
+ print("识别结果:", res['result'][0])
+else:
+ print("识别失败:", res)
diff --git a/第11讲语音识别与合成/课堂成果/课后作业-柯南变声领带.py b/第11讲语音识别与合成/课堂成果/课后作业-柯南变声领带.py
new file mode 100644
index 0000000..8647ef3
--- /dev/null
+++ b/第11讲语音识别与合成/课堂成果/课后作业-柯南变声领带.py
@@ -0,0 +1,114 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+'''柯南变声领结
+
+任务描述:
+
+变身名侦探柯南,制作一个神奇的变声领结!你将录制一段音频,通过语音识别转换成文字,再通过语音合成器将文字变成机器人音调!快来挑战吧,看谁的变声音效最酷!
+
+作业要求:
+
+1. 将课堂代码【语音识别】和【语音合成】整合到一个文件中
+
+2. 文字合成语音,选择喜欢的“语音人”'''
+import pyaudio
+import wave
+import keyboard
+from aip import AipSpeech
+
+# 从麦克风录制音频并保存到指定文件
+
+# 创建 PyAudio 对象
+p = pyaudio.PyAudio()
+# 打开音频流,设置格式、声道数、采样率等参数
+stream = p.open(format=pyaudio.paInt16, channels=1, rate=16000, input=True, frames_per_buffer=1024)
+# 创建一个空列表用于存储录制的音频数据
+frames = []
+# 打印提示信息,表示开始录制
+print("Press 's' to start recording...")
+# 等待用户按下 's' 键开始录制
+keyboard.wait('s')
+# 打印提示信息,表示开始录制
+print("Recording...")
+# 开始录制
+while True:
+ # 从音频流中读取 1024 个数据样本
+ data = stream.read(1024)
+ # 将数据添加到 frames 列表中
+ frames.append(data)
+ # 检查是否按下 'q' 键结束录制
+ if keyboard.is_pressed('q'):
+ break
+# 打印提示信息,表示录制已停止
+print("Recording stopped.")
+# 停止音频流
+stream.stop_stream()
+# 关闭音频流
+stream.close()
+# 终止 PyAudio 对象
+p.terminate()
+# 打开文件,以写入模式打开
+wf = wave.open("pyaudio.wav", 'wb')
+# 设置音频的声道数、采样宽度和采样率
+wf.setnchannels(1)
+wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
+wf.setframerate(16000)
+# 将 frames 列表中的所有数据连接成一个字节串,并写入文件
+wf.writeframes(b''.join(frames))
+# 关闭文件
+wf.close()
+print("Done")
+
+# 定义常量
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+
+# 准备【语音工具】
+client = AipSpeech(APP_ID, API_KEY, SECRET_KEY)
+
+# 定义要识别的语音文件
+file = 'pyaudio.wav'
+
+
+# 读取音频文件
+def read_audio(file):
+ with open(file, 'rb') as f:
+ return f.read()
+
+
+# 调用语音识别接口
+res = client.asr(read_audio(file), 'wav', 16000, {
+ 'dev_pid': 1537 # 普通话识别
+})
+
+# 打印返回结果
+if 'result' in res:
+ print("识别结果:", res['result'][0])
+else:
+ print("识别失败:", res)
+
+# 要合成的文本
+text = res['result'][0]
+
+# 调用语音合成接口
+res = client.synthesis(text, 'zh', 1, {
+ 'vol': 5, # 音量
+ 'per': 0, # 发音人
+ 'spd': 5 # 语速
+})
+print(res)
+
+# 判断调用是否成功
+if not isinstance(res, dict):
+ # 获取合成音频结果
+ with open('save.mp3', 'wb') as f:
+ f.write(res)
+ print('音频文件保存成功')
+else:
+ print('调用失败, 错误码: %s, 错误信息: %s' % (res['err_no'], res['err_msg']))
\ No newline at end of file
diff --git a/第12讲你的颜值有几分一/52你的颜值有几分一讲义.pdf b/第12讲你的颜值有几分一/52你的颜值有几分一讲义.pdf
new file mode 100644
index 0000000..80007f4
Binary files /dev/null and b/第12讲你的颜值有几分一/52你的颜值有几分一讲义.pdf differ
diff --git a/第12讲你的颜值有几分一/你的颜值有几分一.png b/第12讲你的颜值有几分一/你的颜值有几分一.png
new file mode 100644
index 0000000..5106251
Binary files /dev/null and b/第12讲你的颜值有几分一/你的颜值有几分一.png differ
diff --git a/第12讲你的颜值有几分一/课堂成果/你的颜值有几分1.py b/第12讲你的颜值有几分一/课堂成果/你的颜值有几分1.py
new file mode 100644
index 0000000..4271e6f
--- /dev/null
+++ b/第12讲你的颜值有几分一/课堂成果/你的颜值有几分1.py
@@ -0,0 +1,114 @@
+'''
+【一、导入库】
+'''
+# 预置内容,请勿改动
+import io
+import base64
+import cv2
+# 请在下方编写代码
+import tkinter as tk
+from PIL import Image, ImageTk
+from tkinter import filedialog
+
+'''
+【二、初始化】(变量初始化、窗口初始化、API配置信息)
+'''
+# 预置内容,请勿改动
+cap = None
+imgtk = None
+update_id = None
+# 请在下方编写代码
+# 初始化Tkinter
+root = tk.Tk()
+root.geometry('700x700')
+root.title('颜值测评')
+root.resizable(0, 0)
+
+'''
+【三、函数】
+'''
+# 预置内容,请勿改动 图像 --> 字节数据 --> Base64 编码格式
+def img_to_bytes(photoimg):
+ # 将 PhotoImage 转换为 PIL 图像
+ pil_img = ImageTk.getimage(photoimg)
+ # 如果图像具有 Alpha 信道(透明度),则转换为 RGB
+ if pil_img.mode == 'RGBA':
+ pil_img = pil_img.convert('RGB')
+ # 保存到字节缓冲区
+ buffer = io.BytesIO()
+ pil_img.save(buffer, format='JPEG')
+ img_data = buffer.getvalue()
+ return base64.b64encode(img_data).decode('utf-8')
+# 预置内容,请勿改动 打开摄像头
+def open_camera():
+ global cap, update_id
+ cap = cv2.VideoCapture(0)
+ if not cap.isOpened():
+ print("无法打开摄像头")
+ return
+ def update_frame():
+ global cap, update_id
+ ret, frame = cap.read()
+ if frame is None:
+ return
+ frame = cv2.resize(frame, (250, 250))
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ img = Image.fromarray(frame)
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+ update_id = lab_photo.after(10, update_frame)
+ update_frame()
+# 预置内容,请勿改动 关闭摄像头
+def close_camera():
+ global cap, update_id
+ if cap is not None:
+ cap.release()
+ cap = None
+ if update_id is not None:
+ lab_photo.after_cancel(update_id)
+ update_id = None
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 请在下方编写代码
+# 加载本地图片
+def load():
+ file_path = filedialog.askopenfilename() # 打开一个文件选择对话框
+ if file_path:
+ close_camera()
+ img = Image.open(file_path)
+ img = img.resize((250, 250))
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 颜值检测开始
+def ok():
+ pass
+
+'''
+【四、组件配置】
+'''
+# 设置背景图
+bg_image = tk.PhotoImage(file = '测颜值.png')
+bg_label = tk.Label(root, image = bg_image)
+bg_label.place(x=0, y=0, relwidth=1, relheight=1)
+# 设置缩略图
+pic0 = Image.open('缩略图.png')
+pic0 = pic0.resize((250, 250))
+pic0_image = ImageTk.PhotoImage(pic0)
+lab_photo = tk.Label(root, image=pic0_image)
+lab_photo.place(x=223, y=223)
+# 本地上传按钮
+btn_load = tk.Button(root, text="本地上传", command=load, width=15, height=2, font=("楷体", 12))
+btn_load.place(x=115, y=625)
+# 拍照上传按钮
+btn_cam = tk.Button(root, text="拍照上传", command=open_camera, width=15, height=2, font=("楷体", 12))
+btn_cam.place(x=300, y=625)
+# 开始测评按钮
+btn_enter = tk.Button(root, text="点击开测!", command=ok, width=15, height=2, font=("楷体", 12))
+btn_enter.place(x=485, y=625)
+
+'''
+【五、启动事件循环】
+'''
+root.mainloop()
\ No newline at end of file
diff --git a/第12讲你的颜值有几分一/课堂成果/测颜值.png b/第12讲你的颜值有几分一/课堂成果/测颜值.png
new file mode 100644
index 0000000..93b7217
Binary files /dev/null and b/第12讲你的颜值有几分一/课堂成果/测颜值.png differ
diff --git a/第12讲你的颜值有几分一/课堂成果/缩略图.png b/第12讲你的颜值有几分一/课堂成果/缩略图.png
new file mode 100644
index 0000000..e786152
Binary files /dev/null and b/第12讲你的颜值有几分一/课堂成果/缩略图.png differ
diff --git a/第12讲你的颜值有几分一/课堂成果/课后作业-本地图片浏览器.py b/第12讲你的颜值有几分一/课堂成果/课后作业-本地图片浏览器.py
new file mode 100644
index 0000000..3bfdb77
--- /dev/null
+++ b/第12讲你的颜值有几分一/课堂成果/课后作业-本地图片浏览器.py
@@ -0,0 +1,43 @@
+'''本地图片浏览器
+
+任务描述:
+
+创建一个简单的图片浏览器。用户可以从计算机中选择一张图片,并在窗口中指定位置显示。
+
+
+
+作业要求:
+
+1. 界面:包括【选择】按钮和一个图片显示区域(300*300)
+
+2. 加载本地图片:使用文件对话框让用户选择一张本地图片
+
+3. 图片缩放:选中的图片进行缩放来匹配显示区域
+
+4. 更新显示:选择新图片后,界面应更新所选图片'''
+import tkinter as tk
+from PIL import Image, ImageTk
+from tkinter import filedialog
+
+def load():
+ file_path = filedialog.askopenfilename()
+ if file_path:
+ img = Image.open(file_path)
+ img = img.resize((300, 300)) # 缩放图片
+ imgtk = ImageTk.PhotoImage(img)
+ label.config(image=imgtk)
+ label.image = imgtk
+
+root = tk.Tk()
+root.title("本地图片浏览器")
+root.geometry("350x350")
+
+# 显示图片区域
+label = tk.Label(root)
+label.pack()
+
+# 按钮用于选择图片
+button = tk.Button(root, text="选择图片", command=load)
+button.pack()
+
+root.mainloop()
\ No newline at end of file
diff --git a/第13讲你的颜值有几分二/53你的颜值有几分二讲义.pdf b/第13讲你的颜值有几分二/53你的颜值有几分二讲义.pdf
new file mode 100644
index 0000000..3e35913
Binary files /dev/null and b/第13讲你的颜值有几分二/53你的颜值有几分二讲义.pdf differ
diff --git a/第13讲你的颜值有几分二/你的颜值有几分二.png b/第13讲你的颜值有几分二/你的颜值有几分二.png
new file mode 100644
index 0000000..e514651
Binary files /dev/null and b/第13讲你的颜值有几分二/你的颜值有几分二.png differ
diff --git a/第13讲你的颜值有几分二/课堂成果/你的颜值有几分2.py b/第13讲你的颜值有几分二/课堂成果/你的颜值有几分2.py
new file mode 100644
index 0000000..e00fbd2
--- /dev/null
+++ b/第13讲你的颜值有几分二/课堂成果/你的颜值有几分2.py
@@ -0,0 +1,154 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+
+
+'''
+【一、导入库】
+'''
+# 预置内容,请勿改动
+import io
+import base64
+import cv2
+# 请在下方编写代码
+import tkinter as tk
+from PIL import Image, ImageTk
+from tkinter import filedialog, messagebox
+from aip import AipFace
+
+
+'''
+【二、初始化】(变量初始化、窗口初始化、API配置信息)
+'''
+# 预置内容,请勿改动
+cap = None
+imgtk = None
+update_id = None
+# 请在下方编写代码
+# 初始化Tkinter
+root = tk.Tk()
+root.geometry('700x700')
+root.title('颜值测评')
+root.resizable(0, 0)
+# 百度AI的API配置信息
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+client = AipFace(APP_ID, API_KEY, SECRET_KEY)
+
+
+'''
+【三、函数】
+'''
+# 预置内容,请勿改动 图像 --> 字节数据 --> Base64 编码格式
+def img_to_bytes(photoimg):
+ # 将 PhotoImage 转换为 PIL 图像
+ pil_img = ImageTk.getimage(photoimg)
+ # 如果图像具有 Alpha 信道(透明度),则转换为 RGB
+ if pil_img.mode == 'RGBA':
+ pil_img = pil_img.convert('RGB')
+ # 保存到字节缓冲区
+ buffer = io.BytesIO()
+ pil_img.save(buffer, format='JPEG')
+ img_data = buffer.getvalue()
+ return base64.b64encode(img_data).decode('utf-8')
+# 预置内容,请勿改动 打开摄像头
+def open_camera():
+ global cap, update_id
+ cap = cv2.VideoCapture(0)
+ if not cap.isOpened():
+ print("无法打开摄像头")
+ return
+ def update_frame():
+ global cap, update_id
+ ret, frame = cap.read()
+ if frame is None:
+ return
+ frame = cv2.resize(frame, (250, 250))
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ img = Image.fromarray(frame)
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+ update_id = lab_photo.after(10, update_frame)
+ update_frame()
+# 预置内容,请勿改动 关闭摄像头
+def close_camera():
+ global cap, update_id
+ if cap is not None:
+ cap.release()
+ cap = None
+ if update_id is not None:
+ lab_photo.after_cancel(update_id)
+ update_id = None
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 请在下方编写代码
+# 加载本地图片
+def load():
+ file_path = filedialog.askopenfilename() # 打开一个文件选择对话框
+ if file_path:
+ close_camera()
+ img = Image.open(file_path)
+ img = img.resize((250, 250))
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 颜值检测开始
+def ok():
+ # 判断 lab_photo 对象是否具有属性 imgtk
+ if not hasattr(lab_photo, 'imgtk'):
+ messagebox.showerror("错误", "没有显示图片,无法进行颜值测试")
+ return
+ img_base64 = img_to_bytes(lab_photo.imgtk) # 将图片转为Base64
+ imageType = "BASE64" # 设置图片类型
+ options = {"face_field":"age,gender,face_shape,emotion,beauty"}
+ result = client.detect(img_base64, imageType, options)
+ if 'error_msg' in result and result['error_msg'] == 'pic not has face':
+ messagebox.showerror("错误", "图像中未检测到人脸")
+ return
+ if 'result' in result and 'face_list' in result['result']:
+ # 解析结果
+ age = result['result']['face_list'][0]['age']
+ gender = result['result']['face_list'][0]['gender']['type']
+ face_shape = result['result']['face_list'][0]['face_shape']['type']
+ emotion = result['result']['face_list'][0]['emotion']['type']
+ beauty = result['result']['face_list'][0]['beauty']
+ # 构造结果字符串
+ output_str=f"年龄:{age}\n性别:{gender}\n脸型:{face_shape}\n情绪:{emotion}\n颜值:{beauty}"
+ # 使用对话框显示结果
+ messagebox.showinfo("颜值测评结果", output_str)
+ else:
+ messagebox.showerror("错误", "检测失败,请重试")
+
+'''
+【四、组件配置】
+'''
+# 设置背景图
+bg_image = tk.PhotoImage(file = '测颜值.png')
+bg_label = tk.Label(root, image = bg_image)
+bg_label.place(x=0, y=0, relwidth=1, relheight=1)
+# 设置缩略图
+pic0 = Image.open('缩略图.png')
+pic0 = pic0.resize((250, 250))
+pic0_image = ImageTk.PhotoImage(pic0)
+lab_photo = tk.Label(root, image=pic0_image)
+lab_photo.place(x=223, y=223)
+# 本地上传按钮
+btn_load = tk.Button(root, text="本地上传", command=load, width=15, height=2, font=("楷体", 12))
+btn_load.place(x=115, y=625)
+# 拍照上传按钮
+btn_cam = tk.Button(root, text="拍照上传", command=open_camera, width=15, height=2, font=("楷体", 12))
+btn_cam.place(x=300, y=625)
+# 开始测评按钮
+btn_enter = tk.Button(root, text="点击开测!", command=ok, width=15, height=2, font=("楷体", 12))
+btn_enter.place(x=485, y=625)
+
+'''
+【五、启动事件循环】
+'''
+root.mainloop()
diff --git a/第13讲你的颜值有几分二/课堂成果/安装第三方库.py b/第13讲你的颜值有几分二/课堂成果/安装第三方库.py
new file mode 100644
index 0000000..b528f70
--- /dev/null
+++ b/第13讲你的颜值有几分二/课堂成果/安装第三方库.py
@@ -0,0 +1,5 @@
+# 点击运行【安装第三方库.py】,即可安装本课用到的第三方库
+
+import pip
+pip.main(['install','baidu-aip'])
+pip.main(['install','chardet'])
diff --git a/第13讲你的颜值有几分二/课堂成果/测颜值.png b/第13讲你的颜值有几分二/课堂成果/测颜值.png
new file mode 100644
index 0000000..93b7217
Binary files /dev/null and b/第13讲你的颜值有几分二/课堂成果/测颜值.png differ
diff --git a/第13讲你的颜值有几分二/课堂成果/缩略图.png b/第13讲你的颜值有几分二/课堂成果/缩略图.png
new file mode 100644
index 0000000..e786152
Binary files /dev/null and b/第13讲你的颜值有几分二/课堂成果/缩略图.png differ
diff --git a/第13讲你的颜值有几分二/课堂成果/课堂作业-增加检测项目.py b/第13讲你的颜值有几分二/课堂成果/课堂作业-增加检测项目.py
new file mode 100644
index 0000000..c631de2
--- /dev/null
+++ b/第13讲你的颜值有几分二/课堂成果/课堂作业-增加检测项目.py
@@ -0,0 +1,157 @@
+"""
+》》》运行前必做《《《
+1. 运行【安装第三方库.py】文件
+2. 注册百度云账号,获取API,配置后查看完整效果
+账号注册指南:
+https://huewq7h021.feishu.cn/wiki/Ry3UwaoceiMRXgklbWtc9mEUn9f?from=from_copylink
+"""
+
+'''
+【导入库】
+'''
+# 【预置内容,请勿改动】
+import io
+import base64
+import cv2
+# 请在下方编写代码
+import tkinter as tk
+from PIL import Image, ImageTk
+from tkinter import filedialog, messagebox
+from aip import AipFace
+
+
+'''
+【初始化】(变量初始化、窗口初始化、API配置信息)
+'''
+# 【预置内容,请勿改动】
+cap = None
+imgtk = None
+update_id = None
+# 请在下方编写代码
+# 初始化Tkinter
+root = tk.Tk()
+root.geometry('700x700')
+root.title('颜值测评')
+root.resizable(0, 0)
+# 百度AI的API配置信息
+APP_ID = '你的 AppID'
+API_KEY = '你的 API Key'
+SECRET_KEY = '你的 Secret Key'
+client = AipFace(APP_ID, API_KEY, SECRET_KEY)
+
+
+'''
+【函数】
+'''
+# 【预置内容,请勿改动】 图像 --> 字节数据 --> Base64 编码格式
+def img_to_bytes(photoimg):
+ # 将 PhotoImage 转换为 PIL 图像
+ pil_img = ImageTk.getimage(photoimg)
+ # 如果图像具有 Alpha 信道(透明度),则转换为 RGB
+ if pil_img.mode == 'RGBA':
+ pil_img = pil_img.convert('RGB')
+ # 保存到字节缓冲区
+ buffer = io.BytesIO()
+ pil_img.save(buffer, format='JPEG')
+ img_data = buffer.getvalue()
+ return base64.b64encode(img_data).decode('utf-8')
+# 【预置内容,请勿改动】打开摄像头
+def open_camera():
+ global cap, update_id
+ cap = cv2.VideoCapture(0)
+ if not cap.isOpened():
+ print("无法打开摄像头")
+ return
+ def update_frame():
+ global cap, update_id
+ ret, frame = cap.read()
+ if frame is None:
+ return
+ frame = cv2.resize(frame, (250, 250))
+ frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
+ img = Image.fromarray(frame)
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+ update_id = lab_photo.after(10, update_frame)
+ update_frame()
+# 【预置内容,请勿改动】关闭摄像头
+def close_camera():
+ global cap, update_id
+ if cap is not None:
+ cap.release()
+ cap = None
+ if update_id is not None:
+ lab_photo.after_cancel(update_id)
+ update_id = None
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 请在下方编写代码
+# 加载本地图片
+def load():
+ file_path = filedialog.askopenfilename() # 打开一个文件选择对话框
+ if file_path:
+ close_camera()
+ img = Image.open(file_path)
+ img = img.resize((250, 250))
+ imgtk = ImageTk.PhotoImage(img)
+ lab_photo.imgtk = imgtk
+ lab_photo.config(image=imgtk)
+# 颜值检测开始
+def ok():
+ # 判断 lab_photo 对象是否具有属性 imgtk
+ if not hasattr(lab_photo, 'imgtk'):
+ messagebox.showerror("错误", "没有显示图片,无法进行颜值测试")
+ return
+ img_base64 = img_to_bytes(lab_photo.imgtk) # 将图片转为Base64
+ imageType = "BASE64" # 设置图片类型
+ options = {"face_field":"age,gender,face_shape,emotion,beauty,glasses,mask,face_type"}
+ result = client.detect(img_base64, imageType, options)
+ if 'error_msg' in result and result['error_msg'] == 'pic not has face':
+ messagebox.showerror("错误", "图像中未检测到人脸")
+ return
+ if 'result' in result and 'face_list' in result['result']:
+ # 解析结果
+ age = result['result']['face_list'][0]['age']
+ gender = result['result']['face_list'][0]['gender']['type']
+ face_shape = result['result']['face_list'][0]['face_shape']['type']
+ emotion = result['result']['face_list'][0]['emotion']['type']
+ beauty = result['result']['face_list'][0]['beauty']
+ glasses = result['result']['face_list'][0]['glasses']['type']
+ mask = result['result']['face_list'][0]['mask']['type']
+ face_type = result['result']['face_list'][0]['face_type']['type']
+ # 构造结果字符串
+ result_str1=f"年龄:{age}\n性别:{gender}\n脸型:{face_shape}\n情绪:{emotion}\n颜值:{beauty}\n"
+ result_str2=f"是否戴眼镜:{glasses}\n是否戴口罩:{mask}\n人脸类型:{face_type}"
+ # 使用对话框显示结果
+ messagebox.showinfo("颜值测评结果", result_str1+result_str2)
+ else:
+ messagebox.showerror("错误", "检测失败,请重试")
+
+'''
+【组件配置】
+'''
+# 设置背景图
+bg_image = tk.PhotoImage(file = '测颜值.png')
+bg_label = tk.Label(root, image = bg_image)
+bg_label.place(x=0, y=0, relwidth=1, relheight=1)
+# 设置缩略图
+pic0 = Image.open('缩略图.png')
+pic0 = pic0.resize((250, 250))
+pic0_image = ImageTk.PhotoImage(pic0)
+lab_photo = tk.Label(root, image=pic0_image)
+lab_photo.place(x=223, y=223)
+# 本地上传按钮
+btn_load = tk.Button(root, text="本地上传", command=load, width=15, height=2, font=("楷体", 12))
+btn_load.place(x=115, y=625)
+# 拍照上传按钮
+btn_cam = tk.Button(root, text="拍照上传", command=open_camera, width=15, height=2, font=("楷体", 12))
+btn_cam.place(x=300, y=625)
+# 开始测评按钮
+btn_enter = tk.Button(root, text="点击开测!", command=ok, width=15, height=2, font=("楷体", 12))
+btn_enter.place(x=485, y=625)
+
+'''
+【启动事件循环】
+'''
+root.mainloop()
diff --git a/第14讲十秒挑战/54十秒挑战讲义.pdf b/第14讲十秒挑战/54十秒挑战讲义.pdf
new file mode 100644
index 0000000..61b781a
Binary files /dev/null and b/第14讲十秒挑战/54十秒挑战讲义.pdf differ
diff --git a/第14讲十秒挑战/十秒挑战.png b/第14讲十秒挑战/十秒挑战.png
new file mode 100644
index 0000000..4bfa5de
Binary files /dev/null and b/第14讲十秒挑战/十秒挑战.png differ
diff --git a/第14讲十秒挑战/课堂成果/十秒挑战.png b/第14讲十秒挑战/课堂成果/十秒挑战.png
new file mode 100644
index 0000000..d2f1762
Binary files /dev/null and b/第14讲十秒挑战/课堂成果/十秒挑战.png differ
diff --git a/第14讲十秒挑战/课堂成果/十秒挑战.py b/第14讲十秒挑战/课堂成果/十秒挑战.py
new file mode 100644
index 0000000..7ec0cd2
--- /dev/null
+++ b/第14讲十秒挑战/课堂成果/十秒挑战.py
@@ -0,0 +1,65 @@
+import tkinter as tk
+import time
+from tkinter import messagebox
+
+# 创建主窗口
+root = tk.Tk()
+root.geometry("300x400") # 设置窗口大小
+root.title("10秒挑战")
+
+bg_image = tk.PhotoImage(file = '十秒挑战.png')
+bg_label = tk.Label(root, image = bg_image)
+bg_label.place(x=0, y=0, relwidth=1, relheight=1)
+
+# 初始化运行状态
+flag = False
+
+# 定期更新显示时间
+def update_time():
+ if flag:
+ now = time.time()
+ timex = now - start_time
+ timex_label.config(text=f"时间:{timex:.3f} 秒\n")
+ root.after(10, update_time) # 10ms 后更新一次
+
+# 根据当前状态开始或停止计时
+def change():
+ global flag, start_time
+
+ if not flag: # 如果计时尚未开始
+ flag = True
+ start_time = time.time() # 获取当前时间戳
+ update_time() # 开始更新时间显示
+ else: # 如果计时已经开始
+ flag = False # 停止更新时间显示
+ end_time = time.time() # 获取当前时间戳
+ timex = end_time - start_time # 计算实际耗时
+ goal = 10 # 目标耗时
+
+ # 计算时间差
+ time_difference = timex - goal
+
+ # 更新显示
+ timex_label.config(text=f"实际时间:{timex:.3f}秒\n误差:{time_difference:.3f}秒")
+
+ # 显示结果
+ if f'{time_difference:.3f}' == '0.000':
+ messagebox.showinfo("结果","难以置信!你就是掌控时间的神!")
+ else:
+ messagebox.showinfo("结果","还差一点点,再接再厉吧!")
+
+# 创建标签
+title_label = tk.Label(root, text="10 秒挑战", font=("楷体", 16))
+title_label.pack(pady=(72,10))
+
+# 创建时间显示标签
+timex_label = tk.Label(root, text="点击按钮开始挑战\n", font=("楷体", 12))
+timex_label.pack(pady=(22,17))
+
+# 创建按钮并设置图片
+btn_photo = tk.PhotoImage(file = '按钮.png')
+btn = tk.Button(root, image=btn_photo, command=change)
+btn.pack(pady=20)
+
+# 运行Tkinter主循环
+root.mainloop()
\ No newline at end of file
diff --git a/第14讲十秒挑战/课堂成果/按钮.png b/第14讲十秒挑战/课堂成果/按钮.png
new file mode 100644
index 0000000..bd51cbe
Binary files /dev/null and b/第14讲十秒挑战/课堂成果/按钮.png differ
diff --git a/第14讲十秒挑战/课堂成果/课后作业-点击按钮切换背景颜色.py b/第14讲十秒挑战/课堂成果/课后作业-点击按钮切换背景颜色.py
new file mode 100644
index 0000000..bee13c6
--- /dev/null
+++ b/第14讲十秒挑战/课堂成果/课后作业-点击按钮切换背景颜色.py
@@ -0,0 +1,51 @@
+'''【课后作业】
+
+点击切换背景颜色
+
+要求:
+
+1.窗口内有标签、按钮如图所示
+
+2.窗口初始背景为蓝色
+
+3.蓝色背景时点击按钮,背景变红,弹出对话框“变红了”;红色背景时点击按钮,背景变蓝,弹出对话框“变蓝了”
+
+注意:窗口名.config(bg='颜色')
+
+可以设置、更改窗口背景颜色'''
+import tkinter as tk
+from tkinter import messagebox
+
+# 初始化主窗口
+root = tk.Tk()
+root.geometry("300x200+600+300")
+root.title("背景颜色切换")
+
+# 初始化背景颜色标记
+is_blue = True
+
+def change():
+ global is_blue
+
+ if is_blue:
+ root.config(bg="red")
+ is_blue = False
+ messagebox.showinfo("提示", "变红了")
+ else:
+ root.config(bg="blue")
+ is_blue = True
+ messagebox.showinfo("提示", "变蓝了")
+
+# 创建标签提示操作
+label = tk.Label(root, text="点击按钮切换背景颜色", font=("楷体", 14))
+label.pack(pady=20)
+
+# 创建按钮来切换背景颜色
+change_button = tk.Button(root, text="切换背景颜色", command=change)
+change_button.pack(pady=10)
+
+# 初始化背景颜色为蓝色
+root.config(bg="blue")
+
+# 运行Tkinter主循环
+root.mainloop()
\ No newline at end of file
diff --git a/第15讲星座之谜/55星座之谜讲义.pdf b/第15讲星座之谜/55星座之谜讲义.pdf
new file mode 100644
index 0000000..384d541
Binary files /dev/null and b/第15讲星座之谜/55星座之谜讲义.pdf differ
diff --git a/第15讲星座之谜/星座之谜.png b/第15讲星座之谜/星座之谜.png
new file mode 100644
index 0000000..8d33a6b
Binary files /dev/null and b/第15讲星座之谜/星座之谜.png differ
diff --git a/第15讲星座之谜/课堂成果/星图.gif b/第15讲星座之谜/课堂成果/星图.gif
new file mode 100644
index 0000000..a888f0f
Binary files /dev/null and b/第15讲星座之谜/课堂成果/星图.gif differ
diff --git a/第15讲星座之谜/课堂成果/星座之谜.py b/第15讲星座之谜/课堂成果/星座之谜.py
new file mode 100644
index 0000000..a3bdc22
--- /dev/null
+++ b/第15讲星座之谜/课堂成果/星座之谜.py
@@ -0,0 +1,105 @@
+import tkinter as tk
+from PIL import Image, ImageTk
+from tkinter import messagebox
+
+# 预置内容,请勿改动
+def check(month, day): # 判断星座的函数
+ if (month == 1 and day >= 20) or (month == 2 and day <= 18):
+ return "水瓶座♒"
+ elif (month == 2 and day >= 19) or (month == 3 and day <= 20):
+ return "双鱼座♓"
+ elif (month == 3 and day >= 21) or (month == 4 and day <= 19):
+ return "白羊座♈"
+ elif (month == 4 and day >= 20) or (month == 5 and day <= 20):
+ return "金牛座♉"
+ elif (month == 5 and day >= 21) or (month == 6 and day <= 21):
+ return "双子座♊"
+ elif (month == 6 and day >= 22) or (month == 7 and day <= 22):
+ return "巨蟹座♋"
+ elif (month == 7 and day >= 23) or (month == 8 and day <= 22):
+ return "狮子座♌"
+ elif (month == 8 and day >= 23) or (month == 9 and day <= 22):
+ return "处女座♍"
+ elif (month == 9 and day >= 23) or (month == 10 and day <= 23):
+ return "天秤座♎"
+ elif (month == 10 and day >= 24) or (month == 11 and day <= 22):
+ return "天蝎座♏"
+ elif (month == 11 and day >= 23) or (month == 12 and day <= 21):
+ return "射手座♐"
+ elif (month == 12 and day >= 22) or (month == 1 and day <= 19):
+ return "摩羯座♑"
+
+# 创建Tkinter窗口
+root = tk.Tk()
+root.geometry('320x360')
+root.title("测测你的星座吧")
+
+# 创建一个标签用于显示gif动画
+label_bg = tk.Label(root)
+label_bg.place(x=0, y=0, relwidth=1, relheight=1) #将标签放在窗口顶部并充斥整个窗口
+
+# 加载gif图片并将每一帧存储在frames列表中
+image = Image.open('星图.gif') # 打开gif图片文件
+frames = [] # 用于存储gif的所有帧
+try:
+ while True:
+ frames.append(ImageTk.PhotoImage(image)) # 将每一帧添加到frames列表中
+ image.seek(len(frames)) # 跳转到gif的下一帧
+except EOFError:
+ pass # 当到达gif结束时,跳出循环
+
+# 用于更新gif动画帧的函数
+def upd(idx):
+ frame = frames[idx] # 获取当前帧
+ label_bg.configure(image=frame) # 更新标签中显示的帧
+ idx = (idx + 1) % len(frames) # 计算下一帧的索引
+ root.after(100, upd, idx) # 100毫秒后调用自己继续更新帧
+
+upd(0) # 开始播放gif动画
+
+# 创建标签和文本框
+label_year = tk.Label(root, text="出生年:")
+label_year.grid(row=0, column=0, padx=(60,10), pady=(140,10))
+
+entry_year = tk.Entry(root)
+entry_year.grid(row=0, column=1, pady=(140,10))
+
+label_month = tk.Label(root, text="出生月:")
+label_month.grid(row=1, column=0, padx=(60,10), pady=10)
+
+entry_month = tk.Entry(root)
+entry_month.grid(row=1, column=1, pady=10)
+
+label_day = tk.Label(root, text="出生日:")
+label_day.grid(row=2, column=0, padx=(60,10), pady=10)
+
+entry_day = tk.Entry(root)
+entry_day.grid(row=2, column=1, pady=10)
+
+# 按钮点击处理函数
+# 点击提交按钮时调用,它获取用户输入的出生年月日,验证输入有效性,并显示对应的星座信息
+def click():
+ year = entry_year.get() # 获取用户输入的出生年份
+ month = entry_month.get() # 获取用户输入的出生月份
+ day = entry_day.get() # 获取用户输入的出生日
+
+ # 检查用户输入的年、月、日是否为有效的数字
+ if not year.isdigit() or not month.isdigit() or not day.isdigit():
+ messagebox.showerror("输入错误", "请输入有效的日期")
+
+ month = int(month) # 将月份转换为整数
+ day = int(day) # 将日期转换为整数
+
+ # 检查日期是否在有效范围内
+ if month < 1 or month > 12 or day < 1 or day > 31:
+ messagebox.showerror("输入错误", "请输入有效的日期")
+
+ result = check(month, day) # 调用check函数获取星座信息
+ messagebox.showinfo("星座", f"你的星座是:{result}") # 显示用户的星座信息
+
+# 创建提交按钮
+btn = tk.Button(root, text="提交", command=click)
+btn.grid(row=3, columnspan=2, padx=(80,10), pady=10)
+
+# 运行Tkinter主循环
+root.mainloop()
diff --git a/第15讲星座之谜/课堂成果/生肖计算助手.py b/第15讲星座之谜/课堂成果/生肖计算助手.py
new file mode 100644
index 0000000..63e882d
--- /dev/null
+++ b/第15讲星座之谜/课堂成果/生肖计算助手.py
@@ -0,0 +1,49 @@
+'''【课后作业要求】
+
+生肖计算助手
+
+要求:
+
+1.窗口内有标签、单行文本输入框、提交按钮
+
+2.输入正确的年份(1900-2100)后会弹出对话框显示生肖
+
+3.输入的年份不在范围内或者不是数字格式,会弹出错误对话框
+
+注意:判断生肖的函数check(year)已经预置好,可以直接调用;组件的位置可以自行调整,合理美观即可。'''
+import tkinter as tk
+from tkinter import messagebox
+
+root = tk.Tk()
+root.geometry("300x200+600+300")
+root.title("生肖计算助手")
+
+
+# 预置内容,请勿改动
+def check(year):
+ sx = ["鼠", "牛", "虎", "兔", "龙", "蛇", "马", "羊", "猴", "鸡", "狗", "猪"]
+ idx = (year - 1900) % 12
+ return sx[idx]
+
+
+def click():
+ year = entry_year.get()
+ if not year.isdigit():
+ messagebox.showerror("输入错误", "请输入有效的年份数值")
+ year = int(year)
+ if year < 1900 or year > 2100:
+ messagebox.showerror("输入错误", "请输入有效的年份数值")
+ result = check(year)
+ messagebox.showinfo("属相", f"您的生肖是:{result}")
+
+
+label_year = tk.Label(root, text='出生年份:')
+label_year.grid(row=0, column=0, padx=20, pady=50)
+
+entry_year = tk.Entry(root)
+entry_year.grid(row=0, column=1, pady=50)
+
+btn = tk.Button(root, text='提交', command=click)
+btn.grid(row=1, columnspan=2, padx=(60, 0))
+
+root.mainloop()
diff --git a/第16讲中国地图我来拼(一)/56中国地图我来拼一讲义.pdf b/第16讲中国地图我来拼(一)/56中国地图我来拼一讲义.pdf
new file mode 100644
index 0000000..8713976
Binary files /dev/null and b/第16讲中国地图我来拼(一)/56中国地图我来拼一讲义.pdf differ
diff --git a/第16讲中国地图我来拼(一)/中国地图我来拼(一).png b/第16讲中国地图我来拼(一)/中国地图我来拼(一).png
new file mode 100644
index 0000000..90c260b
Binary files /dev/null and b/第16讲中国地图我来拼(一)/中国地图我来拼(一).png differ
diff --git a/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼.7z b/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼.7z
new file mode 100644
index 0000000..db33f2d
Binary files /dev/null and b/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼.7z differ
diff --git a/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼1.py b/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼1.py
new file mode 100644
index 0000000..1a05747
--- /dev/null
+++ b/第16讲中国地图我来拼(一)/课堂成果/中国地图我来拼1.py
@@ -0,0 +1,64 @@
+# 预置内容,请勿改动
+a = {"01新疆碎片": (225, 231), "02西藏碎片": (244, 457), "03内蒙古碎片": (623, 203),
+ "04青海碎片": (383, 396), "05四川碎片": (491, 521), "06黑龙江碎片": (861, 122),
+ "07甘肃碎片": (472, 358), "08云南碎片": (457, 621), "09广西碎片": (580, 656),
+ "10湖南碎片": (640, 584), "11陕西碎片": (586, 415), "12河北碎片": (718, 330),
+ "13吉林碎片": (859, 228), "14湖北碎片": (654, 506), "15广东碎片": (678, 677),
+ "16贵州碎片": (549, 593), "17河南碎片": (672, 446), "18江西碎片": (724, 584),
+ "19山东碎片": (758, 392), "20山西碎片": (650, 369), "21辽宁碎片": (805, 284),
+ "22安徽碎片": (740, 487), "23福建碎片": (766, 609), "24江苏碎片": (770, 462),
+ "25浙江碎片": (793, 538), "26重庆碎片": (573, 525), "27宁夏碎片": (548, 375),
+ "28台湾碎片": (824, 652), "29海南碎片": (610, 753), "30北京碎片": (715, 310),
+ "31天津碎片": (730, 326), "32上海碎片": (818, 495)} # 省份文件名称和对应的正确位置
+
+# 导入库
+import pgzrun
+import os
+import random
+
+# 设置窗口
+WIDTH = 1000 # 窗口的宽度
+HEIGHT = 800 # 窗口的高度
+# 设置窗口标题
+TITLE = '中国地图我来拼'
+
+# 初始值设置
+selected_piece = None # 当前被选择的碎片
+selected_name = None # 当前被选择的碎片名字
+
+# 加载碎片
+pieces = []
+# 遍历指定文件夹中的所有文件
+for filename in os.listdir('images'):
+ if filename[-6:] == '碎片.png': # 只处理以碎片.png结尾的文件
+ img = Actor(filename[:-4], (random.randint(0, WIDTH), random.randint(0, HEIGHT)))
+ pieces.append([img, filename[:-4], False]) # 添加所有碎片和碎片信息到列表
+
+# 刷新屏幕
+def draw():
+ screen.blit('中国地图背景',(0,0)) # 绘制背景
+ # 绘制每个碎片
+ for piece in pieces:
+ piece[0].draw()
+
+# 鼠标按下事件
+def on_mouse_down(pos):
+ global selected_piece, selected_name
+ for piece, name, placed in pieces:
+ if piece.collidepoint(pos) and not placed: # 检查是否点击到未正确放置的碎片
+ selected_piece = piece # 记录选择的碎片
+ selected_name = name # 记录碎片名称
+ break
+
+# 鼠标移动事件
+def on_mouse_move(pos):
+ if selected_piece != None and 0
+ pass
+
+# 启动游戏
+pgzrun.go()
diff --git a/第17讲中国地图我来拼(二)/57中国地图我来拼二讲义.pdf b/第17讲中国地图我来拼(二)/57中国地图我来拼二讲义.pdf
new file mode 100644
index 0000000..f653f29
Binary files /dev/null and b/第17讲中国地图我来拼(二)/57中国地图我来拼二讲义.pdf differ
diff --git a/第17讲中国地图我来拼(二)/中国地图我来拼(二).png b/第17讲中国地图我来拼(二)/中国地图我来拼(二).png
new file mode 100644
index 0000000..9364e72
Binary files /dev/null and b/第17讲中国地图我来拼(二)/中国地图我来拼(二).png differ
diff --git a/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼.7z b/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼.7z
new file mode 100644
index 0000000..db33f2d
Binary files /dev/null and b/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼.7z differ
diff --git a/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼2.py b/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼2.py
new file mode 100644
index 0000000..214d8d5
--- /dev/null
+++ b/第17讲中国地图我来拼(二)/课堂成果/中国地图我来拼2.py
@@ -0,0 +1,69 @@
+# 预置内容,请勿改动
+a = {"01新疆碎片": (225, 231), "02西藏碎片": (244, 457), "03内蒙古碎片": (623, 203),
+ "04青海碎片": (383, 396), "05四川碎片": (491, 521), "06黑龙江碎片": (861, 122),
+ "07甘肃碎片": (472, 358), "08云南碎片": (457, 621), "09广西碎片": (580, 656),
+ "10湖南碎片": (640, 584), "11陕西碎片": (586, 415), "12河北碎片": (718, 330),
+ "13吉林碎片": (859, 228), "14湖北碎片": (654, 506), "15广东碎片": (678, 677),
+ "16贵州碎片": (549, 593), "17河南碎片": (672, 446), "18江西碎片": (724, 584),
+ "19山东碎片": (758, 392), "20山西碎片": (650, 369), "21辽宁碎片": (805, 284),
+ "22安徽碎片": (740, 487), "23福建碎片": (766, 609), "24江苏碎片": (770, 462),
+ "25浙江碎片": (793, 538), "26重庆碎片": (573, 525), "27宁夏碎片": (548, 375),
+ "28台湾碎片": (824, 652), "29海南碎片": (610, 753), "30北京碎片": (715, 310),
+ "31天津碎片": (730, 326), "32上海碎片": (818, 495)} # 省份文件名称和对应的正确位置
+
+# 导入库
+import pgzrun
+import os
+import random
+
+# 设置窗口
+WIDTH = 1000 # 窗口的宽度
+HEIGHT = 800 # 窗口的高度
+# 设置窗口标题
+TITLE = '中国地图我来拼'
+
+# 初始值设置
+selected_piece = None # 当前被选择的碎片
+selected_name = None # 当前被选择的碎片名字
+
+# 加载碎片
+pieces = []
+# 遍历指定文件夹中的所有文件
+for filename in os.listdir('images'):
+ if filename[-6:] == '碎片.png': # 只处理以碎片.png结尾的文件
+ img = Actor(filename[:-4], (random.randint(0, WIDTH), random.randint(0, HEIGHT)))
+ pieces.append([img, filename[:-4], False]) # 添加所有碎片和碎片信息到列表
+
+
+# 刷新屏幕
+def draw():
+ screen.blit('中国地图背景', (0, 0)) # 绘制背景
+ # 绘制每个碎片
+ for piece in pieces:
+ piece[0].draw()
+
+
+# 鼠标按下事件
+def on_mouse_down(pos):
+ global selected_piece, selected_name
+ for piece, name, placed in pieces:
+ if piece.collidepoint(pos) and not placed: # 检查是否点击到未正确放置的碎片
+ selected_piece = piece # 记录选择的碎片
+ selected_name = name # 记录碎片名称
+ break
+
+
+# 鼠标移动事件
+def on_mouse_move(pos):
+ if selected_piece != None and 0 < pos[0] < 1000 and 0 < pos[1] < 800: # 如果有选中碎片且鼠标未移出窗口,就随着鼠标移动
+ selected_piece.pos = pos # 更新选中碎片的位置
+
+
+# 鼠标释放事件
+def on_mouse_up(pos):
+ # <检测碎片是否正确放置>
+ pass
+
+
+# 启动游戏
+pgzrun.go()
diff --git a/第18讲火眼金睛(一)/58火眼金睛一讲义.pdf b/第18讲火眼金睛(一)/58火眼金睛一讲义.pdf
new file mode 100644
index 0000000..3e9ba9b
Binary files /dev/null and b/第18讲火眼金睛(一)/58火眼金睛一讲义.pdf differ
diff --git a/第18讲火眼金睛(一)/火眼金睛(一).png b/第18讲火眼金睛(一)/火眼金睛(一).png
new file mode 100644
index 0000000..85cf527
Binary files /dev/null and b/第18讲火眼金睛(一)/火眼金睛(一).png differ
diff --git a/第18讲火眼金睛(一)/课堂成果/火眼金睛.7z b/第18讲火眼金睛(一)/课堂成果/火眼金睛.7z
new file mode 100644
index 0000000..f190132
Binary files /dev/null and b/第18讲火眼金睛(一)/课堂成果/火眼金睛.7z differ
diff --git a/第18讲火眼金睛(一)/课堂成果/火眼金睛1.py b/第18讲火眼金睛(一)/课堂成果/火眼金睛1.py
new file mode 100644
index 0000000..752ff78
--- /dev/null
+++ b/第18讲火眼金睛(一)/课堂成果/火眼金睛1.py
@@ -0,0 +1,48 @@
+import pgzrun
+import random
+
+# 设置窗口
+WIDTH = 1000 # 窗口的宽度
+HEIGHT = 725 # 窗口的高度
+
+def draw():
+ screen.blit('火眼金睛.png', (0, 0))
+ for grid in grids:
+ screen.draw.filled_rect(Rect(grid['pos'], (side, side)), 'white')
+
+def update():
+ pass
+
+def base_color():
+ """生成随机基础颜色"""
+ return (random.randint(0, 255),
+ random.randint(0, 255),
+ random.randint(0, 255))
+
+def dif_color(base):
+ """
+ 参数:
+ base:表示基础颜色的元组,格式为(r,g,b)
+ """
+ r = min(base[0] + random.randint(20, 30), 255)
+ g = min(base[1] + random.randint(20, 30), 255)
+ b = min(base[2] + random.randint(20, 30), 255)
+ return (r, g, b)
+
+# 初始为3×3的矩阵
+n = 3
+# 根据格子数量计算格子边长和间距
+side = 700 // n * 0.9
+space = 700 // n * 0.1
+# 创建列表grids,后面存储每个方格信息
+grids = []
+for row in range(n): # 遍历行
+ for col in range(n): # 遍历列
+ info = {
+ 'pos': (space + col * (side + space), space + row * (side + space)),
+ 'color': 'white' # 测试用,后续及时更新对应颜色
+ }
+ grids.append(info)
+
+# 启动游戏
+pgzrun.go()
\ No newline at end of file
diff --git a/第18讲火眼金睛(一)/课堂成果/课后作业-五阶橙色矩阵.py b/第18讲火眼金睛(一)/课堂成果/课后作业-五阶橙色矩阵.py
new file mode 100644
index 0000000..76dbbc3
--- /dev/null
+++ b/第18讲火眼金睛(一)/课堂成果/课后作业-五阶橙色矩阵.py
@@ -0,0 +1,39 @@
+'''
+
+五阶橙色矩阵
+
+要求如下:
+
+1. 方块边长为40,间距为5
+
+2. 绘制五阶矩阵方块
+
+3. 方块为橙色‘orange’'''
+
+# 导入pgzero库
+import pgzrun
+
+# 设置窗口
+WIDTH = 725 # 窗口的宽度
+HEIGHT = 725 # 窗口的高度
+
+def draw():
+ for grid in grids:
+ screen.draw.filled_rect(Rect(grid['pos'], (side, side)), 'orange')
+
+# 五阶矩阵
+n = 5
+# 提供边长和间距
+side = 40
+space = 5
+# 创建列表grids,后面存储每个方格信息
+grids = []
+for row in range(n): # 遍历行
+ for col in range(n): # 遍历列
+ info = {
+ 'pos': (space + col * (side + space), space + row * (side + space)),
+ }
+ grids.append(info)
+
+# 启动游戏
+pgzrun.go()
\ No newline at end of file
diff --git a/第19讲火眼金睛(二)/59火眼金睛二讲义.pdf b/第19讲火眼金睛(二)/59火眼金睛二讲义.pdf
new file mode 100644
index 0000000..cd4e3db
Binary files /dev/null and b/第19讲火眼金睛(二)/59火眼金睛二讲义.pdf differ
diff --git a/第19讲火眼金睛(二)/火眼金睛(二).png b/第19讲火眼金睛(二)/火眼金睛(二).png
new file mode 100644
index 0000000..17286df
Binary files /dev/null and b/第19讲火眼金睛(二)/火眼金睛(二).png differ
diff --git a/第19讲火眼金睛(二)/课堂成果/火眼金睛.7z b/第19讲火眼金睛(二)/课堂成果/火眼金睛.7z
new file mode 100644
index 0000000..f190132
Binary files /dev/null and b/第19讲火眼金睛(二)/课堂成果/火眼金睛.7z differ
diff --git a/第19讲火眼金睛(二)/课堂成果/火眼金睛.py b/第19讲火眼金睛(二)/课堂成果/火眼金睛.py
new file mode 100644
index 0000000..21057c6
--- /dev/null
+++ b/第19讲火眼金睛(二)/课堂成果/火眼金睛.py
@@ -0,0 +1,82 @@
+import pgzrun
+import random
+import time
+
+WIDTH = 1000 # 窗口的宽度
+HEIGHT = 725 # 窗口的高度
+
+def draw():
+ screen.blit('火眼金睛.png', (0, 0))
+ if win:
+ screen.blit('游戏成功.png', (0, 0))
+ screen.draw.text(f"{total_t:.1f}", center=(520, 570), fontsize=90, color="yellow")
+ else:
+ screen.draw.text(f"{t:.1f} s", center=(900, 662), fontsize=40, color="yellow")
+ for grid in grids:
+ screen.draw.filled_rect(Rect(grid['pos'], (side, side)), grid['color'])
+
+def update():
+ """更新函数,用于实时更新游戏状态相关信息,这里主要更新总耗时"""
+ global t
+ t = time.time() - start_t
+
+def base_color():
+ """生成随机基础颜色"""
+ return (random.randint(0, 255),
+ random.randint(0, 255),
+ random.randint(0, 255))
+
+def dif_color(base):
+ """
+ 参数:
+ base:表示基础颜色的元组,格式为(r,g,b)
+ """
+ r = min(base[0] + random.randint(20, 30), 255)
+ g = min(base[1] + random.randint(20, 30), 255)
+ b = min(base[2] + random.randint(20, 30), 255)
+ return (r, g, b)
+
+def game():
+ global grids, side, dc
+ # 根据格子数量计算格子边长和间距
+ side = 700 // n * 0.9
+ space = 700 // n * 0.1
+ # 创建列表grids,后面存储每个方格信息
+ grids = []
+ # 获取基础色和异色
+ bc = base_color()
+ dc = dif_color(bc)
+ # 记录方格编号
+ i = 1
+ # 随机选择一个位置的方格设置略微不同的颜色
+ dif_index = random.randint(1, n * n)
+ for row in range(n):
+ for col in range(n):
+ info = {
+ 'pos': (space + col * (side + space),
+ space + row * (side + space)),
+ 'color': dc if i == dif_index else bc
+ }
+ grids.append(info)
+ i += 1
+
+def on_mouse_down(pos):
+ global n, win, total_t
+ for grid in grids:
+ grid_rect = Rect(grid['pos'], (side, side))
+ if grid_rect.collidepoint(pos) and grid['color'] == dc:
+ if n > 10:
+ win = True
+ total_t = t
+ else:
+ n += 1 # 进入下一关
+ game()
+
+# 初始化游戏参数
+n = 3 # 初始为3×3的矩阵
+win = False # 记录游戏成功状态
+start_t = time.time() # 记录开始时间
+game()
+
+# 启动游戏
+pgzrun.go()
\ No newline at end of file
diff --git a/第19讲火眼金睛(二)/课堂成果/课后作业-作品优化 .py b/第19讲火眼金睛(二)/课堂成果/课后作业-作品优化 .py
new file mode 100644
index 0000000..5d1f685
--- /dev/null
+++ b/第19讲火眼金睛(二)/课堂成果/课后作业-作品优化 .py
@@ -0,0 +1,89 @@
+'''作品优化 —— 增大游戏难度
+
+提示:
+
+1. 增加关卡数量
+
+2. 减小基础色和异色的区别'''
+import pgzrun
+import random
+import time
+
+WIDTH = 1000 # 窗口的宽度
+HEIGHT = 725 # 窗口的高度
+
+def draw():
+ screen.blit('火眼金睛.png', (0, 0))
+ if win:
+ screen.blit('游戏成功.png', (0, 0))
+ screen.draw.text(f"{total_t:.1f}", center=(520, 570), fontsize=90, color="yellow")
+ else:
+ screen.draw.text(f"{t:.1f} s", center=(900, 662), fontsize=40, color="yellow")
+ for grid in grids:
+ screen.draw.filled_rect(Rect(grid['pos'], (side, side)), grid['color'])
+
+def update():
+ """更新函数,用于实时更新游戏状态相关信息,这里主要更新总耗时"""
+ global t
+ t = time.time() - start_t
+
+def base_color():
+ """生成随机基础颜色"""
+ return (random.randint(0, 255),
+ random.randint(0, 255),
+ random.randint(0, 255))
+
+def dif_color(base):
+ """
+ 参数:
+ base:表示基础颜色的元组,格式为(r,g,b)
+ """
+ r = min(base[0] + random.randint(20, 25), 255)
+ g = min(base[1] + random.randint(20, 25), 255)
+ b = min(base[2] + random.randint(20, 25), 255)
+ return (r, g, b)
+
+def game():
+ global grids, side, dc
+ # 根据格子数量计算格子边长和间距
+ side = 700 // n * 0.9
+ space = 700 // n * 0.1
+ # 创建列表grids,后面存储每个方格信息
+ grids = []
+ # 获取基础色和异色
+ bc = base_color()
+ dc = dif_color(bc)
+ # 记录方格编号
+ i = 1
+ # 随机选择一个位置的方格设置略微不同的颜色
+ dif_index = random.randint(1, n * n)
+ for row in range(n):
+ for col in range(n):
+ info = {
+ 'pos': (space + col * (side + space),
+ space + row * (side + space)),
+ 'color': dc if i == dif_index else bc
+ }
+ grids.append(info)
+ i += 1
+
+def on_mouse_down(pos):
+ global n, win, total_t
+ for grid in grids:
+ grid_rect = Rect(grid['pos'], (side, side))
+ if grid_rect.collidepoint(pos) and grid['color'] == dc:
+ if n > 20:
+ win = True
+ total_t = t
+ else:
+ n += 1 # 进入下一关
+ game()
+
+# 初始化游戏参数
+n = 3 # 初始为3×3的矩阵
+win = False # 记录游戏成功状态
+start_t = time.time() # 记录开始时间
+game()
+
+# 启动游戏
+pgzrun.go()
\ No newline at end of file
diff --git a/第1讲点名系统/41点名系统讲义.pdf b/第1讲点名系统/41点名系统讲义.pdf
new file mode 100644
index 0000000..3b4e146
Binary files /dev/null and b/第1讲点名系统/41点名系统讲义.pdf differ
diff --git a/第1讲点名系统/点名系统.png b/第1讲点名系统/点名系统.png
new file mode 100644
index 0000000..26c2905
Binary files /dev/null and b/第1讲点名系统/点名系统.png differ
diff --git a/第1讲点名系统/课堂成果/点名.png b/第1讲点名系统/课堂成果/点名.png
new file mode 100644
index 0000000..2c554c7
Binary files /dev/null and b/第1讲点名系统/课堂成果/点名.png differ
diff --git a/第1讲点名系统/课堂成果/点名系统.py b/第1讲点名系统/课堂成果/点名系统.py
new file mode 100644
index 0000000..d51399a
--- /dev/null
+++ b/第1讲点名系统/课堂成果/点名系统.py
@@ -0,0 +1,40 @@
+# 导入所需要的库
+from tkinter import *
+import random
+
+# 创建主窗口
+root = Tk()
+root.geometry('500x150+300+500')
+root.title('点名系统')
+
+bg_image = PhotoImage(file = '点名.png')
+
+bg_label = Label(root, image = bg_image)
+bg_label.place(x=0, y=0, relwidth=1, relheight=1)
+
+# 设置全局变量
+var = StringVar() # 这个变量用来显示在标签上的名字
+names = ['小明', '红红', '粘豆包', '牛牛'] # 这个列表存储学生的名字
+flag = False # 这个标志用来表示是否正在进行点名
+
+# 定义一个函数,用来进行点名
+def roll():
+ if flag: # 如果正在进行点名,那么显示一个随机的名字
+ var.set(random.choice(names))
+ root.after(10, roll) # 在10毫秒后,再次调用这个函数
+
+# 定义一个函数,用来切换点名状态
+def check():
+ global flag # 声明我们要使用的是全局变量,而不是创建一个新的局部变量
+ if flag: # 如果正在进行点名,那么停止点名
+ flag = False
+ else: # 否则,开始点名
+ flag = True
+ roll()
+
+# 创建并配置标签和按钮
+Label(root, textvariable=var, font=('楷体', 50)).pack()
+Button(root, text="开始/停止点名", command=check).pack()
+
+# 启动事件循环
+root.mainloop()
diff --git a/第1讲点名系统/课堂成果/课后作业-晚饭吃什么.py b/第1讲点名系统/课堂成果/课后作业-晚饭吃什么.py
new file mode 100644
index 0000000..4e946be
--- /dev/null
+++ b/第1讲点名系统/课堂成果/课后作业-晚饭吃什么.py
@@ -0,0 +1,45 @@
+'''【课后作业要求】
+晚饭吃什么
+
+要求:
+
+1. 点击按钮食物开始滚动
+
+2. 再次点击按钮食物停止滚动,显示晚饭要吃的食物
+
+3. 修改合适的题目和按钮文本'''
+# 导入所需要的库
+from tkinter import *
+import random
+
+# 创建主窗口
+root = Tk()
+root.geometry('300x100+300+500')
+root.title('晚饭吃什么')
+
+# 设置全局变量
+var = StringVar()
+foods = ['火锅', '烤肉', '炒菜', '烧烤']
+rolling = False
+
+# 定义一个函数,用来滚动清单
+def roll_food():
+ if rolling:
+ var.set(random.choice(foods))
+ root.after(10, roll_food)
+
+# 定义一个函数,用来切换按钮状态
+def toggle_roll():
+ global rolling
+ if rolling:
+ rolling = False
+ else:
+ rolling = True
+ roll_food()
+
+# 创建并配置标签和按钮
+Label(root, textvariable=var, font=('楷体', 40)).pack()
+Button(root, text="开始/停止滚动", command=toggle_roll).pack()
+
+# 启动事件循环
+root.mainloop()
diff --git a/第20讲疯狂的摩托(一)/60疯狂的摩托一讲义.pdf b/第20讲疯狂的摩托(一)/60疯狂的摩托一讲义.pdf
new file mode 100644
index 0000000..7bcac59
Binary files /dev/null and b/第20讲疯狂的摩托(一)/60疯狂的摩托一讲义.pdf differ
diff --git a/第20讲疯狂的摩托(一)/疯狂的摩托(一).png b/第20讲疯狂的摩托(一)/疯狂的摩托(一).png
new file mode 100644
index 0000000..98a97d9
Binary files /dev/null and b/第20讲疯狂的摩托(一)/疯狂的摩托(一).png differ
diff --git a/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托.7z b/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托.7z
new file mode 100644
index 0000000..ae5c863
Binary files /dev/null and b/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托.7z differ
diff --git a/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托1 .py b/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托1 .py
new file mode 100644
index 0000000..55cda70
--- /dev/null
+++ b/第20讲疯狂的摩托(一)/课堂成果/疯狂的摩托1 .py
@@ -0,0 +1,68 @@
+import pgzrun
+import random
+from pgzhelper import *
+
+# 游戏窗口大小
+WIDTH = 1500
+HEIGHT = 800
+
+# 创建背景角色
+bg1 = Actor('连续道路', topleft = (0,0))
+bg2 = Actor('连续道路', topleft = (1500,0))
+
+# 创建障碍物
+obstacles = []
+for _ in range(3): # 障碍物数量
+ x = random.randint(WIDTH, WIDTH + 1500) # 障碍物出现在屏幕右侧外
+ y = random.randint(100, HEIGHT - 50)
+ obstacles.append(Actor('路障', (x, y)))
+
+# 创建摩托车
+motor = Actor('摩托1', (200, HEIGHT // 2))
+# 将摩托造型存放在列表内
+motor.images = ['摩托1','摩托2']
+
+# 初始化设置
+speed = 15
+
+def draw():
+ # 绘制连续背景
+ bg1.draw()
+ bg2.draw()
+ # 绘制障碍物
+ for obs in obstacles:
+ obs.draw()
+ # 绘制摩托
+ motor.draw()
+
+# 背景、终点线移动
+def bg_move():
+ bg1.x -= speed
+ bg2.x -= speed
+ if bg1.right <= 0:
+ bg1.left = bg2.right
+ if bg2.right <= 0:
+ bg2.left = bg1.right
+
+# 更新障碍物位置
+def obs_move():
+ for obs in obstacles:
+ obs.x -= speed # 障碍物随背景一起移动
+ if obs.x < 0:
+ obs.x = random.randint(WIDTH, WIDTH + 1500) # 障碍物继续出现在屏幕外
+ obs.y = random.randint(100, HEIGHT - 50)
+
+def update():
+ bg_move()
+ obs_move()
+ # 控制赛车移动,限制不能出界
+ if keyboard.up and motor.top > 0:
+ motor.y -= 7
+ if keyboard.down and motor.bottom < HEIGHT-50:
+ motor.y += 7
+
+def change_image():
+ motor.next_image()
+clock.schedule_interval(change_image,0.2)
+
+pgzrun.go()
\ No newline at end of file
diff --git a/第20讲疯狂的摩托(一)/课堂成果/课后作业-小城漫步.py b/第20讲疯狂的摩托(一)/课堂成果/课后作业-小城漫步.py
new file mode 100644
index 0000000..45f99c9
--- /dev/null
+++ b/第20讲疯狂的摩托(一)/课堂成果/课后作业-小城漫步.py
@@ -0,0 +1,48 @@
+'''小城漫步
+
+要求如下:
+
+1. ‘白日街景’、‘夜晚街景’两图滚动出现
+
+2. ‘走1’、‘走2’两图,实现博克斯走路动效
+
+3. 按下键盘右键,背景滚动'''
+import pgzrun
+from pgzhelper import *
+
+WIDTH = 960
+HEIGHT = 720
+
+# 创建背景角色
+bg1 = Actor('白日街景', topleft=(0, 0))
+bg2 = Actor('夜晚街景', topleft=(960, 0))
+# 创建博克斯角色
+people = Actor('走1', (200, 500))
+people.images = ['走1', '走2']
+# 初始化速度
+speed = 10
+
+
+def draw():
+ bg1.draw()
+ bg2.draw()
+ people.draw()
+
+
+def update():
+ if keyboard.right:
+ bg1.x -= speed
+ bg2.x -= speed
+ if bg1.right <= 0:
+ bg1.left = bg2.right
+ if bg2.right <= 0:
+ bg2.left = bg1.right
+
+
+def change_image():
+ people.next_image()
+
+
+clock.schedule_interval(change_image, 0.5)
+
+pgzrun.go()
\ No newline at end of file
diff --git a/第21讲疯狂的摩托(二)/61疯狂的摩托二讲义.pdf b/第21讲疯狂的摩托(二)/61疯狂的摩托二讲义.pdf
new file mode 100644
index 0000000..3a75e25
Binary files /dev/null and b/第21讲疯狂的摩托(二)/61疯狂的摩托二讲义.pdf differ
diff --git a/第21讲疯狂的摩托(二)/疯狂的摩托(二).png b/第21讲疯狂的摩托(二)/疯狂的摩托(二).png
new file mode 100644
index 0000000..4f7a237
Binary files /dev/null and b/第21讲疯狂的摩托(二)/疯狂的摩托(二).png differ
diff --git a/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.7z b/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.7z
new file mode 100644
index 0000000..ae5c863
Binary files /dev/null and b/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.7z differ
diff --git a/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.py b/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.py
new file mode 100644
index 0000000..4382974
--- /dev/null
+++ b/第21讲疯狂的摩托(二)/课堂成果/疯狂的摩托.py
@@ -0,0 +1,109 @@
+import pgzrun
+import random
+from pgzhelper import *
+
+# 游戏窗口大小
+WIDTH = 1500
+HEIGHT = 800
+
+# 创建背景角色
+bg1 = Actor('连续道路', topleft = (0,0))
+bg2 = Actor('连续道路', topleft = (1500,0))
+
+# 创建障碍物
+obstacles = []
+for _ in range(3): # 障碍物数量
+ x = random.randint(WIDTH, WIDTH + 1500) # 障碍物出现在屏幕右侧外
+ y = random.randint(100, HEIGHT - 50)
+ obstacles.append(Actor('路障', (x, y)))
+
+# 创建摩托车
+motor = Actor('摩托1', (200, HEIGHT // 2))
+# 将摩托造型存放在列表内
+motor.images = ['摩托1','摩托2']
+
+# 创建终点线
+line = Actor('终点线', topleft = (20000, 163))
+
+# 初始化设置
+speed = 15
+flag = 0
+
+def draw():
+ # 绘制连续背景
+ bg1.draw()
+ bg2.draw()
+ if flag == 1:
+ music.stop()
+ screen.blit('摩托成功', (0,0))
+ elif flag == 2:
+ music.stop()
+ screen.blit('摩托失败', (0,0))
+ else:
+ # 绘制障碍物
+ for obs in obstacles:
+ obs.draw()
+ # 绘制摩托
+ motor.draw()
+ # 绘制终点线
+ line.draw()
+ # 绘制距离文字
+ x = int(line.x-motor.x)
+ screen.draw.text(f'距终点:{x} m', (50,700), fontname = 'simkai', fontsize = 50)
+
+# 背景、终点线移动
+def bg_move():
+ bg1.x -= speed
+ bg2.x -= speed
+ if bg1.right <= 0:
+ bg1.left = bg2.right
+ if bg2.right <= 0:
+ bg2.left = bg1.right
+ line.x -= speed
+
+# 更新障碍物位置
+def obs_move():
+ for obs in obstacles:
+ obs.x -= speed # 障碍物随背景一起移动
+ if obs.x < 0:
+ obs.x = random.randint(WIDTH, WIDTH + 1500) # 障碍物继续出现在屏幕外
+ obs.y = random.randint(100, HEIGHT - 50)
+
+# 最后冲刺
+def line_collide():
+ global flag
+ if motor.collide_pixel(line):
+ flag = 1
+ sounds.胜利.play()
+ else:
+ motor.x += 15
+
+# 判断是否与障碍物相撞
+def obs_collide():
+ global flag
+ for obs in obstacles:
+ if motor.collide_pixel(obs):
+ flag = 2
+ sounds.失败.play()
+
+def update():
+ if flag == 0:
+ if line.x > WIDTH - 200: # 正常行驶
+ bg_move()
+ obs_move()
+ else: # 最后冲刺
+ line_collide()
+ # 控制赛车移动,限制不能出界
+ if keyboard.up and motor.top > 0:
+ motor.y -= 7
+ if keyboard.down and motor.bottom < HEIGHT-50:
+ motor.y += 7
+ # 是否碰撞障碍物
+ obs_collide()
+
+def change_image():
+ motor.next_image()
+clock.schedule_interval(change_image,0.2)
+music.play('速度与激情')
+
+pgzrun.go()
\ No newline at end of file
diff --git a/第21讲疯狂的摩托(二)/课堂成果/课后作业 -游戏优化py b/第21讲疯狂的摩托(二)/课堂成果/课后作业 -游戏优化py
new file mode 100644
index 0000000..bd9eceb
--- /dev/null
+++ b/第21讲疯狂的摩托(二)/课堂成果/课后作业 -游戏优化py
@@ -0,0 +1,153 @@
+'''游戏优化
+
+要求如下:
+
+1. 绘制‘钻石’角色
+
+2. 钻石随背景同步移动,移出舞台后从右侧重新进入
+
+3. 摩托碰到钻石后,钻石从右侧重新进入
+
+4. 变量 score 记录收集到的钻石数量
+
+5. 在窗口内,绘制文字‘收集宝石:×颗’'''
+import pgzrun
+import random
+from pgzhelper import *
+
+# 游戏窗口大小
+WIDTH = 1500
+HEIGHT = 800
+
+# 创建背景角色
+bg1 = Actor('连续道路', topleft=(0, 0))
+bg2 = Actor('连续道路', topleft=(1500, 0))
+
+# 创建障碍物
+obstacles = []
+for _ in range(3): # 障碍物数量
+ x = random.randint(WIDTH, WIDTH + 1500) # 障碍物出现在屏幕右侧外
+ y = random.randint(100, HEIGHT - 50)
+ obstacles.append(Actor('路障', (x, y)))
+
+# 创建摩托车
+motor = Actor('摩托1', (200, HEIGHT // 2))
+# 将摩托造型存放在列表内
+motor.images = ['摩托1', '摩托2']
+
+# 创建终点线
+line = Actor('终点线', topleft=(20000, 163))
+
+# 创建钻石
+zuan = Actor('钻石', topleft=(WIDTH + 100, random.randint(100, HEIGHT - 50)))
+
+# 初始化设置
+speed = 15
+flag = 0
+score = 0
+
+
+def draw():
+ # 绘制连续背景
+ bg1.draw()
+ bg2.draw()
+ if flag == 1:
+ music.stop()
+ screen.blit('摩托成功', (0, 0))
+ elif flag == 2:
+ music.stop()
+ screen.blit('摩托失败', (0, 0))
+ else:
+ # 绘制障碍物
+ for obs in obstacles:
+ obs.draw()
+ # 绘制摩托
+ motor.draw()
+ # 绘制终点线
+ line.draw()
+ # 绘制钻石
+ zuan.draw()
+ # 绘制距离文字
+ x = int(line.x - motor.x)
+ screen.draw.text(f'距终点:{x} m', (50, 700), fontname='simkai', fontsize=50)
+ # 绘制钻石数量文字
+ screen.draw.text(f'收集钻石:{score}颗', (50, 100), fontname='simkai', fontsize=50)
+
+
+# 背景、终点线移动
+def bg_move():
+ bg1.x -= speed
+ bg2.x -= speed
+ if bg1.right <= 0:
+ bg1.left = bg2.right
+ if bg2.right <= 0:
+ bg2.left = bg1.right
+ line.x -= speed
+ zuan.x -= speed
+ if zuan.x <= 0:
+ zuan.x = random.randint(WIDTH, WIDTH + 1500)
+ zuan.y = random.randint(100, HEIGHT - 50)
+
+ # 更新障碍物位置
+
+
+def obs_move():
+ for obs in obstacles:
+ obs.x -= speed # 障碍物随背景一起移动
+ if obs.x < 0:
+ obs.x = random.randint(WIDTH, WIDTH + 1500) # 障碍物继续出现在屏幕外
+ obs.y = random.randint(100, HEIGHT - 50)
+
+
+# 最后冲刺
+def line_collide():
+ global flag
+ if motor.collide_pixel(line):
+ flag = 1
+ else:
+ motor.x += 15
+
+
+# 判断是否与障碍物相撞
+def obs_collide():
+ global flag
+ for obs in obstacles:
+ if motor.collide_pixel(obs):
+ flag = 2
+
+
+# 收集钻石
+def zuan_collide():
+ global score
+ if motor.collide_pixel(zuan):
+ score += 1
+ zuan.x = random.randint(WIDTH, WIDTH + 1500)
+ zuan.y = random.randint(100, HEIGHT - 50)
+
+
+def update():
+ if flag == 0:
+ if line.x > WIDTH - 200: # 正常行驶
+ bg_move()
+ obs_move()
+ else: # 最后冲刺
+ line_collide()
+ # 控制赛车移动,限制不能出界
+ if keyboard.up and motor.top > 0:
+ motor.y -= 7
+ if keyboard.down and motor.bottom < HEIGHT - 50:
+ motor.y += 7
+ # 是否碰撞障碍物
+ obs_collide()
+ # 是否碰到钻石
+ zuan_collide()
+
+
+def change_image():
+ motor.next_image()
+
+
+clock.schedule_interval(change_image, 0.2)
+music.play('速度与激情')
+
+pgzrun.go()
\ No newline at end of file
diff --git a/第2讲弹幕/42弹幕讲义.pdf b/第2讲弹幕/42弹幕讲义.pdf
new file mode 100644
index 0000000..5fd58ee
Binary files /dev/null and b/第2讲弹幕/42弹幕讲义.pdf differ
diff --git a/第2讲弹幕/弹幕.png b/第2讲弹幕/弹幕.png
new file mode 100644
index 0000000..489a24f
Binary files /dev/null and b/第2讲弹幕/弹幕.png differ
diff --git a/第2讲弹幕/课堂成果/.idea/.gitignore b/第2讲弹幕/课堂成果/.idea/.gitignore
new file mode 100644
index 0000000..359bb53
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/第2讲弹幕/课堂成果/.idea/inspectionProfiles/Project_Default.xml b/第2讲弹幕/课堂成果/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..36de856
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/inspectionProfiles/profiles_settings.xml b/第2讲弹幕/课堂成果/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/material_theme_project_new.xml b/第2讲弹幕/课堂成果/.idea/material_theme_project_new.xml
new file mode 100644
index 0000000..ef4c87e
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/material_theme_project_new.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/misc.xml b/第2讲弹幕/课堂成果/.idea/misc.xml
new file mode 100644
index 0000000..23231ce
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/modules.xml b/第2讲弹幕/课堂成果/.idea/modules.xml
new file mode 100644
index 0000000..7631ecb
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/vcs.xml b/第2讲弹幕/课堂成果/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/.idea/课堂成果.iml b/第2讲弹幕/课堂成果/.idea/课堂成果.iml
new file mode 100644
index 0000000..d0876a7
--- /dev/null
+++ b/第2讲弹幕/课堂成果/.idea/课堂成果.iml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/README.md b/第2讲弹幕/课堂成果/README.md
new file mode 100644
index 0000000..58054a0
--- /dev/null
+++ b/第2讲弹幕/课堂成果/README.md
@@ -0,0 +1,3 @@
+```bash
+pip install pillow -i https://pypi.tuna.tsinghua.edu.cn/simple
+```
\ No newline at end of file
diff --git a/第2讲弹幕/课堂成果/kuang.png b/第2讲弹幕/课堂成果/kuang.png
new file mode 100644
index 0000000..cbbaffd
Binary files /dev/null and b/第2讲弹幕/课堂成果/kuang.png differ
diff --git a/第2讲弹幕/课堂成果/tv.png b/第2讲弹幕/课堂成果/tv.png
new file mode 100644
index 0000000..5eae63b
Binary files /dev/null and b/第2讲弹幕/课堂成果/tv.png differ
diff --git a/第2讲弹幕/课堂成果/弹幕.py b/第2讲弹幕/课堂成果/弹幕.py
new file mode 100644
index 0000000..86200df
--- /dev/null
+++ b/第2讲弹幕/课堂成果/弹幕.py
@@ -0,0 +1,43 @@
+import tkinter as tk
+import random
+import threading
+import time
+from PIL import Image, ImageTk
+
+class MovingLabel(threading.Thread):
+ def __init__(self, window, text):
+ threading.Thread.__init__(self)
+ self.text = text
+ self.label = tk.Label(window, image=kuang,text=self.text, compound="center",font=("黑体",20),fg='white',width=190,height=45)
+ self.label.place(x=800, y=random.randint(50, 400))
+
+ def run(self):
+ x = 800
+ while x > -200:
+ x -= 2
+ self.label.place(x=x)
+ time.sleep(0.02)
+ self.label.destroy()
+
+def send():
+ text = e1.get()
+ ml = MovingLabel(window, text)
+ ml.start()
+
+window = tk.Tk()
+window.geometry('1000x670')
+window.resizable(0,0)
+kuang = ImageTk.PhotoImage(file='kuang.png')
+
+bg_image = Image.open("tv.png")
+bg_image = ImageTk.PhotoImage(bg_image)
+bg_label = tk.Label(window, image=bg_image)
+bg_label.pack()
+
+e1=tk.Entry(window, font=("黑体", 20))
+e1.place(x=280,y=620)
+
+b1=tk.Button(window, text="发送弹幕", font=("黑体", 20), command=send)
+b1.place(x=580,y=613)
+
+window.mainloop()
diff --git a/第2讲弹幕/课堂成果/课后作业.py b/第2讲弹幕/课堂成果/课后作业.py
new file mode 100644
index 0000000..4ff18d8
--- /dev/null
+++ b/第2讲弹幕/课堂成果/课后作业.py
@@ -0,0 +1,44 @@
+import tkinter as tk
+import random
+import threading
+import time
+from PIL import Image, ImageTk
+
+class MovingLabel(threading.Thread):
+ def __init__(self, window, text):
+ threading.Thread.__init__(self)
+ self.text = text
+ self.label = tk.Label(window, image=kuang,text=self.text, compound="center",font=("黑体",20),fg='white',width=190,height=45)
+ #self.label.place(x=800, y=random.randint(10, 550))
+ self.label.place(x=random.randint(10, 550), y=300)
+
+ def run(self):
+ y = 500
+ while y > 0:
+ y -= 2
+ self.label.place(y=y)
+ time.sleep(0.02)
+ self.label.destroy()
+
+def send():
+ text = e1.get()
+ ml = MovingLabel(window, text)
+ ml.start()
+
+window = tk.Tk()
+window.geometry('1000x670')
+window.resizable(0,0)
+kuang = ImageTk.PhotoImage(file='kuang.png')
+
+bg_image = Image.open("tv.png")
+bg_image = ImageTk.PhotoImage(bg_image)
+bg_label = tk.Label(window, image=bg_image)
+bg_label.pack()
+
+e1=tk.Entry(window, font=("黑体", 20))
+e1.place(x=280,y=620)
+
+b1=tk.Button(window, text="发送弹幕", font=("黑体", 20), command=send)
+b1.place(x=580,y=613)
+
+window.mainloop()
\ No newline at end of file
diff --git a/第3讲二维码生成器/43二维码生成器讲义.pdf b/第3讲二维码生成器/43二维码生成器讲义.pdf
new file mode 100644
index 0000000..7273a47
Binary files /dev/null and b/第3讲二维码生成器/43二维码生成器讲义.pdf differ
diff --git a/第3讲二维码生成器/二维码生成器.png b/第3讲二维码生成器/二维码生成器.png
new file mode 100644
index 0000000..a6e76fe
Binary files /dev/null and b/第3讲二维码生成器/二维码生成器.png differ
diff --git a/第3讲二维码生成器/课堂成果/qrcode_bg.png b/第3讲二维码生成器/课堂成果/qrcode_bg.png
new file mode 100644
index 0000000..e296776
Binary files /dev/null and b/第3讲二维码生成器/课堂成果/qrcode_bg.png differ
diff --git a/第3讲二维码生成器/课堂成果/二维码生成器.py b/第3讲二维码生成器/课堂成果/二维码生成器.py
new file mode 100644
index 0000000..7e314e5
--- /dev/null
+++ b/第3讲二维码生成器/课堂成果/二维码生成器.py
@@ -0,0 +1,38 @@
+# 编程前,运行【安装第三方库.py】文件,安装本课用到的第三方库
+
+import tkinter
+from PIL import Image, ImageTk
+from tkinter import filedialog
+import os
+from amzqr import amzqr
+w = tkinter.Tk()
+w.geometry("400x400")
+w.resizable(0,0)
+
+bg_image = Image.open("qrcode_bg.png")
+bg_image = ImageTk.PhotoImage(bg_image)
+bg_label = tkinter.Label(w, image=bg_image)
+bg_label.pack()
+
+t1 = tkinter.Text(w, font=("微软雅黑", 12),width=30,height=5)
+t1.place(x=80, y=100)
+t2 = tkinter.Text(w, font=("微软雅黑", 12),width=23,height=1)
+t2.place(x=80, y=250)
+def get_pic():
+ pic_path = filedialog.askopenfilename()
+ t2.delete("1.0", "end")
+ t2.insert("1.0", pic_path)
+
+btn1 = tkinter.Button(w, text="浏览", font=("微软雅黑", 12), command=get_pic)
+btn1.place(x=312, y=250, height=25)
+def qr():
+ words = t1.get("1.0","end")
+ words = "".join(words.split('\n'))
+ picture = t2.get("1.0", "end")[:-1]
+ version, level, qr_name = amzqr.run(words=words, picture=picture, colorized=True)
+ os.system(qr_name)
+
+btn2 = tkinter.Button(w, text="生成二维码", font=("微软雅黑", 15), command=qr)
+btn2.place(x=80, y=300, width=250)
+w.mainloop()
+
diff --git a/第3讲二维码生成器/课堂成果/安装第三方库.py b/第3讲二维码生成器/课堂成果/安装第三方库.py
new file mode 100644
index 0000000..bef3c4e
--- /dev/null
+++ b/第3讲二维码生成器/课堂成果/安装第三方库.py
@@ -0,0 +1,7 @@
+# 点击运行【安装第三方库.py】,即可安装本课用到的第三方库
+
+import pip
+pip.main(['install','jieba'])
+pip.main(['install','wordcloud'])
+#pip.main(['install','pillow'])
+#pip.main(['install','numpy'])
\ No newline at end of file
diff --git a/第4讲邮箱轰炸1/44邮箱轰炸1讲义.pdf b/第4讲邮箱轰炸1/44邮箱轰炸1讲义.pdf
new file mode 100644
index 0000000..a754df2
Binary files /dev/null and b/第4讲邮箱轰炸1/44邮箱轰炸1讲义.pdf differ
diff --git a/第4讲邮箱轰炸1/课堂成果/email.png b/第4讲邮箱轰炸1/课堂成果/email.png
new file mode 100644
index 0000000..29670eb
Binary files /dev/null and b/第4讲邮箱轰炸1/课堂成果/email.png differ
diff --git a/第4讲邮箱轰炸1/课堂成果/课后作业.py b/第4讲邮箱轰炸1/课堂成果/课后作业.py
new file mode 100644
index 0000000..807ee45
--- /dev/null
+++ b/第4讲邮箱轰炸1/课堂成果/课后作业.py
@@ -0,0 +1,21 @@
+import smtplib
+from email.mime.text import MIMEText
+from email.utils import formataddr
+import time
+
+to=input("输入收件人:")
+count=int(input("发送次数:"))
+user='zhangsan444444z@163.com'
+password='FMORERKAQJWEBSUX'
+subject = "新年祝福"
+content = "新年快乐,祝您新年大吉!"
+msg = MIMEText(content,'html','utf-8')
+msg['Subject'] = subject
+msg['From'] = formataddr(('张三',user))
+msg['to'] = to
+s = smtplib.SMTP_SSL("smtp.163.com", 465)
+s.login(user, password)
+for i in range(count):
+ s.sendmail(user, to, msg.as_string())
+ print('成功')
+ time.sleep(2)
diff --git a/第4讲邮箱轰炸1/课堂成果/邮箱轰炸1.py b/第4讲邮箱轰炸1/课堂成果/邮箱轰炸1.py
new file mode 100644
index 0000000..b6c9e16
--- /dev/null
+++ b/第4讲邮箱轰炸1/课堂成果/邮箱轰炸1.py
@@ -0,0 +1,35 @@
+# 1 导入模块
+import smtplib
+from email.mime.text import MIMEText #往邮件中写内容的对象
+from email.utils import formataddr #发件人信息
+import time
+
+# 2 发送方和接收方配置
+# 发件方邮箱:谁发送的
+user='zhangsan444444z@163.com'
+# 生成的授权码:不能泄露
+password='FMORERKAQJWEBSUX'
+# # 发送给谁,可以写多个人,以列表形式存储
+to="zhangsan444444z@163.com"
+
+subject = "新年祝福" # 邮件主题
+content = "新年快乐,祝您新年大吉!" # 邮箱内容
+
+# 生成一个MIMEText对象(发送html格式邮件)
+msg = MIMEText(content,'html','utf-8')
+# 放入邮件主题
+msg['Subject'] = subject
+# 放入发件人,元祖中内容第一个是发件人名称,第二个是发件地址
+msg['From'] = formataddr(('张三',user))
+# 放入收件人,将收件人转化为以逗号分隔的字符串
+msg['to'] = to
+
+# 通过ssl方式发送,服务器地址,端口 465 994
+s = smtplib.SMTP_SSL("smtp.163.com", 465)
+# 登录到邮箱
+s.login(user, password)
+# 发送邮件:发送方,收件方,要发送的消息
+for i in range(5):
+ s.sendmail(user, to, msg.as_string()) # 第二个参数可以以列表的方式写多个
+ print('成功')
+ time.sleep(2)
diff --git a/第4讲邮箱轰炸1/邮箱轰炸1.png b/第4讲邮箱轰炸1/邮箱轰炸1.png
new file mode 100644
index 0000000..fb72e52
Binary files /dev/null and b/第4讲邮箱轰炸1/邮箱轰炸1.png differ
diff --git a/第5讲邮箱轰炸2/45邮箱轰炸2讲义.pdf b/第5讲邮箱轰炸2/45邮箱轰炸2讲义.pdf
new file mode 100644
index 0000000..84564ea
Binary files /dev/null and b/第5讲邮箱轰炸2/45邮箱轰炸2讲义.pdf differ
diff --git a/第5讲邮箱轰炸2/课堂成果/email.png b/第5讲邮箱轰炸2/课堂成果/email.png
new file mode 100644
index 0000000..29670eb
Binary files /dev/null and b/第5讲邮箱轰炸2/课堂成果/email.png differ
diff --git a/第5讲邮箱轰炸2/课堂成果/邮箱轰炸2.py b/第5讲邮箱轰炸2/课堂成果/邮箱轰炸2.py
new file mode 100644
index 0000000..e925e05
--- /dev/null
+++ b/第5讲邮箱轰炸2/课堂成果/邮箱轰炸2.py
@@ -0,0 +1,73 @@
+# 1 导入模块
+import smtplib
+from email.mime.text import MIMEText #往邮件中写内容的对象
+from email.utils import formataddr #发件人信息
+import time
+import tkinter
+import threading
+
+
+
+# 2 发送方和接收方配置
+# 发件方邮箱:谁发送的
+user='zhangsan444444z@163.com'
+# 生成的授权码:不能泄露
+password='FMORERKAQJWEBSUX'
+
+def send_mail():
+ to = e1.get()
+ content = t2.get("1.0", "end")
+ count = int(e3.get())
+ delay= int(e4.get())
+
+ subject = "To:{}".format(to) # 邮件主题
+ #content = "新年快乐,祝您新年大吉!" # 邮箱内容
+
+ # 生成一个MIMEText对象(发送html格式邮件)
+ msg = MIMEText(content,'html','utf-8')
+ # 放入邮件主题
+ msg['Subject'] = subject
+ # 放入发件人,元祖中内容第一个是发件人名称,第二个是发件地址
+ msg['From'] = formataddr(('张三',user))
+ # 放入收件人,将收件人转化为以逗号分隔的字符串
+ msg['to'] = to
+
+ # 通过ssl方式发送,服务器地址,端口 465 994
+ s = smtplib.SMTP_SSL("smtp.163.com", 465)
+ # 登录到邮箱
+ s.login(user, password)
+ # 发送邮件:发送方,收件方,要发送的消息
+ for i in range(count):
+ s.sendmail(user, to, msg.as_string()) # 第二个参数可以以列表的方式写多个
+ print('成功')
+ time.sleep(delay)
+
+
+def send():
+ t = threading.Thread(target=send_mail)
+ t.start()
+
+w = tkinter.Tk()
+w.geometry('800x600')
+w.resizable(0,0)
+
+bg = tkinter.PhotoImage(file='email.png')
+bg_label = tkinter.Label(w, image=bg)
+bg_label.place(x=0, y=0)
+
+e1 = tkinter.Entry(w,font=("黑体",20),width=18)
+e1.place(x=150, y=190)
+
+t2 = tkinter.Text(w,font=("黑体",20),width=18,height=8)
+t2.place(x=150, y=255)
+
+e3 = tkinter.Entry(w,font=("黑体",20),width=8)
+e3.place(x=508, y=190)
+
+e4 = tkinter.Entry(w,font=("黑体",20),width=8)
+e4.place(x=508, y=322)
+
+b5 = tkinter.Button(w, text="发送", font=("黑体",20),width=8,command=send)
+b5.place(x=508,y=425)
+
+w.mainloop()
diff --git a/第5讲邮箱轰炸2/邮箱轰炸2.png b/第5讲邮箱轰炸2/邮箱轰炸2.png
new file mode 100644
index 0000000..77f9ffb
Binary files /dev/null and b/第5讲邮箱轰炸2/邮箱轰炸2.png differ
diff --git a/第6讲太阳系/46太阳系讲义.pdf b/第6讲太阳系/46太阳系讲义.pdf
new file mode 100644
index 0000000..03cdc74
Binary files /dev/null and b/第6讲太阳系/46太阳系讲义.pdf differ
diff --git a/第6讲太阳系/46课太阳系海报.png b/第6讲太阳系/46课太阳系海报.png
new file mode 100644
index 0000000..70ae353
Binary files /dev/null and b/第6讲太阳系/46课太阳系海报.png differ
diff --git a/第6讲太阳系/课堂成果/playground.png b/第6讲太阳系/课堂成果/playground.png
new file mode 100644
index 0000000..ef945fb
Binary files /dev/null and b/第6讲太阳系/课堂成果/playground.png differ
diff --git a/第6讲太阳系/课堂成果/rabbit.gif b/第6讲太阳系/课堂成果/rabbit.gif
new file mode 100644
index 0000000..93fd967
Binary files /dev/null and b/第6讲太阳系/课堂成果/rabbit.gif differ
diff --git a/第6讲太阳系/课堂成果/sun.png b/第6讲太阳系/课堂成果/sun.png
new file mode 100644
index 0000000..c9c3e6e
Binary files /dev/null and b/第6讲太阳系/课堂成果/sun.png differ
diff --git a/第6讲太阳系/课堂成果/土星.gif b/第6讲太阳系/课堂成果/土星.gif
new file mode 100644
index 0000000..6160c99
Binary files /dev/null and b/第6讲太阳系/课堂成果/土星.gif differ
diff --git a/第6讲太阳系/课堂成果/地球.gif b/第6讲太阳系/课堂成果/地球.gif
new file mode 100644
index 0000000..17d5e76
Binary files /dev/null and b/第6讲太阳系/课堂成果/地球.gif differ
diff --git a/第6讲太阳系/课堂成果/天王星.gif b/第6讲太阳系/课堂成果/天王星.gif
new file mode 100644
index 0000000..3e94794
Binary files /dev/null and b/第6讲太阳系/课堂成果/天王星.gif differ
diff --git a/第6讲太阳系/课堂成果/太阳系.png b/第6讲太阳系/课堂成果/太阳系.png
new file mode 100644
index 0000000..43bd4b0
Binary files /dev/null and b/第6讲太阳系/课堂成果/太阳系.png differ
diff --git a/第6讲太阳系/课堂成果/太阳系.py b/第6讲太阳系/课堂成果/太阳系.py
new file mode 100644
index 0000000..70ba9df
--- /dev/null
+++ b/第6讲太阳系/课堂成果/太阳系.py
@@ -0,0 +1,72 @@
+#请在这里编写代码
+from turtle import *
+import time
+
+tracer(0)
+screen = Screen() # 创建窗口
+screen.bgpic("sun.png") # 设置背景
+screen.setup(1000, 800) # 设置窗口大小
+
+
+register_shape("水星.gif")
+mercury = Turtle()
+mercury.shape("水星.gif")
+mercury.penup()
+
+register_shape("金星.gif")
+gold = Turtle()
+gold.shape("金星.gif")
+gold.penup()
+
+register_shape("地球.gif")
+earth =Turtle()
+earth.shape("地球.gif")
+earth.penup()
+
+register_shape("火星.gif")
+mars = Turtle()
+mars.shape("火星.gif")
+mars.penup()
+mars.goto(0,-180)
+
+register_shape("木星.gif")
+mu = Turtle()
+mu.shape("木星.gif")
+mu.penup()
+mu.goto(0,-220)
+
+register_shape("土星.gif")
+tu = Turtle()
+tu.shape("土星.gif")
+tu.penup()
+tu.goto(0,-270)
+
+register_shape("天王星.gif")
+tian = Turtle()
+tian.shape("天王星.gif")
+tian.penup()
+tian.goto(0,-320)
+
+register_shape("海王星.gif")
+hai = Turtle()
+hai.shape("海王星.gif")
+hai.penup()
+hai.goto(0,-380)
+
+
+mercury.goto(0, -70)
+gold.goto(0, -100)
+earth.goto(0, -140)
+
+while True:
+ mercury.circle(70, 360 / 88)
+ gold.circle(100, 360 / 365)
+ earth.circle(140, 360 / 224)
+ mars.circle(180, 360 / 450)
+ mu.circle(220, 360 / 500)
+ tu.circle(270, 360 / 600)
+ tian.circle(320, 360 / 700)
+ hai.circle(380, 360 / 800)
+ update() # 刷新屏幕
+ time.sleep(0.01)
+
diff --git a/第6讲太阳系/课堂成果/木星.gif b/第6讲太阳系/课堂成果/木星.gif
new file mode 100644
index 0000000..87c1861
Binary files /dev/null and b/第6讲太阳系/课堂成果/木星.gif differ
diff --git a/第6讲太阳系/课堂成果/水星.gif b/第6讲太阳系/课堂成果/水星.gif
new file mode 100644
index 0000000..56c42e4
Binary files /dev/null and b/第6讲太阳系/课堂成果/水星.gif differ
diff --git a/第6讲太阳系/课堂成果/海王星.gif b/第6讲太阳系/课堂成果/海王星.gif
new file mode 100644
index 0000000..750cd46
Binary files /dev/null and b/第6讲太阳系/课堂成果/海王星.gif differ
diff --git a/第6讲太阳系/课堂成果/火星.gif b/第6讲太阳系/课堂成果/火星.gif
new file mode 100644
index 0000000..c8094c9
Binary files /dev/null and b/第6讲太阳系/课堂成果/火星.gif differ
diff --git a/第6讲太阳系/课堂成果/课后作业-龟兔赛跑.py b/第6讲太阳系/课堂成果/课后作业-龟兔赛跑.py
new file mode 100644
index 0000000..8c796ff
--- /dev/null
+++ b/第6讲太阳系/课堂成果/课后作业-龟兔赛跑.py
@@ -0,0 +1,30 @@
+#请在这里编写代码
+import turtle
+import time
+
+turtle.tracer(0)
+screen = turtle.Screen() # 创建窗口
+screen.bgpic("playground.png") # 设置背景
+screen.setup(800, 800) # 设置窗口大小
+
+
+turtle.register_shape("rabbit.gif")
+t=turtle.Pen()
+rabbit = turtle.Turtle()
+rabbit.shape("rabbit.gif")
+rabbit.penup()
+rabbit.goto(0, -200)
+t.penup()
+t.color("green")
+t.goto(0,-250)
+t.turtlesize(3)
+t.shape("turtle")
+
+while True:
+ rabbit.circle(200, 3)
+ t.circle(250, 1)
+
+
+ turtle.update() # 刷新屏幕
+ time.sleep(0.01)
+
diff --git a/第6讲太阳系/课堂成果/金星.gif b/第6讲太阳系/课堂成果/金星.gif
new file mode 100644
index 0000000..e531e7d
Binary files /dev/null and b/第6讲太阳系/课堂成果/金星.gif differ
diff --git a/第7讲字母卡牌/47字母卡牌讲义.pdf b/第7讲字母卡牌/47字母卡牌讲义.pdf
new file mode 100644
index 0000000..45d4df3
Binary files /dev/null and b/第7讲字母卡牌/47字母卡牌讲义.pdf differ
diff --git a/第7讲字母卡牌/字母卡牌.png b/第7讲字母卡牌/字母卡牌.png
new file mode 100644
index 0000000..19f6f9c
Binary files /dev/null and b/第7讲字母卡牌/字母卡牌.png differ
diff --git a/第7讲字母卡牌/课堂成果/A.gif b/第7讲字母卡牌/课堂成果/A.gif
new file mode 100644
index 0000000..9803702
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/A.gif differ
diff --git a/第7讲字母卡牌/课堂成果/ABC.ogg b/第7讲字母卡牌/课堂成果/ABC.ogg
new file mode 100644
index 0000000..b1f9a68
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/ABC.ogg differ
diff --git a/第7讲字母卡牌/课堂成果/B.gif b/第7讲字母卡牌/课堂成果/B.gif
new file mode 100644
index 0000000..01d6ce9
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/B.gif differ
diff --git a/第7讲字母卡牌/课堂成果/C.gif b/第7讲字母卡牌/课堂成果/C.gif
new file mode 100644
index 0000000..94e33f3
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/C.gif differ
diff --git a/第7讲字母卡牌/课堂成果/D.gif b/第7讲字母卡牌/课堂成果/D.gif
new file mode 100644
index 0000000..9b36474
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/D.gif differ
diff --git a/第7讲字母卡牌/课堂成果/E.gif b/第7讲字母卡牌/课堂成果/E.gif
new file mode 100644
index 0000000..ac99bff
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/E.gif differ
diff --git a/第7讲字母卡牌/课堂成果/F.gif b/第7讲字母卡牌/课堂成果/F.gif
new file mode 100644
index 0000000..d91610f
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/F.gif differ
diff --git a/第7讲字母卡牌/课堂成果/G.gif b/第7讲字母卡牌/课堂成果/G.gif
new file mode 100644
index 0000000..d8a8689
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/G.gif differ
diff --git a/第7讲字母卡牌/课堂成果/H.gif b/第7讲字母卡牌/课堂成果/H.gif
new file mode 100644
index 0000000..185960a
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/H.gif differ
diff --git a/第7讲字母卡牌/课堂成果/I.gif b/第7讲字母卡牌/课堂成果/I.gif
new file mode 100644
index 0000000..f92292b
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/I.gif differ
diff --git a/第7讲字母卡牌/课堂成果/J.gif b/第7讲字母卡牌/课堂成果/J.gif
new file mode 100644
index 0000000..b40d5b2
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/J.gif differ
diff --git a/第7讲字母卡牌/课堂成果/K.gif b/第7讲字母卡牌/课堂成果/K.gif
new file mode 100644
index 0000000..f3aa7b9
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/K.gif differ
diff --git a/第7讲字母卡牌/课堂成果/L.gif b/第7讲字母卡牌/课堂成果/L.gif
new file mode 100644
index 0000000..6218580
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/L.gif differ
diff --git a/第7讲字母卡牌/课堂成果/M.gif b/第7讲字母卡牌/课堂成果/M.gif
new file mode 100644
index 0000000..57b5c1a
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/M.gif differ
diff --git a/第7讲字母卡牌/课堂成果/N.gif b/第7讲字母卡牌/课堂成果/N.gif
new file mode 100644
index 0000000..9f544a4
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/N.gif differ
diff --git a/第7讲字母卡牌/课堂成果/O.gif b/第7讲字母卡牌/课堂成果/O.gif
new file mode 100644
index 0000000..a4939db
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/O.gif differ
diff --git a/第7讲字母卡牌/课堂成果/P.gif b/第7讲字母卡牌/课堂成果/P.gif
new file mode 100644
index 0000000..00276fa
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/P.gif differ
diff --git a/第7讲字母卡牌/课堂成果/Q.gif b/第7讲字母卡牌/课堂成果/Q.gif
new file mode 100644
index 0000000..ceb1cc2
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/Q.gif differ
diff --git a/第7讲字母卡牌/课堂成果/R.gif b/第7讲字母卡牌/课堂成果/R.gif
new file mode 100644
index 0000000..c9255a5
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/R.gif differ
diff --git a/第7讲字母卡牌/课堂成果/README.md b/第7讲字母卡牌/课堂成果/README.md
new file mode 100644
index 0000000..1109d02
--- /dev/null
+++ b/第7讲字母卡牌/课堂成果/README.md
@@ -0,0 +1,3 @@
+```bash
+pip install pygame -i https://mirrors.aliyun.com/pypi/simple/
+```
\ No newline at end of file
diff --git a/第7讲字母卡牌/课堂成果/S.gif b/第7讲字母卡牌/课堂成果/S.gif
new file mode 100644
index 0000000..33ca659
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/S.gif differ
diff --git a/第7讲字母卡牌/课堂成果/T.gif b/第7讲字母卡牌/课堂成果/T.gif
new file mode 100644
index 0000000..0e421be
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/T.gif differ
diff --git a/第7讲字母卡牌/课堂成果/U.gif b/第7讲字母卡牌/课堂成果/U.gif
new file mode 100644
index 0000000..f8cd49f
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/U.gif differ
diff --git a/第7讲字母卡牌/课堂成果/V.gif b/第7讲字母卡牌/课堂成果/V.gif
new file mode 100644
index 0000000..2f1b7e1
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/V.gif differ
diff --git a/第7讲字母卡牌/课堂成果/W.gif b/第7讲字母卡牌/课堂成果/W.gif
new file mode 100644
index 0000000..6603bcf
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/W.gif differ
diff --git a/第7讲字母卡牌/课堂成果/X.gif b/第7讲字母卡牌/课堂成果/X.gif
new file mode 100644
index 0000000..cb9a25f
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/X.gif differ
diff --git a/第7讲字母卡牌/课堂成果/Y.gif b/第7讲字母卡牌/课堂成果/Y.gif
new file mode 100644
index 0000000..21a176d
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/Y.gif differ
diff --git a/第7讲字母卡牌/课堂成果/Z.gif b/第7讲字母卡牌/课堂成果/Z.gif
new file mode 100644
index 0000000..7cdf4eb
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/Z.gif differ
diff --git a/第7讲字母卡牌/课堂成果/cardback.gif b/第7讲字母卡牌/课堂成果/cardback.gif
new file mode 100644
index 0000000..1e08184
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/cardback.gif differ
diff --git a/第7讲字母卡牌/课堂成果/jiyi.py b/第7讲字母卡牌/课堂成果/jiyi.py
new file mode 100644
index 0000000..427a491
--- /dev/null
+++ b/第7讲字母卡牌/课堂成果/jiyi.py
@@ -0,0 +1,166 @@
+import turtle
+import random
+import time
+import string
+
+def start_game(rows=8, cols=8):
+ SIZE = 80
+ COUNT = rows * cols
+ WIDTH, HEIGHT = cols * SIZE, rows * SIZE
+
+ # 初始化画布和窗口(上方留出按钮空间)
+ screen = turtle.Screen()
+ screen.setup(WIDTH + 40, HEIGHT + 80) # 上方多出40像素放按钮
+ screen.bgcolor('white')
+ screen.title("字母翻牌游戏")
+
+ # 注册字母图片(这里默认没有图片)
+ for ch in string.ascii_uppercase:
+ try:
+ turtle.addshape(f"{ch}.gif")
+ except:
+ pass
+
+ # 生成牌面内容
+ tiles = random.sample(string.ascii_uppercase * 2, COUNT // 2) * 2
+ random.shuffle(tiles)
+
+ # 卡片是否隐藏
+ hide = [True] * COUNT
+
+ # 游戏状态
+ state = {
+ 'mark': None,
+ 'matched_pair': None,
+ 'reveal': None
+ }
+
+ # 卡片乌龟
+ turtles = [turtle.Turtle() for _ in range(COUNT)]
+ for t in turtles:
+ t.hideturtle()
+ t.penup()
+
+ # 公共画笔
+ pen = turtle.Turtle()
+ pen.hideturtle()
+ pen.penup()
+
+ # 返回按钮乌龟
+ back_btn = turtle.Turtle()
+ back_btn.hideturtle()
+ back_btn.penup()
+
+ def draw_back_button():
+ back_btn.goto(-WIDTH // 2, HEIGHT // 2 + 10)
+ back_btn.color("black", "lightgray")
+ back_btn.begin_fill()
+ for _ in range(2):
+ back_btn.forward(100)
+ back_btn.left(90)
+ back_btn.forward(40)
+ back_btn.left(90)
+ back_btn.end_fill()
+ back_btn.goto(-WIDTH // 2 + 20, HEIGHT // 2 + 15)
+ back_btn.write("返回", font=("Arial", 16, "bold"))
+
+ def check_back_button(x, y):
+ bx1, by1 = -WIDTH // 2, HEIGHT // 2 + 10
+ bx2, by2 = bx1 + 100, by1 + 40
+ return bx1 <= x <= bx2 and by1 <= y <= by2
+
+ def go_back_to_menu():
+ screen.bye()
+ import youxijiemian
+ youxijiemian.show_start_window()
+ # 你可以在这里调用 Tkinter 菜单,例如:show_start_window()
+
+ def xy(i):
+ x = -WIDTH // 2 + (i % cols) * SIZE
+ y = -HEIGHT // 2 + (i // cols) * SIZE
+ return x, y
+
+ def index(x, y):
+ col = int((x + WIDTH // 2) // SIZE)
+ row = int((y + HEIGHT // 2) // SIZE)
+ i = row * cols + col
+ if 0 <= i < COUNT:
+ return i
+ return None
+
+ def draw():
+ pen.clear()
+ for i in range(COUNT):
+ x, y = xy(i)
+ t = turtles[i]
+ t.goto(x + SIZE // 2, y + SIZE // 2)
+
+ if not hide[i]:
+ t.hideturtle()
+ elif i == state.get("mark") or i == state.get("reveal") or (state.get("matched_pair") and i in state["matched_pair"]):
+ t.shape("square")
+ t.shapesize(stretch_wid=3, stretch_len=3)
+ t.color("black")
+ t.showturtle()
+ pen.goto(x + SIZE // 2 - 15, y + SIZE // 2 - 20)
+ pen.write(tiles[i], font=('Arial', 24, 'bold'))
+ else:
+ pen.goto(x, y)
+ pen.color('black', 'skyblue')
+ pen.begin_fill()
+ for _ in range(4):
+ pen.forward(SIZE - 10)
+ pen.left(90)
+ pen.end_fill()
+ t.hideturtle()
+ draw_back_button()
+ turtle.update()
+
+ def hide_matched():
+ i1, i2 = state["matched_pair"]
+ hide[i1] = False
+ hide[i2] = False
+ state["matched_pair"] = None
+ draw()
+
+ def tap(x, y):
+ if check_back_button(x, y):
+ go_back_to_menu()
+ return
+
+ i = index(x, y)
+ if i is None or not hide[i] or state.get("matched_pair"):
+ return
+
+ m = state.get("mark")
+ if m is None:
+ state["mark"] = i
+ elif m == i:
+ return
+ elif tiles[m] != tiles[i]:
+ state["reveal"] = i
+ draw()
+ time.sleep(0.5)
+ state["mark"] = None
+ state["reveal"] = None
+ else:
+ state["matched_pair"] = (m, i)
+ state["mark"] = None
+ state["reveal"] = None
+ draw()
+ screen.ontimer(hide_matched, 2000)
+
+ draw()
+ if all(not h for h in hide):
+ pen.goto(0, 0)
+ pen.color("green")
+ pen.write("🎉 全部配对成功!", font=('Arial', 24, 'bold'))
+
+ turtle.tracer(False)
+ draw()
+ turtle.onscreenclick(tap)
+ turtle.done()
+
+# 测试入口
+if __name__ == "__main__":
+ start_game(8, 8)
diff --git a/第7讲字母卡牌/课堂成果/letter.png b/第7讲字母卡牌/课堂成果/letter.png
new file mode 100644
index 0000000..2b08d03
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/letter.png differ
diff --git a/第7讲字母卡牌/课堂成果/youxijiemian.py b/第7讲字母卡牌/课堂成果/youxijiemian.py
new file mode 100644
index 0000000..74f946c
--- /dev/null
+++ b/第7讲字母卡牌/课堂成果/youxijiemian.py
@@ -0,0 +1,34 @@
+# start_menu.py
+import tkinter as tk
+import jiyi # 你的游戏模块(包含 start_game)
+
+def show_start_window():
+ def start_game(rows, cols):
+ print(f"游戏启动:{rows}行 x {cols}列")
+ root.destroy()
+ jiyi.start_game(rows, cols)
+
+ root = tk.Tk()
+ root.title("字母翻牌游戏 - 开始界面")
+ root.geometry("600x500")
+
+ tk.Label(root, text="请选择游戏难度", font=("Arial", 18)).pack(pady=20)
+
+ difficulty = tk.StringVar(value="8x8")
+ for option in ["6x6", "8x8", "10x10"]:
+ tk.Radiobutton(root, text=option, variable=difficulty, value=option,
+ font=("Arial", 16)).pack(anchor="w", padx=60, pady=8)
+
+ def on_start_click():
+ diff = difficulty.get()
+ rows, cols = map(int, diff.split("x"))
+ start_game(rows, cols)
+
+ tk.Button(root, text="开始游戏", font=("Arial", 20), bg="lightgreen",
+ command=on_start_click).pack(pady=30, ipadx=20, ipady=10)
+
+ root.mainloop()
+
+# 程序入口
+if __name__ == "__main__":
+ show_start_window()
diff --git a/第7讲字母卡牌/课堂成果/字母卡牌.py b/第7讲字母卡牌/课堂成果/字母卡牌.py
new file mode 100644
index 0000000..4802f54
--- /dev/null
+++ b/第7讲字母卡牌/课堂成果/字母卡牌.py
@@ -0,0 +1,30 @@
+# 运行程序前, 请务必前往本课包【课程说明】处,下载课程素材,完成配置
+
+from turtle import *
+import pygame
+pygame.mixer.init()
+pygame.mixer.music.load("ABC.ogg")
+pygame.mixer.music.play(-1)
+
+tracer(False)
+setup(1200,800)
+bgpic('letter.png')
+t=Pen()
+t.hideturtle()
+
+for i in range(65,91):
+ register_shape(str(chr(i))+'.gif')
+
+number=0
+def draw(x,y):
+ global number
+ t.penup()
+ t.goto(x,y)
+ t.pendown()
+ t.shape(chr(number%26+65)+".gif")
+ t.stamp()
+ number+=1
+ update()
+listen()
+onscreenclick(draw)
+done()
diff --git a/第7讲字母卡牌/课堂成果/字母卡牌素材.zip b/第7讲字母卡牌/课堂成果/字母卡牌素材.zip
new file mode 100644
index 0000000..5da9877
Binary files /dev/null and b/第7讲字母卡牌/课堂成果/字母卡牌素材.zip differ
diff --git a/第8讲蒙特卡洛法求圆周率/48蒙特卡洛法求圆周率讲义.pdf b/第8讲蒙特卡洛法求圆周率/48蒙特卡洛法求圆周率讲义.pdf
new file mode 100644
index 0000000..45e711a
Binary files /dev/null and b/第8讲蒙特卡洛法求圆周率/48蒙特卡洛法求圆周率讲义.pdf differ
diff --git a/第8讲蒙特卡洛法求圆周率/蒙特卡洛法求圆周率.png b/第8讲蒙特卡洛法求圆周率/蒙特卡洛法求圆周率.png
new file mode 100644
index 0000000..8a4e414
Binary files /dev/null and b/第8讲蒙特卡洛法求圆周率/蒙特卡洛法求圆周率.png differ
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/.gitignore b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/.gitignore
new file mode 100644
index 0000000..359bb53
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/.gitignore
@@ -0,0 +1,3 @@
+# 默认忽略的文件
+/shelf/
+/workspace.xml
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/Project_Default.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/Project_Default.xml
new file mode 100644
index 0000000..36de856
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/Project_Default.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/profiles_settings.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/profiles_settings.xml
new file mode 100644
index 0000000..105ce2d
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/inspectionProfiles/profiles_settings.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/material_theme_project_new.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/material_theme_project_new.xml
new file mode 100644
index 0000000..ef4c87e
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/material_theme_project_new.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/misc.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/misc.xml
new file mode 100644
index 0000000..23231ce
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/misc.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/modules.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/modules.xml
new file mode 100644
index 0000000..7631ecb
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/modules.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/vcs.xml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/vcs.xml
new file mode 100644
index 0000000..b2bdec2
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/课堂成果.iml b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/课堂成果.iml
new file mode 100644
index 0000000..8b8c395
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/.idea/课堂成果.iml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/dot.png b/第8讲蒙特卡洛法求圆周率/课堂成果/dot.png
new file mode 100644
index 0000000..52e3ab7
Binary files /dev/null and b/第8讲蒙特卡洛法求圆周率/课堂成果/dot.png differ
diff --git a/第8讲蒙特卡洛法求圆周率/课堂成果/随机打点法.py b/第8讲蒙特卡洛法求圆周率/课堂成果/随机打点法.py
new file mode 100644
index 0000000..9a2a571
--- /dev/null
+++ b/第8讲蒙特卡洛法求圆周率/课堂成果/随机打点法.py
@@ -0,0 +1,32 @@
+from turtle import *
+import random
+tracer(False)
+bgpic("dot.png")
+setup(1200,800)
+
+t=Pen()
+t.ht()
+t.penup()
+
+nei=0
+total=0
+
+t2=Pen()
+t2.ht()
+t2.penup()
+t2.goto(380,-50)
+
+while True:
+ x=random.randint(-200,200)
+ y=random.randint(-200,200)
+ t.goto(x,y)
+ if t.distance(0,0)<200:
+ t.dot(5,'yellow')
+ nei+=1
+ else:
+ t.dot(5,'magenta')
+ total+=1
+ pai=4*nei/total
+ t2.clear()
+ t2.write("{}\n\n{}\n\n{}".format(nei,total,round(pai,4)),font=("宋体",25,'bold'))
+ update()
diff --git a/第9讲世界时钟/49世界时钟讲义.pdf b/第9讲世界时钟/49世界时钟讲义.pdf
new file mode 100644
index 0000000..3905ba8
Binary files /dev/null and b/第9讲世界时钟/49世界时钟讲义.pdf differ
diff --git a/第9讲世界时钟/世界时钟.png b/第9讲世界时钟/世界时钟.png
new file mode 100644
index 0000000..2fcec59
Binary files /dev/null and b/第9讲世界时钟/世界时钟.png differ
diff --git a/第9讲世界时钟/课堂成果/America.png b/第9讲世界时钟/课堂成果/America.png
new file mode 100644
index 0000000..c40d143
Binary files /dev/null and b/第9讲世界时钟/课堂成果/America.png differ
diff --git a/第9讲世界时钟/课堂成果/Britain.png b/第9讲世界时钟/课堂成果/Britain.png
new file mode 100644
index 0000000..e50074c
Binary files /dev/null and b/第9讲世界时钟/课堂成果/Britain.png differ
diff --git a/第9讲世界时钟/课堂成果/China.png b/第9讲世界时钟/课堂成果/China.png
new file mode 100644
index 0000000..95e8948
Binary files /dev/null and b/第9讲世界时钟/课堂成果/China.png differ
diff --git a/第9讲世界时钟/课堂成果/Russia.png b/第9讲世界时钟/课堂成果/Russia.png
new file mode 100644
index 0000000..342a09b
Binary files /dev/null and b/第9讲世界时钟/课堂成果/Russia.png differ
diff --git a/第9讲世界时钟/课堂成果/世界时钟.py b/第9讲世界时钟/课堂成果/世界时钟.py
new file mode 100644
index 0000000..ca08cfe
--- /dev/null
+++ b/第9讲世界时钟/课堂成果/世界时钟.py
@@ -0,0 +1,64 @@
+import datetime
+from turtle import *
+
+bgpic("China.png")
+setup(1200,800)
+tracer(False)
+
+h=Pen()
+m=Pen()
+s=Pen()
+h.pensize(5)
+m.pensize(3)
+s.pensize(2)
+
+p=Pen()
+p.ht()
+p.penup()
+p.goto(-220,-345)
+
+t = datetime.datetime.now()
+cha=datetime.timedelta(hours=0)
+
+def change(x,y):
+ # print(x,y)
+ global cha
+ if -495