->Terry<- wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> 
> Ok, I've got my peg game roughed out and I'm having
> problems.
> 
> The new code is at:
> 
> <URL:http://members.socket.net/~tvbare/pypeg/new_pypeg.py>
> 
> I'm confused as to why. The whole OO picture
> has my head reeling, but I thought I had some
> grasp of the basics. Now I'm not so sure. d:^)

Terry,

I can see you're struggling with the OO parts of this program. I'll try to 
help...

Classes group state (instance variables) and behaviour (methods). When 
designing the classes for a program, look for state and behaviour that belong 
together - groups of functions that act on common data.

In your case, I think the fundamental object is a hole. A hole has a location 
and it may or may not contain a peg. Those are it's state. A hole has 
behaviour, in the OO sense, anyway - there are things you want to do with a 
hole. You can draw it, ask it if it has a peg in it, ask it if a mouse click 
falls inside it.

So what would this look like?

class Hole(object):
  # Load peg image. This is a class attribute, not an instance attribute
  pegImage = pygame.image.load('peg.png')

  def __init__(self, location):
    self.location = location
    self.hasPeg = False

  def draw(self, screen):
    ''' A hole knows how to draw itself. '''
    if self.hasPeg:
      screen.blit(Hole.peg, self.location)  # Blit it.

  def isClicked(self, click):
    return self.location[0] <= click[0] <= self.location[0] + 19 \
        and self.location[1] <= click[1] <= self.location[1] + 19


OK, that looks like a pretty handy Hole. 

Notice that this Hole doesn't really correspond very well to what we call a 
hole in the real world. Real holes have locations and they may contain pegs, 
but they don't know how to do anything. That's OK. In the program, any 
functions that use the state of a hole belong in the Hole class.

What else do we need? Well, we need some place to put a bunch of Holes and do 
stuff with the collection, like draw them all and hit test them all. This 
sounds like another class, let's call it Board. The state of a board is just 
the list of Holes it contains. The behaviours of a Board are to draw itself, to 
find which Hole a click falls on (if any), to check for valid moves and to 
perform the moves by changing the state of its Holes. That's a lot, I'll just 
start it:

class Board(object):
  # Load board image
  boardImage = pygame.image.load('board.png').convert_alpha()

  def __init__(self):
    # create a list of Holes
    holeCoords = [[141, 41],
            [114, 91], [164, 91],
            [91, 141], [141, 141], [191, 141],
            [64, 191], [114, 191], [164, 191], [214, 191],
            [41, 241], [91, 241], [141, 241], [191, 241], [241,241]]
    holes = [ Hole(coords) for coord in holeCoords ]

  def draw(self, screen):
    screen.blit(Board.boardImage, (0, 0))        # Blit the board
    for hole in self.holes:
      hole.draw(screen)
    pygame.display.update()             # Refresh display.

See how Board lets the Holes take care of drawing themselves? The Hole is a 
useful abstraction - from the outside we don't have to worry about how it 
works, we can just use it.

continuing with class Board...

  def getClick(self, click):
    ''' Find which Hole was clicked, if any '''
    for hole in self.holes:
      if hole.isClicked(click):
        return hole
    return None

Again, see the division of labor? The Board is just a container, it just works 
with Holes from the outside, it is the Hole that knows whether a click is in it 
or not.
    
Notice how simple and self-contained each method is. This is another hallmark 
of good OO design. The methods that operate on data are in the same class as 
the data. Each class has a simple job to do; working together they get a 
complicated job done.

I hope this helps; obviously there are many more methods to write in Board, and 
you will still have some kind of top-level driver that creates a board and runs 
a game; maybe you will discover that a Game class is useful for creating a 
Board, getting moves and running the game, or maybe a standalone function or 
two will do the job just fine.

Kent

PS I haven't tested any of this!

_______________________________________________
Tutor maillist  -  Tutor@python.org
http://mail.python.org/mailman/listinfo/tutor

Reply via email to