[Tutor] connecting classes

Daniel Yoo dyoo@hkn.EECS.Berkeley.EDU
Sat, 15 Jul 2000 01:47:07 -0700 (PDT)


> A lot of things work already, but I don't understand how I can get one class
> to interact with another (it may be that my classes don't make any sense as
> they're currently designed). Here's an example:
> 
> Python 1.5.2 (#1, May  9 2000, 15:05:56)  [GCC 2.95.3 19991030 (prerelease)]
> on linux-i386
> Copyright 1991-1995 Stichting Mathematisch Centrum, Amsterdam
> >>> import ttt
> >>> game = ttt.Game()
> >>> player1 = ttt.HumanPlayer("Joe", "X")
> >>> player2 = ttt.ComputerPlayer("HAL-9000", "O")
> >>> game.drawBoard()
> 1 2 3
> 4 5 6
> 7 8 9
> >>> player1.chooseMove()
> Where would you like to put your marker?6
> Traceback (innermost last):
>   File "<stdin>", line 1, in ?
>   File "ttt.py", line 47, in chooseMove
>     Game.updateBoard(int(choice), self.marker)
> TypeError: unbound method must be called with class instance 1st argument
> >>>
> 
> Suggestions?


I'll try to look at this from an OOP perspective, so this will be slightly
indirect.

You have two players, 'player1' and 'player2'.  However, which game board
are they playing on?  It's entirely conceivable that you could hold a
whole tournament of tic-tac-toe games, so each player needs to know which
game they're sitting in front of.  That's why saying:

>     Game.updateBoard(int(choice), self.marker)

is ambiguous to the system.  It's doing an updateBoard, but on what
particular game?  That's why the system's complaining about an 'unbound'
method: updateBoard() only works if its associated with a particular Game
instance.

However, you've created a Game instance from the line:

> >>> game = ttt.Game()

so, 'game' must be involved.  You'll probably need to pass off 'game' to
the player initializer, so that each player knows where to sit down and
start playing.


This becomes more clear if you can imagine the situation:

### setting up the game
  game1 = ttt.Game()
  game2 = ttt.Game()

  player1 = ttt.HumanPlayer("Joe", "X")
  player2 = ttt.HumanPlayer("Jill", "O")
  player3 = ttt.ComputerPlayer("Deep Thought", "X")
  player4 = ttt.ComputerPlayer("HAL-9000", "O")

  player1.sitAt(game1)
  player2.sitAt(game1)
  player3.sitAt(game2)
  player4.sitAt(game2)
  ...

or something like that, where we can define sitAt() as:

  def sitAt(self, g):
    self.game = g

and slightly change your chooseMove to use the self.game instance instead
of the Game class.  It would look something like:

   self.game.updateBoard(...)

Setting up self.game inside __init__ might be better than having an
explicit sitAt().  I just like imagining them sitting down imposingly like
Gary Kasparov.  *grin* If this reply is ambigous, it's probably because
I'm too drowsy to see the keyboard. In any case, email tutor@python.org
again if this is unclear --- I should be more awake by then.  Good luck!