These answers are fantastic, but seem to be focusing on one side of your question. I'm going to focus on object orientation.
I reviewed your code with a couple basic concepts in mind, namely polymorphism and encapsulation.
Polymorphism
Where are your objects? A rock, paper, and scissors could all be objects, could they not? And, most importantly, they are all the same kind of object. They are all "pieces" of the game.
Here's a pseudo-example:
class Rock inherits from Element
type = 'rock'
def compare(Element)
if type == 'paper'
return 'LOSE'
elsif type == 'scissors'
return 'WIN'
else
return 'TIE'
Although this is a potential solution, my example is going to go in a different direction simply for the fact that if you wanted to add more elements then you'd have to touch the existing code (re: Chris' example of RPSLS).
Encapsulation
A great programming muscle to exercise is encapsulation. The two main areas, in this example, are to hide the user interface from the game code.
The user interface shouldn't care about the inner-workings of the game. The game shouldn't care how it's displayed. What if you wanted to change the interface to something more graphical? Right now, your code relies on the console to know about the pieces of the game and how it works.
Example
So, let's return to Chris' example again. The elements of this game are something that may change quite often. How can you handle this to make future programming easier?
One solution is to store the "data" of the game elsewhere and dynamically create objects.
The following is Python code to materialize the ideas I've written about here.
Here's code for an abstracted piece of the game, an element:
# The goal for an element is to just know when it wins, when it loses, and how to figure that out.
class Element:
_name = ""
_wins = {}
_loses = {}
def get_name(self):
return self._name
def add_win(self, losingElementName, action):
self._wins[losingElementName] = action
def add_loss(self, winningElementName, action):
self._loses[winningElementName] = action
def compare(self, element):
if element.get_name() in self._wins.keys():
return self._name + " " + self._wins[element.get_name()] + " " + element.get_name()
elif element.get_name() in self._loses.keys():
return None
else:
return "Tie"
def __init__(self, name):
self._name = name
self._wins = {}
self._loses = {}
Games have players:
# The player's only responsibility is to make a selection from a given set. Whether it be computer or human.
class Player:
_type = ''
_selection = ''
def make_selection(self, arrayOfOptions):
index = -1
if (self._type == 'Computer'):
index = random.randint(0, len(arrayOfOptions) - 1)
else:
index = int(raw_input('Enter the number of your selection: ')) - 1
self._selection = arrayOfOptions[index]
return self._type + ' selected ' + self._selection + '.'
def get_selection(self):
return self._selection
def __init__(self, playerType):
self._type = playerType
self._selection = ''
Game code:
# A game should have players, game pieces, and know what to do with them.
class PlayGame:
_player1 = Player('Human')
_player2 = Player('Computer')
_elements = {}
def print_result(self, element1, element2):
val = element1.compare(element2)
if (val != None):
print "YOU WIN! (" + val + ")" # win or tie
else:
print "You lose. (" + element2.compare(element1) + ")"
def fire_when_ready(self):
counter = 1
for e in self._elements.keys():
print str(counter) + ". " + e
counter = counter + 1
print ""
print "Shoot!"
print ""
print self._player1.make_selection(self._elements.keys())
print self._player2.make_selection(self._elements.keys())
element1 = self._elements[self._player1.get_selection()]
element2 = self._elements[self._player2.get_selection()]
self.print_result(element1, element2)
def load_element(self, elementName1, action, elementName2):
winningElementObject = None
newElementObject = None
if (elementName1 in self._elements):
winningElementObject = self._elements[elementName1]
winningElementObject.add_win(elementName2, action)
else:
newElementObject = Element(elementName1)
newElementObject.add_win(elementName2, action)
self._elements[elementName1] = newElementObject
if (elementName2 in self._elements):
losingElementObject = self._elements[elementName2]
losingElementObject.add_loss(elementName1, action)
else:
newElementObject = Element(elementName2)
newElementObject.add_loss(elementName1, action)
self._elements[elementName2] = newElementObject
def __init__(self, filepath):
# get elements from data storage
f = open(filepath)
for line in f:
data = line.split(' ')
self.load_element(data[0], data[1], data[2].replace('\n', ''))
The console code, the user interface:
if __name__ == "__main__":
print "Welcome"
game = PlayGame('data.txt')
print ""
print "Get ready!"
print ""
game.fire_when_ready()
And the data file, data.txt:
scissors cut paper
paper covers rock
rock crushes lizard
lizard poisons spock
spock smashes scissors
scissors decapitates lizard
lizard eats paper
paper disproves spock
spock vaporizes rock
rock crushes scissors
The goal for my answer was to show you how you can use some object oriented concepts in solving your problem. In doing so I also left some unresolved problems. One big one is that the player and game objects are still coupled to the user interface. One way to nicely resolve this would be through the use of delegates.