print """There are 21 tiles. One of them is the poison tile. The first player will draw 1, 2, or 3 tiles.
The second player will then do the same. This will continue until there is one tile left.
The person whose turn it is when this occurs will be poisoned. They will also lose."""
# allows playing more than one game
play_again = "y"
while play_again is "y":
tiles = 21
# keep track of which player it is
player = 1
def turn(tiles,player):
print ""
print "Player", player, "'s turn:"
take = input("How many tiles would you like to take? ")
if take == 1 or 2 or 3:
tiles = tiles - take
if tiles == 1:
print "Congratulations, player", player, "you won!"
valid = 2
elif tiles < 1:
print "Either there aren't that many tiles left, or you don't need to take the last tile."
else:
if player == 1:
player = player + 1
else:
player = player - 1
print "There are now", tiles, "tiles left."
return player
return tiles
else:
print "You must take either 1, 2, or 3 tiles. Try again."
# make sure take is valid
valid = 1
while valid == 1:
turn(tiles,player)
play_again = raw_input("Would you like to play another game? (y/n): ")
print ""
print "Pressing Control (Ctrl), Z will close the program."
Help with a simple python game
The game is called poison. The idea is that there are 21 tiles, and players take turns drawing 1, 2, or 3 tiles until there is only one left. The person who draws that last tile loses. Naturally the strategy is to go second, and always make sure the total number of tiles drwn is a multiple of 4. (So if your opponent draws 3, you draw 1, they draw 2, you draw 2, etc.) But that doesn't really matter. Here is my source code which seems to be on the brink of completion, I just have semi-minor bugs that need fixing.
EDIT: Oh dear, it seems to have removed my tabs. It shows them here in the edit post screen. If someone figures out how to fix this please respond. Right now I need to go to bed.
[Edit: Use the [source lang="cpp"] tag with the lang="python" attribute. - Oluseyi]
The problems I have identified are:
The obvious one, is for some reason sets tiles back to 21 every time.
Also, if you enter a number other than 1, 2, or 3, it doesn't tell you that it isn't allowed. I wanted that to get caught in the 'if take == 1 or 2 or 3' bit, but it didn't and I don't know why.
After this I plan to make some sort of AI for it, and eventually make a graphical version for it, but for now I just need help with this. Also, if there is a better way to approach this, that would be nice too. It seems a little longish for such a simple game, and this is a learning experience after all.
Thank you,
-Gavin Bauer
[Edited by - Oluseyi on April 24, 2005 9:22:54 PM]
Quote:for some reason sets tiles back to 21 every timeWell, your structure is borked. You're defining your function within the while loop body, which means it gets recreated - along with all the variable initializations. That's why tiles gets set back to 21 each time.
def turn(tiles, player): ...def main(): player = 1 play_again = "y" tiles = 21 while play_again="y" ...if __name__ is '__main__': main()
Scoping is critical.
Quote:Also, if you enter a number other than 1, 2, or 3, it doesn't tell you that it isn't allowed. I wanted that to get caught in the 'if take == 1 or 2 or 3' bit, but it didn't and I don't know why.if take == 1 or 2 or 3 doesn't do what you think it does. Integer values (among others) can be evaluated in a Boolean context: non-zero values are True. That means your statement evaluates as the following:
if take == 1 or True or True
Clearly, that's not what you want. What you want is:
if take == 1 or take == 2 or take == 3.
Quote:The obvious one, is for some reason sets tiles back to 21 every time.
Python integers are immutable. Changing them creates a new variable, it does not modify the old value. So essentially, they cannot be passed reference.
That problem also exists with the player variable and the valid variable.
Solution: either modify them as a global variable (see the global keyword), a member variable, or return the player from the function.
return playerreturn tiles
And one return is actually enough (return isn't like yield)
Quote:Also, if you enter a number other than 1, 2, or 3, it doesn't tell you that it isn't allowed. I wanted that to get caught in the 'if take == 1 or 2 or 3' bit, but it didn't and I don't know why.
if take == 1 or 2 or 3:
Is interpreted as if (take==1) or 2 or 3, which will be True if take==1 and 2 (which is also "true"), otherwise.
You really want if 1 <= take <= 3 or if take in (1,2,3).
def turn(tiles,player): print "Player %s's turn:" % player print "There are %s tiles left.\n" % tiles take = raw_input("How many tiles would you like to take? ") try: take = int(take) except: take = None print if take not in (1,2,3): print "You must take either 1, 2, or 3 tiles. Try again.\n" return (tiles, player, True) if take > tiles: print "There aren't that many tiles left.\n" return (tiles, player, True) if take == tiles: print "you don't need to take the last tile.\n" return (tiles, player, True) tiles -= take if tiles == 1: print "There is only one tile left." print "Congratulations, player %s you won!\n" % player return (None, None, False) return (tiles, 3-player, True) def main(): print """There are 21 tiles. One of them is the poison tile. The first player will draw 1, 2, or 3 tiles. The second player will then do the same. This will continue until there is one tile left. The person whose turn it is when this occurs will be poisoned. They will also lose. """ # allows playing more than one game play_again = "y" while play_again is "y": tiles, player, running = 21, 1, True while running: tiles, player, running = turn(tiles, player) play_again = raw_input("Would you like to play another game? (y/n): ") print "Game over."if __name__ == "__main__": main()
Or, using a Game class.
class Game(object): def __init__(self): self.player = 1 self.tiles = 21 self.running = None def run(self): self.running = True while self.running: self.turn() def turn(self): print "Player %s's turn:" % self.player print "There are %s tiles left.\n" % self.tiles take = raw_input("How many tiles would you like to take? ") try: take = int(take) except: take = None print if take not in (1,2,3): print "You must take either 1, 2, or 3 tiles. Try again.\n" elif take > self.tiles: print "There aren't that many tiles left.\n" elif take == self.tiles: print "You don't need to take the last tile.\n" elif take == self.tiles-1: print "There is only one tile left." print "Congratulations, player %s you won!\n" % self.player self.running = False else: self.tiles -= take self.player = 3-self.playerdef main(): print """There are 21 tiles. One of them is the poison tile. The first player will draw 1, 2, or 3 tiles. The second player will then do the same. This will continue until there is one tile left. The person whose turn it is when this occurs will be poisoned. They will also lose. """ play_again = "y" while play_again is "y": game = Game() game.run() play_again = raw_input("Would you like to play another game? (y/n): ") print "Game over." if __name__ == "__main__": main()
I haven't looked at this thread all week, I've been busy. I got help from a guy on the python tutoring service, who helped me considerably. Before I'd even looked at any of the posts on this forum, I had this:
By the way, Fruny's 'if 1 <= take <= 3' doesn't work because that would allow someone to take, say, 1.5 tiles, which is not allowed. Other than that, excellent advise, I'm still quite new to python and programming in general, so I recognise now that my original code was quite scrambled.
[Edited by - gsail on April 28, 2005 4:35:14 PM]
def turn(tiles,player): print "" print "Player", player, "'s turn:" take = input("How many tiles would you like to take? ") if take in (1,2,3): tiles = tiles - take if tiles == 1: print "Congratulations, player", player, "you won!" valid = 2 elif tiles == 0: print "Suicide is a crime!" elif tiles < 0: print "You can't take more tiles than are left!" else: player = (player % 2) + 1 print "There are now", tiles, "tiles left." else: print "You must take either 1, 2, or 3 tiles. Try again." return (tiles, player)print '''There are 21 tiles. One of them is the poison tile. The first player will draw1, 2, or 3 tiles. The second player will then do the same. This will continueuntil there is one tile left. The person whose turn it is when this occurs willbe poisoned. They will also lose.'''# allows playing more than one gameplay_again = "y"while play_again is "y": tiles = 21 # keep track of which player it is player = 1 # make sure take is valid valid = 1 while valid == 1: tiles, player = turn(tiles,player) play_again = raw_input("Would you like to play another game? (y/n): ")print ""print "Pressing Control (Ctrl), Z will close the program."
By the way, Fruny's 'if 1 <= take <= 3' doesn't work because that would allow someone to take, say, 1.5 tiles, which is not allowed. Other than that, excellent advise, I'm still quite new to python and programming in general, so I recognise now that my original code was quite scrambled.
[Edited by - gsail on April 28, 2005 4:35:14 PM]
Quote:By the way, Fruny's 'if 1 <= take <= 3' doesn't work because that would allow someone to take, say, 1.5 tiles, which is not allowed.
Ah, but note how I converted the input string to an int. [smile] The problem with input as opposed to raw_input is that you could type, say, file("helloworld","w") and it would accept it, creating a file on your disk. Then in the next input you could write to it, etc...
Looking good. You'll probably want to fix it so that it will check the amount of remaining tiles before taking away from them, so that you don't leave the game in an invalid state after the turn() function. Oh, and take Fruny's advice seriously about input() vs raw_input() - the former is really intended for developing tools or interpreter shells etc., not games.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement