2013-05-03 54 views
0

删除所以我有一个球类,看起来像这样:如何检查是否在列表中球碰撞,并从列表

class Ball(object): 
    def __init__(self,n,x0,y0,dx,dy,r,c): 
     self.xc = x0 
     self.yc = y0 
     self.dx = dx 
     self.dy = dy 
     self.radius = r 
     self.area = math.pi*((r)**2) 
     self.color = c 
     self.name = n 
    def position(self): 
     return (self.xc,self.yc) 
    def move(self): 
     self.xc+=self.dx 
     self.yc+=self.dy 
    def collide(self,o,new_name): 
     x = ((self.area*self.xc)+(o.area*o.xc))/(self.area+o.area) 
     y = ((self.area*self.yc)+(o.area*o.yc))/(self.area+o.area) 
     dx = ((self.area*self.dx)+(o.area*o.dx))/(self.area+o.area) 
     dy = ((self.area*self.dy)+(o.area*o.dy))/(self.area+o.area) 
     if self.area >= o.area: 
      c = self.color 
     else: 
      c = o.color 
     area = (self.area+o.area) 
     r = math.sqrt(area/(math.pi)) 
     return Ball(new_name,x,y,dx,dy,r,c) 
    def does_collide(self,o): 
     if math.hypot((self.xc-o.xc),(self.yc-o.yc))<=(self.radius+o.radius): 
      return True 
     else: 
      return False 

而且我跑在我的主要代码while循环来模拟不同的球,每个球每次迭代移动其dx和dy值。为了做到这一点,我有一个名为球的列表,它包含我所有的球对象。它看起来是这样的:

balls=[ball1,ball2,ball3,ball4...] and so forth 

我想要做的就是使用does_collide功能在我的球类检查两个球发生碰撞,如果他们这样做我想从列表中删除和插入两个球列表中由碰撞函数创建的新球。碰撞函数创建一个新球,其x,y,dx和dy值是两个球的加权平均值,其颜色是最大球的颜色。

因此,对于列表中的所有球,如何使用函数does_collide主动检查是否有任何两个球碰撞并将它们从列表中删除?我还想将新球添加到列表中,这是碰撞函数的结果。

我试图做这样的事情:

  for ball1 in balls: 
      for ball2 in balls: 
       if ball1.name!=ball2.name: 
        if ball1.does_collide(ball2) == True: 
         ball = ball1.collide(ball2,(int(N)+1)) 
         balls.append(ball) 
         balls.remove(ball1) 
         balls.remove(ball2) 

但只是似乎很混乱和崩溃的每一个碰撞发生时。

+2

'itertools.combinations'可以产生2元组来比较并保存一些嵌套循环。 – 2013-05-04 00:10:56

+1

您正在修改您正在迭代的列表,这绝不是一个好主意。 – martineau 2013-05-04 00:15:39

+0

请注意:尽量快速阅读[Zen of Python](http://python.net/~goodger/projects/pycon/2007/idiomatic/handout.html#the-zen-of-python-1) ,这是制作干净和Pythonic代码的绝妙指南。我不知道你是否来自Lisp-y语言,但是,你使用了很多不必要的括号!:) – whatyouhide 2013-05-04 00:16:42

回答

3

您是否在意订购?如果没有,这是你可以做到的一种方式。

import itertools 

newballs = [] 
removed = set() 
for b1, b2 in itertools.combinations(balls, 2): 
    if b1 not in removed and b2 not in removed: 
     if b1.does_collide(b2): 
      removed.add(b1) 
      removed.add(b2) 
      newballs.append(b1.collide(b2)) 

balls = [b for b in balls if b not in removed] + newballs 
0

我们在整个列表中选择外循环运行,但让你内环仅从当前外环球+ 1运行到列表的末尾。显然,如果球5(例如)与球8碰撞(例如),则球8与球5碰撞,所以你不必检查两者。

另外,您正在从列表中删除项目,同时您正在迭代列表。这不可能是安全的。除了在循环中进行删除之外,我只需在循环中设置标志,指​​示哪些球应该被删除,然后在另一个循环中删除它们。

+0

个人而言,我发现它更简单,更清晰,只是迭代数组的副本。它还节省了一些簿记。 – azgult 2013-05-04 00:14:22