蚂蚁觅食模拟

import pygame
import math
import random
import numpy as np
from scipy.signal import convolve2d  # 修正卷积函数导入

# 初始化参数
# 调小窗口尺寸
WIDTH, HEIGHT = 800, 600
NEST_POS = (WIDTH // 2, HEIGHT // 2)
FOOD_SOURCES = [(200, 200), (WIDTH - 200, HEIGHT - 200), (WIDTH // 2, HEIGHT - 300)]  # 增加食物源
NUM_ANTS = 1000
PHEROMONE_DECAY = 0.985
FOOD_CAPACITY = 10000
MAX_SPEED = 2.2


class Ant:
    def __init__(self):
        self.pos = np.array(NEST_POS, dtype=np.float32)
        self.angle = random.uniform(0, 2 * math.pi)
        self.speed = MAX_SPEED * random.uniform(0.8, 1.2)
        self.has_food = False
        self.search_time = 0
        self.pheromone_strength = 1.0

    def sense_environment(self, grid):
        x, y = int(self.pos[0]), int(self.pos[1])
        return grid[
               max(0, x - 1):min(WIDTH, x + 2),
               max(0, y - 1):min(HEIGHT, y + 2)
               ]

    def follow_pheromone(self, sensed, homing=False):
        try:
            if sensed.size == 0:
                self.random_walk()
                return

            if homing:
                weights = sensed
            else:
                weights = 1 / (sensed + 1e-6)  # 避免除零错误

            total = np.sum(weights)
            if total > 0:
                probs = weights.flatten() / total
                choice = np.random.choice(len(probs), p=probs)
                dy, dx = np.unravel_index(choice, sensed.shape)
                target_vec = np.array([dx - 1, dy - 1])  # 转换为方向向量

                if np.linalg.norm(target_vec) > 0:
                    new_angle = math.atan2(target_vec[1], target_vec[0])
                    self.angle = new_angle + random.uniform(-0.1, 0.1)
        except:
            self.random_walk()

    def random_walk(self):
        self.angle += random.uniform(-0.5, 0.5)
        self.speed = MAX_SPEED * random.uniform(0.7, 1.1)

    def move(self, food_grid, pheromone_grid):
        # 环境感知
        sensed = self.sense_environment(pheromone_grid if self.has_food else food_grid)

        # 行为决策
        if self.has_food:
            self.follow_pheromone(sensed, homing=True)
            pheromone_grid[int(self.pos[0]), int(self.pos[1])] += 0.5  # 留下返巢信息素
        else:
            if self.search_time > 150:
                self.random_walk()
            else:
                self.follow_pheromone(sensed)

        # 位置更新
        self.pos += np.array([
            math.cos(self.angle) * self.speed,
            math.sin(self.angle) * self.speed
        ])
        self.pos = np.clip(self.pos, [10, 10], [WIDTH - 10, HEIGHT - 10])

        # 边界反弹
        if self.pos[0] <= 10 or self.pos[0] >= WIDTH - 10:
            self.angle = math.pi - self.angle
        if self.pos[1] <= 10 or self.pos[1] >= HEIGHT - 10:
            self.angle = -self.angle

        self.search_time += 1


class Simulation:
    def __init__(self):
        pygame.init()
        self.screen = pygame.display.set_mode((WIDTH, HEIGHT))
        pygame.display.set_caption("超大蚂蚁觅食模拟")
        self.clock = pygame.time.Clock()

        self.ants = [Ant() for _ in range(NUM_ANTS)]
        self.food_grid = np.zeros((WIDTH, HEIGHT))
        for pos in FOOD_SOURCES:
            self.food_grid[pos[0] - 20:pos[0] + 20, pos[1] - 20:pos[1] + 20] = FOOD_CAPACITY
        self.pheromone_grid = np.zeros((WIDTH, HEIGHT))

    def update_pheromones(self):
        self.pheromone_grid *= PHEROMONE_DECAY
        kernel = np.array([[0.05, 0.1, 0.05],
                           [0.1, 0.4, 0.1],
                           [0.05, 0.1, 0.05]])
        self.pheromone_grid = convolve2d(
            self.pheromone_grid, kernel, mode='same', boundary='symm'
        )

    def draw(self):
        self.screen.fill((25, 25, 40))

        # 绘制信息素
        pheromone_surface = pygame.surfarray.make_surface(
            np.clip(self.pheromone_grid * 50, 0, 255).astype(np.uint8).T
        )
        self.screen.blit(pheromone_surface, (0, 0))

        # 绘制蚂蚁
        for ant in self.ants:
            color = (220, 80, 80) if ant.has_food else (120, 180, 250)
            pygame.draw.circle(self.screen, color, ant.pos.astype(int), 3)

        # 绘制巢穴和食物
        pygame.draw.circle(self.screen, (250, 250, 100), NEST_POS, 20)
        for pos in FOOD_SOURCES:
            pygame.draw.circle(self.screen, (80, 220, 80), pos, 25)

        pygame.display.flip()

    def run(self):
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False

            for ant in self.ants:
                ant.move(self.food_grid, self.pheromone_grid)

                # 食物交互
                x, y = int(ant.pos[0]), int(ant.pos[1])
                if not ant.has_food and self.food_grid[x, y] > 0:
                    ant.has_food = True
                    ant.search_time = 0
                    self.food_grid[x, y] -= 1
                    self.pheromone_grid[x, y] += 1.0  # 留下觅食信息素
                elif ant.has_food and np.linalg.norm(ant.pos - NEST_POS) < 25:
                    ant.has_food = False
                    self.pheromone_grid[x, y] += 3.0

            self.update_pheromones()
            self.draw()
            self.clock.tick(60)

        pygame.quit()


if __name__ == "__main__":
    sim = Simulation()
    sim.run()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值