25级第八次实验报告

2025010089  1
2025010090  
2025010091  1
2025010092  
2025010093  1
2025010094  
2025010095  1
2025010096  
2025010097  1
2025010098 1
2025010099  
2025010100  
2025010101 1
2025010102  
2025010103  
2025010104  
2025010105  
2025010106  
2025010107  1
2025010108  
2025010109  
2025010110  
2025010112  
2025010113  
2025010114  
2025010115   1
2025010117  1
2025010118  
2025010119  1
2025010120  
2025010121  
2025010122  
2025010124  1
2025010125  1
2025010126  
2025010127  
2025010128  1
2025010130  1
2025010131  1
2025010132  

2025010089张静文

抛物线旋转面

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

# 抛物线y=x²绕y轴旋转
t = np.linspace(-2, 2, 50)
th = np.linspace(0, 2*np.pi, 50)
T, TH = np.meshgrid(t, th)

X = T*np.cos(TH)
Z = T*np.sin(TH)
Y = T**2

ax.plot_surface(X,Y,Z)
plt.show()

屏幕截图 2026-06-17 120517

 2025010090殷慧湘

import wave
import simpleaudio as sa
import os

def play_wav_audio(wav_path):
    if not os.path.exists(wav_path):
        print(f"错误:音频文件【{wav_path}】不存在,请确认文件名和存放位置!")
        return
    try:
        # 加载wav音频
        wave_obj = sa.WaveObject.from_wave_file(wav_path)
        # 播放音频
        play_obj = wave_obj.play()
        # 阻塞等待播放完成
        play_obj.wait_done()
        print("音频播放完毕!")
    except Exception as e:
        print(f"音频播放失败,异常信息:{e}")

if __name__ == "__main__":
    # 方案1:同目录直接写文件名
    audio_file = "20250821_151742_1.wav"
    # 方案2:桌面绝对路径(取消下面注释使用)
    # audio_file = r"C:\Users\30256\Desktop\20250821_151742_1.wav"
    play_wav_audio(audio_file)

  屏幕截图 2026-06-17 202823

 

2025010091张译心

损耗

 

import pygame

# 初始化窗口
pygame.init()
WIDTH, HEIGHT = 800, 600
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("全方位自由反弹小球|速度系数0.8")

# 颜色
WHITE = (255, 255, 255)
ORANGE = (255, 140, 0)
BLACK = (0, 0, 0)
GRAY = (160, 160, 160)

# 小球参数
radius = 20
x = WIDTH // 2
y = HEIGHT // 2
vx = 5.0    # X方向初速度
vy = 3.0    # Y方向初速度
e = 0.8     # 反弹速度衰减系数

# 动能统计
init_energy = vx**2 + vy**2
total_loss = 0.0

# 兼容字体,解决之前报错
try:
    font = pygame.font.SysFont("Arial", 20)
except:
    font = pygame.font.Font(None, 20)

clock = pygame.time.Clock()
FPS = 60

running = True
while running:
    # 退出窗口事件
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 小球移动
    x += vx
    y += vy

    # 左右边界碰撞
    if x <= radius or x >= WIDTH - radius:
        old_e = vx**2 + vy**2
        vx = -vx * e
        new_e = vx**2 + vy**2
        total_loss += old_e - new_e
    # 上下边界碰撞
    if y <= radius or y >= HEIGHT - radius:
        old_e = vx**2 + vy**2
        vy = -vy * e
        new_e = vx**2 + vy**2
        total_loss += old_e - new_e

    # 绘制画面
    screen.fill(WHITE)
    # 四周墙体
    pygame.draw.rect(screen, GRAY, (0, 0, WIDTH, 5))
    pygame.draw.rect(screen, GRAY, (0, HEIGHT-5, WIDTH, 5))
    pygame.draw.rect(screen, GRAY, (0, 0, 5, HEIGHT))
    pygame.draw.rect(screen, GRAY, (WIDTH-5, 0, 5, HEIGHT))
    # 绘制小球
    pygame.draw.circle(screen, ORANGE, (int(x), int(y)), radius)

    # 文字信息
    loss_rate = total_loss / init_energy
    text = f"Speed X:{abs(vx):.2f} Y:{abs(vy):.2f} | Total Energy Loss: {loss_rate:.2%}"
    text_surface = font.render(text, True, BLACK)
    screen.blit(text_surface, (10, 10))

    pygame.display.update()
    clock.tick(FPS)

pygame.quit()

屏幕截图 2026-06-17 192553

 

 2025010093惠盾

音乐加载播放

import pygame
import sys

# 初始化pygame和音频模块
pygame.init()
pygame.mixer.init()

# 窗口设置
WIDTH, HEIGHT = 400, 200
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("音乐播放器")

# 颜色定义
WHITE = (255, 255, 255)
BLACK = (0, 0, 0)

# 加载音乐文件(替换成你的音乐路径,支持 mp3 / wav)
music_path = "111.mp3"
try:
    pygame.mixer.music.load(music_path)
except Exception as e:
    print("音乐文件加载失败,请检查路径!", e)
    sys.exit()

# 播放状态标记
is_playing = False
font = pygame.font.SysFont("SimHei", 24)  # 中文支持

# 主循环
clock = pygame.time.Clock()
while True:
    screen.fill(WHITE)

    # 事件监听
    for event in pygame.event.get():
        # 关闭窗口
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        
        # 键盘按键控制
        if event.type == pygame.KEYDOWN:
            # 空格键:播放/暂停
            if event.key == pygame.K_SPACE:
                if is_playing:
                    pygame.mixer.music.pause()
                    is_playing = False
                else:
                    pygame.mixer.music.unpause()
                    pygame.mixer.music.play(-1)  # -1 代表循环播放
                    is_playing = True
            # S键:停止音乐
            if event.key == pygame.K_s:
                pygame.mixer.music.stop()
                is_playing = False

    # 绘制文字提示
    if is_playing:
        text = font.render("播放中 | 空格暂停 | S停止", True, BLACK)
    else:
        text = font.render("已暂停 | 空格播放 | S停止", True, BLACK)
    screen.blit(text, (30, 80))

    pygame.display.flip()
    clock.tick(60)

屏幕截图 2026-06-17 113922

 2025010095徐雨轩

卷积操作

import numpy as np

def conv2d_manual(input_img, kernel, stride=1, padding=0):
    """
    手动实现二维卷积
    :param input_img: 输入矩阵 (H, W)
    :param kernel: 卷积核 (kh, kw)
    :param stride: 步长
    :param padding: 边缘填充0
    :return: 卷积输出特征图
    """
    # 1. 获取尺寸
    h_in, w_in = input_img.shape
    kh, kw = kernel.shape

    # 2. 填充
    pad_h = padding
    pad_w = padding
    pad_img = np.pad(input_img, ((pad_h, pad_h), (pad_w, pad_w)), mode='constant', constant_values=0)

    # 3. 计算输出尺寸
    h_out = (h_in + 2 * padding - kh) // stride + 1
    w_out = (w_in + 2 * padding - kw) // stride + 1

    # 4. 初始化输出
    output = np.zeros((h_out, w_out))

    # 5. 滑动窗口卷积计算
    for i in range(h_out):
        for j in range(w_out):
            # 截取窗口
            window = pad_img[i * stride: i * stride + kh, j * stride: j * stride + kw]
            # 点乘求和
            output[i, j] = np.sum(window * kernel)
    return output


if __name__ == "__main__":
    # 输入图像 5x5矩阵
    image = np.array([
        [1, 2, 3, 4, 5],
        [6, 7, 8, 9, 10],
        [11, 12, 13, 14, 15],
        [16, 17, 18, 19, 20],
        [21, 22, 23, 24, 25]
    ])

    # 3x3卷积核(边缘检测核)
    conv_kernel = np.array([
        [-1, -1, -1],
        [-1,  8, -1],
        [-1, -1, -1]
    ])

    # 执行卷积 stride=1, padding=1
    result = conv2d_manual(image, conv_kernel, stride=1, padding=1)

    print("原始输入图像:")
    print(image)
    print("\n卷积核:")
    print(conv_kernel)
    print("\n卷积输出结果:")
    print(result)

 

 屏幕截图 2026-06-17 181431

 

2025010097马浩

飞机大战小游戏

import pygame
import sys
import random
from pygame.locals import *

# 初始化窗口
pygame.init()
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("飞机大战")
clock = pygame.time.Clock()
FPS = 60

# -------------------------- 精简版精灵基类(移除图集逻辑,不会报subsurface错误) --------------------------
class MySprite(pygame.sprite.Sprite):
    def __init__(self, target):
        super().__init__()
        self.target_surface = target
        self.image = None
        self.rect = None

    # 纯色精灵不需要帧动画,update空实现,不操作master_image
    def update(self, current_time):
        pass

# -------------------------- 玩家飞机 --------------------------
class Player(MySprite):
    def __init__(self, target):
        super().__init__(target)
        self.speed = 8
        # 蓝色方块
        self.image = pygame.Surface((60, 80), pygame.SRCALPHA)
        pygame.draw.rect(self.image, (0, 200, 255), self.image.get_rect())
        self.rect = self.image.get_rect()
        self.rect.centerx = SCREEN_WIDTH // 2
        self.rect.bottom = SCREEN_HEIGHT - 20

    def move(self, key_state):
        if key_state[K_LEFT] and self.rect.left > 0:
            self.rect.x -= self.speed
        if key_state[K_RIGHT] and self.rect.right < SCREEN_WIDTH:
            self.rect.x += self.speed
        if key_state[K_UP] and self.rect.top > 0:
            self.rect.y -= self.speed
        if key_state[K_DOWN] and self.rect.bottom < SCREEN_HEIGHT:
            self.rect.y += self.speed

# -------------------------- 子弹类 --------------------------
class Bullet(MySprite):
    def __init__(self, target, x, y):
        super().__init__(target)
        self.speed = 12
        # 黄色长条
        self.image = pygame.Surface((8, 20), pygame.SRCALPHA)
        pygame.draw.rect(self.image, (255, 255, 0), self.image.get_rect())
        self.rect = self.image.get_rect()
        self.rect.centerx = x
        self.rect.bottom = y

    def update(self, current_time):
        self.rect.y -= self.speed
        if self.rect.bottom < 0:
            self.kill()

# -------------------------- 敌机类 --------------------------
class Enemy(MySprite):
    def __init__(self, target):
        super().__init__(target)
        self.speed = random.randint(3, 6)
        # 红色方块
        self.image = pygame.Surface((50, 60), pygame.SRCALPHA)
        pygame.draw.rect(self.image, (255, 50, 50), self.image.get_rect())
        self.rect = self.image.get_rect()
        self.rect.x = random.randint(0, SCREEN_WIDTH - self.rect.width)
        self.rect.y = random.randint(-120, -60)

    def update(self, current_time):
        self.rect.y += self.speed
        if self.rect.top > SCREEN_HEIGHT:
            self.kill()

# -------------------------- 精灵组初始化 --------------------------
player_group = pygame.sprite.Group()
player = Player(screen)
player_group.add(player)

bullet_group = pygame.sprite.Group()
enemy_group = pygame.sprite.Group()

enemy_spawn_timer = 0
bullet_fire_timer = 0

# -------------------------- 主循环 --------------------------
while True:
    ticks = pygame.time.get_ticks()
    screen.fill((0, 0, 30))

    # 退出事件
    for event in pygame.event.get():
        if event.type == QUIT:
            pygame.quit()
            sys.exit()

    # 玩家移动控制
    key_state = pygame.key.get_pressed()
    player.move(key_state)

    # 自动发射子弹
    if ticks - bullet_fire_timer > 150:
        bullet = Bullet(screen, player.rect.centerx, player.rect.top)
        bullet_group.add(bullet)
        bullet_fire_timer = ticks

    # 生成敌机
    if ticks - enemy_spawn_timer > 800:
        enemy = Enemy(screen)
        enemy_group.add(enemy)
        enemy_spawn_timer = ticks

    # 更新所有精灵
    player_group.update(ticks)
    bullet_group.update(ticks)
    enemy_group.update(ticks)

    # 子弹碰撞敌机
    hit_dict = pygame.sprite.groupcollide(bullet_group, enemy_group, True, True)
    if hit_dict:
        print("击中敌机")

    # 玩家碰撞敌机(像素碰撞)
    crash = pygame.sprite.spritecollide(player, enemy_group, True, pygame.sprite.collide_mask)
    if crash:
        print("游戏结束!")
        pygame.quit()
        sys.exit()

    # 绘制画面
    player_group.draw(screen)
    bullet_group.draw(screen)
    enemy_group.draw(screen)

    pygame.display.update()
    clock.tick(FPS)

屏幕截图 2026-06-17 110202

 2025010098韩晓媛

小球加减速度

import pygame
import math

# 初始化pygame
pygame.init()
WIDTH, HEIGHT = 600, 400
screen = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("上下变速运动小球")
clock = pygame.time.Clock()

# 小球参数
ball_r = 20
ball_x = WIDTH // 2        # 水平固定居中
center_y = HEIGHT // 2     # 运动中心
amplitude = 160            # 【加大幅度】上下运动范围更大,变速更明显
time_count = 0             # 时间计数器,控制运动相位

# 颜色
WHITE = (255, 255, 255)
RED = (220, 30, 30)
BLACK = (0, 0, 0)
GRAY = (120, 120, 120)

running = True
while running:
    # 事件监听
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False

    # 变速核心:正弦函数模拟简谐运动,两端速度慢,中间速度快
    time_count += 0.04  # 【增大步长】整体摆动变快,快慢切换更频繁
    offset = amplitude * math.sin(time_count)
    ball_y = center_y + offset

    # 绘制背景
    screen.fill(WHITE)
    # 绘制中心参考线
    pygame.draw.line(screen, BLACK, (0, center_y), (WIDTH, center_y), 1)
    # 绘制上下极限边界线,直观看到小球运动两端
    pygame.draw.line(screen, GRAY, (0, center_y + amplitude), (WIDTH, center_y + amplitude), 1)
    pygame.draw.line(screen, GRAY, (0, center_y - amplitude), (WIDTH, center_y - amplitude), 1)
    # 绘制小球
    pygame.draw.circle(screen, RED, (ball_x, int(ball_y)), ball_r)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()

屏幕截图 2026-06-17 161118

2025010100霍延萌

叠加

from PIL import Image
import os

# 必须保留这个函数定义,放在文件最上方
def blend_two_pic(bg_path, front_path, output_name, alpha=0.5):
    # 判断文件是否存在
    if not os.path.exists(bg_path):
        print(f"错误:背景图 {bg_path} 不存在!")
        return
    if not os.path.exists(front_path):
        print(f"错误:前景图 {front_path} 不存在!")
        return

    # 打开底层背景图、上层叠加图
    bg_img = Image.open(bg_path).convert("RGB")
    front_img = Image.open(front_path).convert("RGB")
    # 统一尺寸为背景图大小
    front_img = front_img.resize(bg_img.size)

    # alpha=0.5 上层50%透明度融合
    result = Image.blend(bg_img, front_img, alpha=0.5)
    # 保存合成图片
    result.save(output_name)
    print(f"图片叠加完成,已保存为:{output_name}")

# 主运行代码(你截图里这段)
if __name__ == "__main__":
    # 方案1:图片和py代码同一文件夹(已注释,不生效)
    # background = "第一张夜景.jpg"
    # foreground = "第二张夜景.jpg"
    # save_file = "夜景叠加效果图.jpg"

    # 方案2:图片在桌面,使用绝对路径(取消#启用)
    background = r"C:\Users\30256\Desktop\第一张夜景.jpg"
    foreground = r"C:\Users\30256\Desktop\第二张夜景.jpg"
    save_file = "夜景叠加效果图.jpg"

    blend_two_pic(background, foreground, save_file, alpha=0.5)

  

  屏幕截图 2026-06-17 205956

 

 

2025010101袁泉

A*寻路

import heapq
import matplotlib.pyplot as plt

# 四方向移动:上下左右
DIRS = [(-1, 0), (1, 0), (0, -1), (0, 1)]

class Node:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.g = 0       # 起点到当前节点的实际代价
        self.h = 0       # 当前节点到终点的预估代价
        self.f = 0       # 总代价 f = g + h
        self.parent = None

    # 重载比较运算符,用于优先队列排序
    def __lt__(self, other):
        return self.f < other.f

def manhattan_h(x1, y1, x2, y2):
    """曼哈顿距离 启发函数"""
    return abs(x1 - x2) + abs(y1 - y2)

def a_star(grid, start, end):
    rows = len(grid)
    cols = len(grid[0])
    start_x, start_y = start
    end_x, end_y = end

    # 边界/障碍物判断
    if grid[start_x][start_y] == 1 or grid[end_x][end_y] == 1:
        return None

    open_heap = []
    closed = set()
    node_map = {}  # 坐标 -> 节点

    start_node = Node(start_x, start_y)
    start_node.h = manhattan_h(start_x, start_y, end_x, end_y)
    start_node.f = start_node.g + start_node.h
    heapq.heappush(open_heap, start_node)
    node_map[(start_x, start_y)] = start_node

    while open_heap:
        # 取出f值最小的节点
        cur_node = heapq.heappop(open_heap)
        cur_x, cur_y = cur_node.x, cur_node.y

        # 到达终点,回溯路径
        if (cur_x, cur_y) == (end_x, end_y):
            path = []
            while cur_node:
                path.append((cur_node.x, cur_node.y))
                cur_node = cur_node.parent
            return path[::-1]  # 反转得到起点到终点路径

        closed.add((cur_x, cur_y))

        # 遍历四个方向邻居
        for dx, dy in DIRS:
            nx = cur_x + dx
            ny = cur_y + dy

            # 越界判断
            if 0 <= nx < rows and 0 <= ny < cols:
                # 障碍物 或 已探索,跳过
                if grid[nx][ny] == 1 or (nx, ny) in closed:
                    continue

                # 新建/获取邻居节点
                if (nx, ny) not in node_map:
                    neighbor = Node(nx, ny)
                    node_map[(nx, ny)] = neighbor
                else:
                    neighbor = node_map[(nx, ny)]

                # 计算新g值(每步代价为1)
                new_g = cur_node.g + 1
                # 新路径更优则更新
                if new_g < neighbor.g or (nx, ny) not in [n for n in open_heap]:
                    neighbor.parent = cur_node
                    neighbor.g = new_g
                    neighbor.h = manhattan_h(nx, ny, end_x, end_y)
                    neighbor.f = neighbor.g + neighbor.h
                    heapq.heappush(open_heap, neighbor)

    # 无可通行路径
    return None

def visualize_path(grid, path, start, end):
    """用matplotlib可视化地图和路径"""
    plt.figure(figsize=(6, 6))
    rows = len(grid)
    cols = len(grid[0])

    # 绘制地图
    for i in range(rows):
        for j in range(cols):
            if grid[i][j] == 1:
                plt.fill_between([j, j+1], i, i+1, color='black')  # 障碍物
            else:
                plt.fill_between([j, j+1], i, i+1, color='white', edgecolor='gray')  # 空地

    # 绘制路径
    if path:
        path_x = [p[1] + 0.5 for p in path]
        path_y = [p[0] + 0.5 for p in path]
        plt.plot(path_x, path_y, color='blue', linewidth=3, label='Path')

    # 标记起点和终点
    plt.scatter(start[1]+0.5, start[0]+0.5, color='green', s=200, marker='o', label='Start')
    plt.scatter(end[1]+0.5, end[0]+0.5, color='red', s=200, marker='s', label='End')

    plt.gca().invert_yaxis()  # 让y轴从上到下
    plt.xticks(range(cols))
    plt.yticks(range(rows))
    plt.grid(True)
    plt.legend()
    plt.title("A* Pathfinding Visualization")
    plt.show()

# ===================== 测试运行 =====================
if __name__ == "__main__":
    # 地图:0=可通行  1=障碍物
    maze = [
        [0, 0, 0, 0, 0],
        [0, 1, 1, 1, 0],
        [0, 0, 0, 1, 0],
        [1, 1, 0, 0, 0],
        [0, 0, 0, 1, 0]
    ]
    start_pos = (0, 0)   # 起点坐标
    end_pos = (4, 4)     # 终点坐标

    result_path = a_star(maze, start_pos, end_pos)
    print("寻路路径坐标:", result_path)
    print("\n地图可视化:")
    visualize_path(maze, result_path, start_pos, end_pos)

屏幕截图 2026-06-17 105315

 

 

2025010107孙瑞妍

# -*- coding: utf-8 -*-
"""
Python聚类分析综合示例(教材风格)
算法:K-Means 聚类
"""

# 1. 导入所需库
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import silhouette_score

# 设置中文显示(可选,解决图中中文乱码)
plt.rcParams["font.family"] = ["SimHei", "WenQuanYi Micro Hei", "Heiti TC"]
plt.rcParams["axes.unicode_minus"] = False

# 2. 构造/读取数据集(模拟教材常用二维样本数据)
data = {
    '特征1': [2.0, 1.8, 3.2, 8.0, 7.5, 9.1, 4.0, 4.2, 3.8, 6.5, 6.8, 7.2],
    '特征2': [1.5, 1.2, 1.8, 7.0, 6.8, 7.3, 2.1, 2.3, 2.0, 5.5, 5.8, 6.1]
}
df = pd.DataFrame(data)
print("原始数据:")
print(df)

# 3. 数据标准化(聚类必须做,消除量纲影响)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(df)

# 4. 肘部法则选择最佳聚类数(教材必讲)
inertia_list = []
k_list = range(1, 7)
for k in k_list:
    kmeans = KMeans(n_clusters=k, random_state=0)
    kmeans.fit(X_scaled)
    inertia_list.append(kmeans.inertia_)

# 绘制肘部图
plt.figure(figsize=(6, 4))
plt.plot(k_list, inertia_list, marker='o')
plt.xlabel("聚类数量 k")
plt.ylabel("簇内误差平方和")
plt.title("肘部法则确定最佳k值")
plt.show()

# 5. 执行K-Means聚类(假设选k=3,可根据肘部图修改)
k = 3
kmeans_model = KMeans(n_clusters=k, random_state=0)
df['聚类标签'] = kmeans_model.fit_predict(X_scaled)

# 6. 输出聚类结果
print("\n聚类后数据:")
print(df)
print("\n聚类中心:")
print(kmeans_model.cluster_centers_)

# 7. 轮廓系数评估聚类效果(教材评价指标)
sil_score = silhouette_score(X_scaled, df['聚类标签'])
print(f"\n轮廓系数(越接近1效果越好):{sil_score:.4f}")

# 8. 聚类结果可视化
plt.figure(figsize=(6, 5))
plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=df['聚类标签'], cmap='rainbow', s=60)
plt.scatter(kmeans_model.cluster_centers_[:,0],
            kmeans_model.cluster_centers_[:,1],
            c='black', marker='X', s=150, label='聚类中心')
plt.xlabel("特征1(标准化)")
plt.ylabel("特征2(标准化)")
plt.title("K-Means聚类结果")
plt.legend()
plt.show()

 

屏幕截图 2026-06-17 211642

 

2025010115  康静茹

制作一个Windows屏保(动态)

import pygame
import sys
import random

# 初始化
pygame.init()
screen_info = pygame.display.Info()
W, H = screen_info.current_w, screen_info.current_h
screen = pygame.display.set_mode((W, H), pygame.FULLSCREEN)
pygame.mouse.set_visible(False)
clock = pygame.time.Clock()

# 粉色系 + 透明度 (R,G,B,Alpha)
PINK_COLOR = (255, 150, 200, 120)

class Bubble:
    def __init__(self):
        self.r = random.randint(18, 50)
        self.x = random.randint(self.r, W - self.r)
        self.y = random.randint(self.r, H - self.r)
        self.vx = random.uniform(-1.8, 1.8)
        self.vy = random.uniform(-1.8, 1.8)

    def update(self):
        self.x += self.vx
        self.y += self.vy
        # 边界反弹
        if self.x - self.r < 0 or self.x + self.r > W:
            self.vx *= -1
        if self.y - self.r < 0 or self.y + self.r > H:
            self.vy *= -1

    def draw(self, surf):
        # 透明画布绘制气泡
        buf = pygame.Surface((self.r*2, self.r*2), pygame.SRCALPHA)
        pygame.draw.circle(buf, PINK_COLOR, (self.r, self.r), self.r)
        surf.blit(buf, (int(self.x - self.r), int(self.y - self.r)))

# 气泡碰撞逻辑
def collide(bub_list):
    for i in range(len(bub_list)):
        for j in range(i + 1, len(bub_list)):
            b1, b2 = bub_list[i], bub_list[j]
            dx = b1.x - b2.x
            dy = b1.y - b2.y
            dist = (dx**2 + dy**2) ** 0.5
            min_d = b1.r + b2.r
            if dist < min_d:
                # 交换速度实现弹性碰撞
                b1.vx, b2.vx = b2.vx, b1.vx
                b1.vy, b2.vy = b2.vy, b1.vy
                # 分离防止粘连
                if dist != 0:
                    offset = min_d - dist
                    b1.x += dx / dist * offset / 2
                    b1.y += dy / dist * offset / 2
                    b2.x -= dx / dist * offset / 2
                    b2.y -= dy / dist * offset / 2

# 创建气泡,数量可自行修改
bubble_num = 15
bubbles = [Bubble() for _ in range(bubble_num)]

running = True
while running:
    # 退出监听
    for e in pygame.event.get():
        if e.type in (pygame.QUIT, pygame.KEYDOWN, pygame.MOUSEBUTTONDOWN):
            running = False
        if e.type == pygame.MOUSEMOTION:
            if abs(e.rel[0]) > 8 or abs(e.rel[1]) > 8:
                running = False

    # 深色背景衬托粉色透明气泡
    screen.fill((5, 5, 15))

    # 更新、碰撞、绘制
    for b in bubbles:
        b.update()
    collide(bubbles)
    for b in bubbles:
        b.draw(screen)

    pygame.display.flip()
    clock.tick(60)

pygame.quit()
sys.exit()

局部截取_20260617_124251

54395f1a8914e76e963ccbecb64326f0

2025010117  李欣栎

消消乐

import pygame
import random

# 基础配置常量
pygame.init()
BLOCK_SIZE = 60
MAP_SIZE = 8
WIN_WIDTH = BLOCK_SIZE * MAP_SIZE
WIN_HEIGHT = BLOCK_SIZE * MAP_SIZE
screen = pygame.display.set_mode((WIN_WIDTH, WIN_HEIGHT))
pygame.display.set_caption("简易消消乐")
clock = pygame.time.Clock()
FPS = 60

# 方块颜色列表
BLOCK_COLORS = [
    (255, 70, 70),
    (70, 255, 70),
    (70, 70, 255),
    (255, 255, 70),
    (255, 70, 255)
]

# 生成空白棋盘
def create_board():
    board = []
    for r in range(MAP_SIZE):
        row = []
        for c in range(MAP_SIZE):
            row.append(random.randint(0, len(BLOCK_COLORS)-1))
        board.append(row)
    return board

# 绘制界面
def render_board(board, selected=None):
    # 填充背景(必须是三元组,不能少括号)
    screen.fill((20, 20, 20))
    for r in range(MAP_SIZE):
        for c in range(MAP_SIZE):
            x = c * BLOCK_SIZE
            y = r * BLOCK_SIZE
            color_idx = board[r][c]
            # 绘制方块
            pygame.draw.rect(
                screen,
                BLOCK_COLORS[color_idx],
                (x + 2, y + 2, BLOCK_SIZE - 4, BLOCK_SIZE - 4)
            )
            # 选中白框
            if selected is not None and selected[0] == r and selected[1] == c:
                pygame.draw.rect(
                    screen,
                    (255, 255, 255),
                    (x, y, BLOCK_SIZE, BLOCK_SIZE),
                    3
                )
    # 刷新画面
    pygame.display.flip()

# 查找所有可消除方块坐标
def find_all_matches(board):
    match_pos = set()
    # 横向三消检测
    for r in range(MAP_SIZE):
        c = 0
        while c <= MAP_SIZE - 3:
            val = board[r][c]
            if val == board[r][c+1] and val == board[r][c+2]:
                match_pos.add((r, c))
                match_pos.add((r, c+1))
                match_pos.add((r, c+2))
            c += 1
    # 纵向三消检测
    for c in range(MAP_SIZE):
        r = 0
        while r <= MAP_SIZE - 3:
            val = board[r][c]
            if val == board[r+1][c] and val == board[r+2][c]:
                match_pos.add((r, c))
                match_pos.add((r+1, c))
                match_pos.add((r+2, c))
            r += 1
    return match_pos

# 消除方块+下落填充
def remove_and_drop(board, match_set):
    # 标记消除位置
    for (r, c) in match_set:
        board[r][c] = None
    # 逐列处理下落
    for c in range(MAP_SIZE):
        col_data = []
        # 收集本列未消除方块
        for r in range(MAP_SIZE):
            if board[r][c] is not None:
                col_data.append(board[r][c])
        # 上方生成新方块
        new_blocks = [random.randint(0, 4) for _ in range(MAP_SIZE - len(col_data))]
        full_col = new_blocks + col_data
        # 写回棋盘
        for r in range(MAP_SIZE):
            board[r][c] = full_col[r]

# 交换两个格子
def swap_block(board, r1, c1, r2, c2):
    board[r1][c1], board[r2][c2] = board[r2][c2], board[r1][c1]

# 鼠标坐标转棋盘行列
def mouse_to_cell(mx, my):
    c = mx // BLOCK_SIZE
    r = my // BLOCK_SIZE
    if 0 <= r < MAP_SIZE and 0 <= c < MAP_SIZE:
        return (r, c)
    return None

def main_game():
    game_board = create_board()
    selected_cell = None
    running = True

    while running:
        # 事件优先处理,防止窗口卡死
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False
            # 鼠标点击交换逻辑
            if event.type == pygame.MOUSEBUTTONDOWN:
                cell = mouse_to_cell(*pygame.mouse.get_pos())
                if cell is None:
                    continue
                if selected_cell is None:
                    selected_cell = cell
                else:
                    r1, c1 = selected_cell
                    r2, c2 = cell
                    # 判断是否相邻
                    if abs(r1 - r2) + abs(c1 - c2) == 1:
                        swap_block(game_board, r1, c1, r2, c2)
                        # 交换后无消除则还原
                        matches = find_all_matches(game_board)
                        if len(matches) == 0:
                            swap_block(game_board, r1, c1, r2, c2)
                    selected_cell = None

        # 连锁消除(加画面刷新,不会卡死)
        matches = find_all_matches(game_board)
        while len(matches) > 0:
            remove_and_drop(game_board, matches)
            render_board(game_board, selected_cell)
            pygame.time.delay(100)  # 消除停顿,避免死循环卡死
            matches = find_all_matches(game_board)

        # 绘制当前棋盘
        render_board(game_board, selected_cell)
        clock.tick(FPS)

    pygame.quit()

if __name__ == "__main__":
    main_game()

282550864d63daa23eeef87032ba8919

912d49c6fd2bbd0805135c70f1e85a28

 2025010119 淡郑雪

两张图拼接

from PIL import Image


def merge_two_img(img1_path, img2_path, save_path, direction="horizontal"):
    """
    拼接两张图片
    :param img1_path: 第一张图路径
    :param img2_path: 第二张图路径
    :param save_path: 输出保存路径
    :param direction: horizontal左右拼接 / vertical上下拼接
    """
    # 打开图片
    img1 = Image.open(img1_path)
    img2 = Image.open(img2_path)

    # 统一高度(左右拼接)/统一宽度(上下拼接)
    if direction == "horizontal":
        # 左右拼接:高度取两张图最大值
        target_h = max(img1.height, img2.height)
        # 等比例缩放两张图
        img1 = img1.resize((img1.width, target_h), Image.Resampling.LANCZOS)
        img2 = img2.resize((img2.width, target_h), Image.Resampling.LANCZOS)
        # 新建画布
        new_w = img1.width + img2.width
        new_h = target_h
        new_img = Image.new("RGB", (new_w, new_h))
        # 粘贴图片
        new_img.paste(img1, (0, 0))
        new_img.paste(img2, (img1.width, 0))

    elif direction == "vertical":
        # 上下拼接:宽度取两张图最大值
        target_w = max(img1.width, img2.width)
        img1 = img1.resize((target_w, img1.height), Image.Resampling.LANCZOS)
        img2 = img2.resize((target_w, img2.height), Image.Resampling.LANCZOS)
        new_w = target_w
        new_h = img1.height + img2.height
        new_img = Image.new("RGB", (new_w, new_h))
        new_img.paste(img1, (0, 0))
        new_img.paste(img2, (0, img1.height))

    # 保存结果
    new_img.save(save_path)
    print(f"图片拼接完成,保存至:{save_path}")
    return new_img


# ========== 使用示例 ==========
if __name__ == "__main__":
    # 替换成你的两张图片路径
    pic1 = "1.jpg"
    pic2 = "2.jpg"
    output = "merge_result.jpg"

    # 左右拼接
    merge_two_img(pic1, pic2, output, direction="horizontal")

    # 上下拼接取消注释运行
    # merge_two_img(pic1, pic2, "vertical_merge.jpg", direction="vertical")

屏幕截图 2026-06-17 173611

 

2025010124 胡鑫

加载图片

import cv2

# 替换成你的图片路径,相对/绝对路径都可以
img_path = "test.jpg"

# 读取图片
img = cv2.imread(img_path)

# 判断是否读取成功
if img is None:
    print("图片读取失败,请检查路径是否正确")
else:
    # 弹出窗口显示图片
    cv2.imshow("Picture", img)
    # 等待按键,任意键关闭窗口
    cv2.waitKey(0)
    # 释放所有窗口
    cv2.destroyAllWindows()

截屏2026-06-17 13.19.35

 

2025010125   刘芮孜

聚类分析图

import requests
import pandas as pd
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
}

def get_forbes_data():
    try:
        url = "https://forbes400.herokuapp.com/api/forbes400/getAllForbes400"
        res = requests.get(url, headers=headers, timeout=10)
        data = res.json()
        df = pd.DataFrame(data)
        df = df[['name', 'netWorth', 'source', 'industry']]
        df['netWorth'] = pd.to_numeric(df['netWorth'], errors='coerce')
        return df.dropna()
    except Exception as e:
        print(f"线上榜单接口无法访问,加载模拟富豪数据集:{e}")
        mock_data = [
            {"name":"Elon Musk","netWorth":219,"source":"Tesla/SpaceX","industry":"高端制造/航天"},
            {"name":"Jeff Bezos","netWorth":171,"source":"Amazon","industry":"电商零售"},
            {"name":"Bernard Arnault","netWorth":158,"source":"LVMH","industry":"奢侈品制造"},
            {"name":"Bill Gates","netWorth":129,"source":"Microsoft","industry":"软件信息技术"},
            {"name":"Warren Buffett","netWorth":118,"source":"Berkshire","industry":"金融投资"},
            {"name":"Larry Page","netWorth":111,"source":"Google","industry":"互联网科技"},
            {"name":"Sergey Brin","netWorth":107,"source":"Google","industry":"互联网科技"},
            {"name":"Steve Ballmer","netWorth":91,"source":"Microsoft","industry":"软件信息技术"},
            {"name":"Larry Ellison","netWorth":106,"source":"Oracle","industry":"软件信息技术"},
            {"name":"Gautam Adani","netWorth":90,"source":"基建能源","industry":"能源上游"},
            {"name":"Mukesh Ambani","netWorth":83,"source":"石化","industry":"化工上游"},
            {"name":"Zhang Yiming","netWorth":50,"source":"TikTok","industry":"互联网平台"},
            {"name":"Zhong Shanshan","netWorth":68,"source":"农夫山泉","industry":"消费品下游"},
            {"name":"Li Ka-shing","netWorth":32,"source":"地产港口","industry":"地产基建下游"},
            {"name":"Cathy Wood","netWorth":1.5,"source":"基金","industry":"金融服务下游"}
        ]
        return pd.DataFrame(mock_data)

def classify_chain(industry):
    upstream = {"能源上游","化工上游","高端制造/航天","矿产","芯片原料","重工原材料"}
    downstream = {"电商零售","奢侈品制造","消费品下游","地产基建下游"}
    neutral = {"互联网科技","软件信息技术","金融投资","互联网平台","金融服务下游"}
    if industry in upstream:
        return "上游产业"
    elif industry in downstream:
        return "下游产业"
    elif industry in neutral:
        return "中性服务业"
    else:
        return "其他行业"

df = get_forbes_data()
df['产业链分类'] = df['industry'].apply(classify_chain)

# 统计占比表格
chain_count = df['产业链分类'].value_counts()
person_ratio = round(chain_count / len(df) * 100, 2)
total_wealth = df.groupby('产业链分类')['netWorth'].sum()
wealth_ratio = round(total_wealth / df['netWorth'].sum() * 100, 2)

stat_table = pd.DataFrame({
    "富豪人数": chain_count,
    "人数占比(%)": person_ratio,
    "总财富(百亿美元)": total_wealth,
    "财富占比(%)": wealth_ratio
})

# 控制台打印结果
print("="*65)
print("福布斯富豪榜 上下游产业统计分析表")
print("="*65)
print(stat_table)

# 绘制图表
plt.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False
fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15,6))

ax1.pie(stat_table['富豪人数'], labels=stat_table.index, autopct='%1.2f%%', startangle=90)
ax1.set_title('各产业链富豪人数分布占比')

ax2.bar(stat_table.index, stat_table['总财富(百亿美元)'])
ax2.set_title('各产业链总财富规模(单位:百亿美元)')
ax2.set_ylabel("财富总值")
plt.tight_layout()
plt.show()

# 导出Excel文件
with pd.ExcelWriter('福布斯富豪产业分析结果.xlsx') as writer:
    df.to_excel(writer, sheet_name='富豪原始明细', index=False)
    stat_table.to_excel(writer, sheet_name='产业链占比统计')

print("\n✅ 分析完成,Excel文件已生成:福布斯富豪产业分析结果.xlsx")

据

 

2025010127 刘杨龙

from PIL import Image

# 加载图片
img = Image.open("123.png")

# 查看属性
print("图片尺寸:", img.size)   # (宽, 高)
print("图片模式:", img.mode)   # RGB/RGBA/L等

# 显示图片
img.show()

# 保存图片
img.save("output.png")

屏幕截图 2026-06-17 134814

 

 2025010128   贾姝慧

视频追踪

# 导入opencv库,用来画图、显示画面、识别红点
import cv2
# 导入numpy库,用来处理数组、颜色阈值这些数据
import numpy as np

# 设置生成画面的宽度 800像素
WIDTH = 600
# 设置生成画面的高度 600像素
HEIGHT = 400

# 红点最开始出现的横坐标
x, y = 100, 100
# 红点水平移动的速度
speed_x = 3
# 红点竖直移动的速度
speed_y = 2e5
# 绘制的红色圆点半径大小
dot_r = 12

# HSV空间里红色下限,用来筛选画面里的红色区域
lower_red = np.array([0, 120, 70])
# HSV空间里红色上限,配合下限框出红色范围
upper_red = np.array([10, 255, 255])

# 定义窗口名字,后面显示画面要用
win_name = "自建视频-红点实时追踪"

# 死循环,不断生成每一帧画面,模拟连续视频
while True:
    # 创建一张纯黑色画布,对应视频的一帧画面
    frame = np.zeros((HEIGHT, WIDTH, 3), dtype=np.uint8)

    # 在画布上绘制红色实心圆点,BGR(0,0,255)是红色,-1代表填充内部
    cv2.circle(frame, (int(x), int(y)), dot_r, (0, 0, 255), -1)

    # 横坐标加上速度,让红点左右移动
    x += speed_x
    # 纵坐标加上速度,让红点上下移动
    y += speed_y

    # 碰到左右边界时,水平速度反向,实现左右反弹
    if x <= dot_r or x >= WIDTH - dot_r:
        speed_x = -speed_x
    # 碰到上下边界时,竖直速度反向,实现上下反弹
    if y <= dot_r or y >= HEIGHT - dot_r:
        speed_y = -speed_y

    # 把RGB画面转换成HSV色彩空间,方便更好的识别颜色
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)
    # 根据设置的红色阈值,生成掩码,只保留红色区域,其余地方变黑
    mask = cv2.inRange(hsv, lower_red, upper_red)
    # 创建3*3的卷积核,用于图像降噪
    kernel = np.ones((3, 3), np.uint8)
    # 闭运算,去除小噪点,让红色区域更完整
    mask = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel)

    # 在掩码图里查找所有轮廓,也就是找到红色区域的边缘
    contours, _ = cv2.findContours(mask, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    # 遍历每一个找到的轮廓
    for cnt in contours:
        # 计算当前轮廓的面积
        area = cv2.contourArea(cnt)
        # 面积太小的噪点直接跳过,不做追踪
        if area < 10:
            continue
        # 给轮廓包裹最小外接圆,获取圆心坐标和圆半径
        (cx, cy), r = cv2.minEnclosingCircle(cnt)
        # 把浮点型的圆心转成整数像素坐标
        center = (int(cx), int(cy))
        # 用绿色圆圈框住识别到的红点
        cv2.circle(frame, center, int(r), (0, 255, 0), 2)
        # 在红点中心画一个蓝色小点标记追踪中心
        cv2.circle(frame, center, 4, (255, 0, 0), -1)
        # 在控制台实时打印识别出来的红点XY坐标
        print(f"追踪到红点坐标 X:{cx:.2f}  Y:{cy:.2f}")

    # 弹出窗口,展示当前这一帧画面
    cv2.imshow(win_name, frame)

    # 等待20毫秒,监听键盘按键
    key = cv2.waitKey(20) & 0xFF
    # 如果按下ESC键,跳出循环结束程序
    if key == 27:
        break
    # 如果手动点击窗口右上角×关闭窗口,也跳出循环
    if cv2.getWindowProperty(win_name, cv2.WND_PROP_VISIBLE) < 1:
        break

# 循环结束,关闭所有opencv打开的窗口,释放资源
cv2.destroyAllWindows()

屏幕截图 2026-06-17 122445

 2025010130任鸿杰

from PIL import Image

# 打开图片
img = Image.open("123.jpg")
# 放大2倍,双线性插值
new_size = (img.width * 2, img.height * 2)
resized_img = img.resize(new_size, Image.BILINEAR)
# 保存
resized_img.save("big_img.jpg")
resized_img.show()

  屏幕截图 2026-06-17 125338

 2025010131 董玥卓

加载音频

from playsound import playsound
import os

# 获取当前脚本目录
current_path = os.path.dirname(__file__)
audio_file = os.path.join(current_path, "audio.mp3")

# 直接播放mp3
playsound(audio_file)

截屏2026-06-17 13.20.13

 

posted @ 2026-06-17 21:34  szmtjs10  阅读(5)  评论(0)    收藏  举报