Let me start by saying that your code is
pretty
much OK as is. Indeed even using clssses
for an
RPS game is probably overkill to some
extent.
What follows should be seen more as some
ideas
for experimentation and building towards a
more
flexible/expandable architecture for future
projects. Its really about introducing some
alternative approaches and increasing
consistency.
It is definitely not "better" - and indeed
could
definitely be improved in several
ways.
> class Human:
> def __init__(self):
> self.points = 0
> self.choice = " "
>
> def plays(self):
> fromUser = raw_input("Pick (R)ock, (P)aper, or
> (S)cissors! ")
> translate = {'r':'rock', 's':'scissors',
> 'p':'paper'}
> try:
> self.choice = translate[fromUser.lower()]
> except KeyError:
> print 'Invalid Response'
>
> class Computer:
> def __init__(self):
> self.points = 0
> self.choice = " "
>
> def plays(self):
> comp_choice = random.randint(0,2)
> if comp_choice == 0:
> self.choice = 'rock'
> elif comp_choice == 1:
> self.choice = 'paper'
> else:
> self.choice = 'scissors'
> def __init__(self):
> self.points = 0
> self.choice = " "
>
> def plays(self):
> fromUser = raw_input("Pick (R)ock, (P)aper, or
> (S)cissors! ")
> translate = {'r':'rock', 's':'scissors',
> 'p':'paper'}
> try:
> self.choice = translate[fromUser.lower()]
> except KeyError:
> print 'Invalid Response'
>
> class Computer:
> def __init__(self):
> self.points = 0
> self.choice = " "
>
> def plays(self):
> comp_choice = random.randint(0,2)
> if comp_choice == 0:
> self.choice = 'rock'
> elif comp_choice == 1:
> self.choice = 'paper'
> else:
> self.choice = 'scissors'
While its of little real advantage for
this program
I'd be tempted to introduce a Player
superclass to avoid
code duplication. The protocol of both classes
here is the same and they both pass the
"is-a"
test for inheritance - ie. they are both
Players.
class Player:
def
__init__(self):
self.points =
0
self.choice = " "
self.choice = " "
def getChoice(self):
pass # implemented in subclass
def plays(self):
choice =
self.getChoice()
if choice == 0:
self.choice = 'rock'
elif choice == 1:
self.choice = 'paper'
else:
self.choice = 'scissors'
if choice == 0:
self.choice = 'rock'
elif choice == 1:
self.choice = 'paper'
else:
self.choice = 'scissors'
Notice I put the plays function in the
Player class.
By unifying the representation of choice we
can use
that function for both and just implement a
relatively simple getChoice method in each
subclass
and we are done... (In fact we could
simplify still
further by storing the choice in its
numeric form
and using a class level dictionary to
translate
that to a string for printing - although in
fact
you never print what the choices were -
maybe you
should?)
class Human(Player):
def
getChoice(self):
choice =
raw_input('Choice - rps: ').lower()
if choice in
'rps':
return
{'r':0,'p':1,'s':2}[choice]
else: raise
ValueError
class Computer(Player):
def
getChoice(self):
return
randrange(0,3)
>
> def compare_objects(human, computer):
> print "Human picked ", human.choice
> print "Computer picked", computer.choice
> results = { 'rock' : {'rock' : 'draw', 'paper': 0,
> 'scissors': 1},
> 'paper' : {'rock' : 1, 'paper': 'draw', 'scissors':
> 0},
> 'scissors' : {'rock' : 0, 'paper' : 1, 'scissors' :
> 'draw'}
> }
>
> outcome = results[human.choice][computer.choice]
> if outcome == 0:
> print "Computer Wins!"
> computer.points = computer.points + 1
> elif outcome == 1:
> print "Human Wins!"
> human.points = human.points + 1
> else:
> print "Draw!"
> def compare_objects(human, computer):
> print "Human picked ", human.choice
> print "Computer picked", computer.choice
> results = { 'rock' : {'rock' : 'draw', 'paper': 0,
> 'scissors': 1},
> 'paper' : {'rock' : 1, 'paper': 'draw', 'scissors':
> 0},
> 'scissors' : {'rock' : 0, 'paper' : 1, 'scissors' :
> 'draw'}
> }
>
> outcome = results[human.choice][computer.choice]
> if outcome == 0:
> print "Computer Wins!"
> computer.points = computer.points + 1
> elif outcome == 1:
> print "Human Wins!"
> human.points = human.points + 1
> else:
> print "Draw!"
By using the number format of storage and
the
dictionary in the class you can simplify
that
as in show below using
lists.
> I actually figured out how to build the 2x2 matrix.
> I'm quite proud of this.
> I actually figured out how to build the 2x2 matrix.
> I'm quite proud of this.
A nested dictionary is one way. Another is
to use numbers
to represent the choices and outcomes and
create a nested
list structure nested list
rps =
{0:'Rock',1:'Paper',2:'Scissors'}
draw,loss,win = 0,1,2
outcomes = [ [0,1,2], [2,0,1], [1,2,0]
]
computer = randrange(0,3)
human = randrange(0,3)
result = outcomes[computer][human]
if result == draw: print
'Draw'
elif result == loss: print 'Computer lost
with', rps[computer]
elif result == win: print 'Computer won
with', rps[computer]
The dictionary is more verbose but does
have more readable
code.
I hope somebody finds at least some of that
interesting! :-)
I guess what I'm really trying to show is
how
choosing different data structures makes a
big
difference to how the code
looks.
Alan G.
_______________________________________________ Tutor maillist - Tutor@python.org http://mail.python.org/mailman/listinfo/tutor