2011-02-06 89 views
1

以下是我正在嘗試在python中執行的一個簡化示例(使用pygame,但可能不相關)。Python類/實例/對象組織問題

我有8×8像素的JPG文件的列表,每個描繪了一個英文字母:

[a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z]

我想安排的這些4x4的方格,在我想要的任何圖案,作爲一個更大的32×32照片:

gmmg 
gppg 
gppg 
gmmg 

但是,該模式只是一個動畫的單幀。 例如,我可能希望4動畫幀,其中b的和n的閃光燈側以交替地側,同時西南一個f移動:

bbnf nnbb bbnn nnbb 
bbnn nnfb bbnn nnbb 
bbnn nnbb bfnn nnbb 
bbnn nnbb bbnn fnbb 

我想對在各幀中的每個正方形的字母值控制以使任何動畫,所以我想基本上有64個單獨的變量(對於如上所示的4幀動畫)。每個正方形還有一個[x,y]列表位置變量和rbg顏色。

我的問題是如何組織這一切與類(我試圖學習OOP)。從邏輯上看,每個框架似乎都包含正方形,每個正方形包含位置,字母和顏色等變量。但我想你甚至可以把它想成每個方塊'包含'4幀...我猜測是製作一個幀類,並把它的4個實例放在一個列表中(如果有4幀),並以某種方式使每個幀實例包含16個方形實例的列表。也許可以使用像frames[2].squares[5].letter = f(只是一個模糊的想法;我太OOP新來知道這是遠程正確還是一個好主意)。但是,瞭解一個知道自己在做什麼的人會組織這些會很有幫助。 謝謝!

+1

快速提示,對於4x4網格,使用列表列表。所以你可以做正方形[3] [0],而不是正方形[8]。 – 2011-02-06 17:42:58

回答

1

由於一個幀的大小是固定的,並且幀的數量不是,所以製作一個class Frame看起來是一個很好的首選。每個Frame將包含成員grid,其可以是包含四個字母的四個列表的列表。由於字符串是不可變的,因此四個字符串的列表將不起作用,儘管它是單個16個字符的字符串可能會更好。你必須確定個人資料。對於這個答案,我會假設你正在製作一系列角色列表。

然後製作一個class Animation,它有一個frames成員,它是一個框架列表。然後,您將編寫如下代碼:

myAnimation.frames[10].grid[2][3] = 'f' 

如果需要,我可以提供更多詳細信息。

例:(沒有測試還沒有,但它應該是關閉文檔註釋應該有希望與doctest工作。)

import string 

class Frame(object): 
    """This is a single frame in an animation.""" 
    def __init__(self, fill=None, color=None): 
     """Initializes the frame. 

     >>> f = Frame() 
     >>> f.print() 
     aaaa 
     aaaa 
     aaaa 
     aaaa 
     >>> g = Frame(fill='c', color=(0, 255, 0)) 
     >>> g.print() 
     cccc 
     cccc 
     cccc 
     cccc 
     """ 
     if fill is None: 
      fill = 'a' # Or whatever default you want 
     self.letterGrid = [] 
     for row in range(4): 
      self.letterGrid.append([fill for col in range(4)]) 

     if color is None: 
      color = (0, 0, 0) 
     self.colorGrid = [] 
     for row in range(4): 
      self.letterGrid.append([fill for col in range(4)]) 

    def set_grid(self, row, col, letter=None, color=None): 
     """Sets the letter and/or color at the given grid. 

     >>> f.set_grid(1, 1, 'b', (255, 0, 0)) 
     >>> f.print() 
     aaaa 
     abaa 
     aaaa 
     aaaa 
     >>> f.set_grid(1, 3, letter='x') 
     >>> f.print() 
     aaaa 
     abax 
     aaaa 
     aaaa 
     >>> f.set_grid(3, 3, color=(255, 0, 0)) 
     """ 
     if letter is not None: 
      self.letterGrid[row][col] = letter 
     if color is not None: 
      self.colorGrid[row][col] = color 

    def position(row, col): 
     return (row * 16, col * 16) 

    def print(self): 
     """Simple routine to print a frame as text.""" 
     for row in self.letterGrid: 
      print(''.join(row)) 

class Animation(object): 
    def __init__(self, frames=None): 
     """Initializes an animation.""" 
     self.frames = frames or [] 

希望這可以讓你開始。

+0

我的願望:)我在下面的框架類發佈我的嘗試。不確定是否它的好,看到你的僞代碼或什麼可能會幫助我比使用谷歌搜索快得多,如果你可以打擾。 – cheeser 2011-02-06 20:33:54

0

另一種方法是創建一個由字典,列表,集合等組成的合適的通用數據結構,然後編寫庫方法來處理這些數據。這聽起來不是很經典的OOP,但它不是,但我發現這種方式更容易處理,並且更容易「正確」。您一方面可以明確地分離構建數據容器的兩個問題,另一方面定義適當的數據操作代碼。

如前面的海報建議,動畫可以建模爲一個幀列表;然後每個幀包含32個列表,每個列表包含32個元素,或者8個列表包含8個元素,每個元素再次模擬上面顯示的4x4網格。當然,是否事先預先計算(或簡單定義)每個幀,或者您是否在動畫期間操作單個幀的「實時」數據取決於進一步考慮。

+0

我過去幾乎只使用列表,但我正在努力學習OOP,看看我是否可以更好地組織東西,並使其成爲人類可以理解的東西。列表通常可以工作,但花了很長時間來思考,我的控制能力僅限於低複雜度。我可能做錯了,但我通常會得到非常複雜的嵌套列表,這些列表會混淆循環,而像myList [3] [5] [8]這樣的數字或者某些東西不是人類可讀的。 – cheeser 2011-02-06 20:45:57

0

@Mike (以上回復僅限600個字符,所以我想我會在這裏顯示我的回覆) 這是我迄今爲止在Frame類中的嘗試。我不知道是否應該在另一個類中定義一個類,或者是否或如何將實例列表發送到Animation類或其他類。每個正方形可以有一個獨特的字母,位置和顏色(位置,因爲我打算讓列或行在位置上可移動)。所以這就是爲什麼我把3種網格放在那裏(不知道這是個好主意,還是個別方格應該有自己的課堂或其他東西)。

class Frame(object): 
    def __init__(self, letterGrid, positionGrid, colorGrid): 
     self.letterGrid = letterGrid 
     self.positionGrid = positionGrid 
     self.colorGrid = colorGrid 

class Animation(object): 
    def __init__(self, frames): 
     self.frames = frames 

frames = [] 
frames.append(Frame([ 
        ['b','b','n','f'], 
        ['b','b','n','n'], 
        ['b','b','n','n'], 
        ['b','b','n','n'] ], 

        [ 
        [[0,0],[16,0],[32,0],[48,0]], 
        [[0,16],[16,16],[32,16],[48,16]], 
        [[0,32],[16,32],[32,32],[48,32]], 
        [[0,48],[16,48],[32,48],[48,48]] ], 

        [ 
        [[0,0,255],[0,0,0],[0,0,0],[0,0,0]], 
        [[0,0,255],[0,0,0],[0,0,0],[0,0,0]], 
        [[0,0,255],[0,0,0],[0,0,0],[0,0,0]], 
        [[0,0,255],[0,0,0],[0,0,0],[0,0,0]] ] 
        )) 

frames.append(Frame([ 
        ['n','n','b','b'], 
        ['n','n','f','b'], 
        ['n','n','b','b'], 
        ['n','n','b','b'] ], 

        [ 
        [[0,0],[16,0],[32,0],[48,0]], 
        [[0,16],[16,16],[32,16],[48,16]], 
        [[0,32],[16,32],[32,32],[48,32]], 
        [[0,48],[16,48],[32,48],[48,48]] ], 

        [ 
        [[0,0,0],[0,0,255],[0,0,0],[0,0,0]], 
        [[0,0,0],[0,0,255],[0,0,0],[0,0,0]], 
        [[0,0,0],[0,0,255],[0,0,0],[0,0,0]], 
        [[0,0,0],[0,0,255],[0,0,0],[0,0,0]] ] 
        )) 

frames.append(Frame([ 
        ['b','b','n','n'], 
        ['b','b','n','n'], 
        ['b','f','n','n'], 
        ['b','b','n','n'] ], 

        [ 
        [[0,0],[16,0],[32,0],[48,0]], 
        [[0,16],[16,16],[32,16],[48,16]], 
        [[0,32],[16,32],[32,32],[48,32]], 
        [[0,48],[16,48],[32,48],[48,48]] ], 

        [ 
        [[0,0,0],[0,0,0],[0,0,255],[0,0,0]], 
        [[0,0,0],[0,0,0],[0,0,255],[0,0,0]], 
        [[0,0,0],[0,0,0],[0,0,255],[0,0,0]], 
        [[0,0,0],[0,0,0],[0,0,255],[0,0,0]] ] 
        )) 

frames.append(Frame([ 
        ['n','n','b','b'], 
        ['n','n','b','b'], 
        ['n','n','b','b'], 
        ['n','n','b','b'] ], 

        [ 
        [[0,0],[16,0],[32,0],[48,0]], 
        [[0,16],[16,16],[32,16],[48,16]], 
        [[0,32],[16,32],[32,32],[48,32]], 
        [[0,48],[16,48],[32,48],[48,48]] ], 

        [ 
        [[0,0,0],[0,0,0],[0,0,0],[0,0,255]], 
        [[0,0,0],[0,0,0],[0,0,0],[0,0,255]], 
        [[0,0,0],[0,0,0],[0,0,0],[0,0,255]], 
        [[0,0,0],[0,0,0],[0,0,0],[0,0,255]] ] 
        )) 

print "3rd frame's colorGrid:\n", frames[2].colorGrid 
+0

你不需要`positionGrid`;它是不變的,可以根據需要進行計算,對吧?所以只需要一個方法`def position(row,col):return(row * 16,col * 16)` – 2011-02-06 21:50:46