2013-05-03 23 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