You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python生成无碰撞随机圆时出现'CreaCir'无radio属性错误排查

错误根源

  1. 列表元素类型混乱:Ventana类的figs列表同时混入了CreaCir(圆创建器)和Circulo(圆实例)对象。当CreaCir的update方法遍历figs时,第一个元素是CreaCir实例,调用colisionC方法时,该方法试图访问c2.radio,但CreaCir无此属性,直接触发报错。
  2. 绘制与碰撞检测圆心不匹配:Circulo类绘制圆时用(self.x, self.y)作为圆心,但碰撞检测用self.cx = x+r、self.cy = y+r作为圆心,导致实际绘制位置和碰撞逻辑位置不一致,即使修复类型问题,碰撞检测也会失效。

修复代码

1. 修正Ventana类

将圆创建器与圆实例列表分离,figs仅存储Circulo对象:

class Ventana:
    def __init__(self, Ven_Tam= (700, 500)):
        pg.init()
        self.ven_tam = Ven_Tam
        pg.display.set_caption("Linea")  # 修正原重复赋值self.ven的错误
        self.ven = pg.display.set_mode(self.ven_tam)
        self.ven.fill(pg.Color('#404040'))
        self.figs = []  # 仅存储Circulo实例
        self.creador = CreaCir(self.figs)  # 单独保存圆创建器
        self.reloj = pg.time.Clock()
        
    def check_events(self):
        for event in pg.event.get():
            if event.type == pg.QUIT or (event.type == pg.KEYDOWN and event.key == pg.K_ESCAPE):
                pg.quit()  # 用pg.quit()替代quit(),避免资源泄漏
                exit()
        pg.display.flip()

    def run(self):
        while True:
            self.check_events()
            self.creador.update()  # 仅调用创建器的update方法
            self.ven.fill(pg.Color('#404040'))  # 每次循环重绘背景,清除残留
            for fig in self.figs:
                fig.dibujar(self.ven)
            self.reloj.tick(30)

2. 修正Circulo类

统一绘制和碰撞检测的圆心坐标:

from math import sqrt, pow

class Circulo(PosGeo):
    def __init__(self, x, y, r):
        self.x = x  # 圆的左上角x坐标
        self.y = y  # 圆的左上角y坐标
        self.radio = r
        self.cx = x + r  # 圆心x坐标
        self.cy = y + r  # 圆心y坐标

    def dibujar(self, ventana):
        # 用圆心坐标绘制圆,与碰撞检测逻辑对齐
        pg.draw.circle(ventana, "white", (self.cx, self.cy), self.radio, 1)

    def update(self):
        pass

    def colisionC(self, c2):
        distancia = sqrt(pow(self.cx - c2.cx, 2) + pow(self.cy - c2.cy, 2))
        return self.radio + c2.radio > distancia

3. 调整CreaCir类

优化循环逻辑,确保遍历对象均为Circulo实例:

from random import randint

class CreaCir:
    def __init__(self, figs):
        self.figs = figs
        self.i = 0
        # 创建第一个圆并加入列表
        self.figs.append(self.crear_circulo())
        self.i += 1

    def crear_circulo(self):
        r = randint(5, 104)
        # 确保圆不会超出窗口边界(基于左上角坐标计算)
        x = randint(r, 700 - r)
        y = randint(r, 500 - r)
        return Circulo(x, y, r)

    def update(self):
        if self.i < 100:
            choca = False
            nuevo_circulo = self.crear_circulo()
            # 遍历已存在的所有圆,检查碰撞
            for circulo in self.figs:
                choca = nuevo_circulo.colisionC(circulo)
                if choca:
                    break
            if not choca:
                self.figs.append(nuevo_circulo)
                self.i += 1

    def dibujar(self, ventana):
        pass

额外优化点

  • 修复Ventana类中self.ven = pg.display.set_caption("Linea")的错误,set_caption无返回值,需单独调用。
  • 添加窗口边界检查,避免生成的圆超出可视区域。
  • 用pg.quit()替代quit(),规范退出流程,防止资源泄漏。

内容的提问来源于stack exchange,提问作者Moy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 00:05:27