2011-02-06 63 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