Jump to content
  • Advertisement
Sign in to follow this  
gsail

Help with a simple python game

This topic is 4859 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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.
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."


[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]

Share this post


Link to post
Share on other sites
Advertisement
Quote:
for some reason sets tiles back to 21 every time
Well, 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.

Share this post


Link to post
Share on other sites
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 player
return 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.player


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.
"""

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()

Share this post


Link to post
Share on other sites
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:


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 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
# 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]

Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!