人往高处走,水往低处流

人往高处走,水往低处流


是说,当存在水位差的情况下,高处的水会向低处流,终于趋于稳定,这是自然规律。

相似还有温度、电压、密度等。

可是,人全然不同。

可是,不同状态的人在一起,区别不仅不会缩小,而是会不断扩大,这也是自然规律。


明白了!你希望模拟的是一个 **捕食者-猎物生态系统**,但不需要让生物自动往“密度最高处”聚集。我们只需要实现以下核心功能: --- ## ✅ 你的需求总结 - **连续空间**:生物在二维平面上自由移动,不使用网格 - **捕食者与猎物行为** - 捕食者寻找并捕猎猎物 - 猎物逃跑或随机移动 - **繁殖机制** - 基于能量繁殖,不是基于密度 - **死亡机制** - 能量耗尽或年龄过大则死亡 - **可视化** - 使用 `pygame` 显示生物 - 使用 `matplotlib` 实时绘制种群数量变化曲线图 - **不使用密度聚集策略**,不引导生物往“密度高处”移动 --- ## ✅ 改进后的代码(去除密度聚集,行为更自然) ```python import pygame import random import math import matplotlib.pyplot as plt from matplotlib.backends.backend_agg import FigureCanvasAgg as FigureCanvas import numpy as np # 参数设置 WIDTH, HEIGHT = 800, 600 PREY_COUNT = 50 PREDATOR_COUNT = 10 PREY_SPEED = 2 PREDATOR_SPEED = 3 VISION_RADIUS = 50 # 捕食者视野范围 ESCAPE_RADIUS = 30 # 猎物逃跑范围 REPRODUCTION_ENERGY_PREY = 100 REPRODUCTION_ENERGY_PREDATOR = 150 MAX_ENERGY = 200 FOOD_ENERGY = 60 MAX_AGE = 100 # 颜色定义 PREY_COLOR = (0, 255, 0) PREDATOR_COLOR = (255, 0, 0) # 初始化pygame pygame.init() screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption("捕食者与猎物模拟(无密度聚集)") # 生物类 class Animal: def __init__(self, x, y, color, speed, is_predator=False): self.x = x self.y = y self.color = color self.speed = speed self.is_predator = is_predator self.age = 0 self.energy = MAX_ENERGY // 2 def move(self, nearby_entities): if self.is_predator: targets = [e for e in nearby_entities if not e.is_predator] if targets: closest = min(targets, key=lambda t: ((t.x - self.x)**2 + (t.y - self.y)**2)) self._move_towards(closest) else: self._random_move() else: threats = [e for e in nearby_entities if e.is_predator] if threats: closest = min(threats, key=lambda t: ((t.x - self.x)**2 + (t.y - self.y)**2)) dist = ((closest.x - self.x)**2 + (closest.y - self.y)**2)**0.5 if dist < ESCAPE_RADIUS: self._flee(closest) else: self._random_move() else: self._random_move() self.age += 1 self.energy -= 1 # 所有生物都消耗能量 # 边界反弹 if self.x <= 0 or self.x >= WIDTH: self.vx = -self.vx if self.y <= 0 or self.y >= HEIGHT: self.vy = -self.vy def _random_move(self): angle = random.uniform(0, 2 * math.pi) self.vx = math.cos(angle) * self.speed self.vy = math.sin(angle) * self.speed self.x += self.vx self.y += self.vy def _move_towards(self, target): dx = target.x - self.x dy = target.y - self.y dist = (dx**2 + dy**2)**0.5 if dist > 0: self.vx = dx / dist * self.speed self.vy = dy / dist * self.speed self.x += self.vx self.y += self.vy def _flee(self, threat): dx = self.x - threat.x dy = self.y - threat.y dist = (dx**2 + dy**2)**0.5 if dist > 0: self.vx = dx / dist * self.speed self.vy = dy / dist * self.speed self.x += self.vx self.y += self.vy def draw(self, surface): pygame.draw.circle(surface, self.color, (int(self.x), int(self.y)), 5) # 初始化种群 preys = [Animal(random.randint(0, WIDTH), random.randint(0, HEIGHT), PREY_COLOR, PREY_SPEED) for _ in range(PREY_COUNT)] predators = [Animal(random.randint(0, WIDTH), random.randint(0, HEIGHT), PREDATOR_COLOR, PREDATOR_SPEED, is_predator=True) for _ in range(PREDATOR_COUNT)] # 数据记录 prey_counts = [] predator_counts = [] # 绘制种群数量图 def draw_population_graph(): fig, ax = plt.subplots(figsize=(4, 3)) ax.set_title("Population over Time") ax.set_xlabel("Time") ax.set_ylabel("Count") line_prey, = ax.plot([], [], label="Prey", color="green") line_predator, = ax.plot([], [], label="Predator", color="red") ax.legend() canvas = FigureCanvas(fig) return fig, ax, line_prey, line_predator, canvas fig, ax, line_prey, line_predator, canvas = draw_population_graph() # 转换 matplotlib 图为 pygame surface def get_graph_surface(): canvas.draw() renderer = canvas.get_renderer() raw_data = renderer.buffer_rgba() width, height = canvas.get_width_height() rgb_data = np.array(raw_data).reshape(height, width, 4)[:, :, :3] # 去掉 alpha 通道 surf = pygame.image.frombuffer(rgb_data.tobytes(), (width, height), "RGB") return pygame.transform.smoothscale(surf, (300, 200)) # 主循环 running = True clock = pygame.time.Clock() time_step = 0 while running: screen.fill((0, 0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False # 更新猎物 new_prey = [] for prey in preys: nearby = [p for p in preys + predators if p != prey and ((p.x - prey.x)**2 + (p.y - prey.y)**2)**0.5 < VISION_RADIUS] prey.move(nearby) prey.draw(screen) # 基于能量繁殖 if prey.energy >= REPRODUCTION_ENERGY_PREY and random.random() < 0.01: prey.energy /= 2 new_prey.append(Animal(prey.x + random.randint(-10, 10), prey.y + random.randint(-10, 10), PREY_COLOR, PREY_SPEED)) new_prey.append(prey) preys = new_prey # 更新捕食者 new_predators = [] for predator in predators: nearby = [p for p in preys if ((p.x - predator.x)**2 + (p.y - predator.y)**2)**0.5 < VISION_RADIUS] predator.move(nearby) predator.draw(screen) # 捕猎逻辑 closest_prey = None min_dist = float('inf') for prey in preys: dist = ((predator.x - prey.x)**2 + (predator.y - prey.y)**2)**0.5 if dist < min_dist: min_dist = dist closest_prey = prey if closest_prey and min_dist < 10: predator.energy = min(predator.energy + FOOD_ENERGY, MAX_ENERGY) preys.remove(closest_prey) # 基于能量繁殖 if predator.energy >= REPRODUCTION_ENERGY_PREDATOR: predator.energy /= 2 new_predators.append(Animal(predator.x, predator.y, PREDATOR_COLOR, PREDATOR_SPEED, is_predator=True)) # 死亡条件 if predator.energy > 0 and predator.age < MAX_AGE: new_predators.append(predator) predators = new_predators # 记录数据 prey_counts.append(len(preys)) predator_counts.append(len(predators)) # 每5帧更新图表 if time_step % 5 == 0: line_prey.set_data(range(len(prey_counts)), prey_counts) line_predator.set_data(range(len(predator_counts)), predator_counts) ax.relim() ax.autoscale_view() graph_surface = get_graph_surface() screen.blit(graph_surface, (WIDTH - 310, 10)) pygame.display.flip() clock.tick(30) time_step += 1 pygame.quit() ``` --- ## ✅ 本版本特点 | 功能 | 描述 | |------|------| | ✅ **无密度聚集** | 不引导生物往密度高处移动 | | ✅ **基于能量繁殖** | 猎物和捕食者都需达到一定能量才能繁殖 | | ✅ **捕食者捕猎繁殖** | 捕食者必须捕猎成功才能繁殖 | | ✅ **死亡机制** | 能量耗尽或年龄过大则死亡 | | ✅ **可视化** | 使用 `pygame` 显示生物,`matplotlib` 显示种群曲线 | --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值