Python Forum
Noob programmer - game of Nim help
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Noob programmer - game of Nim help
#1
Hi, I'm a complete noob to Python so please be nice! Pray

I am writing a game of nim program and I've come across an issue where I've managed to get the game to work against a computer. However I get the following errors:

If you empty pile 2, the game decides the player 2 as the winner without clearing pile 1 and vice versa if you clear pile 1.

I've entered the entirety of my code below, or if preferable, I've attached a zip file of my code.
.zip   GameOfNim Computer.zip (Size: 1.5 KB / Downloads: 66) , it contains a 1 v computer game and a 2 human player game.

Appreciate the assistance on this!

Thanks
Daz

------------------------------------------------------------------

#game of nim Part
#set the initial state
import random
def main():
    
    randPile = random.randint(2, 5)
    player = player1
    print(randPile)
    
#post: play again question
def playAgain():
   
    playAgainAnswer = input("Would you like to play again? type 'yes' to play again or anything else to quit: ")
    playAgainAnswer = playAgainAnswer.capitalize()
    if playAgainAnswer == "Yes":
        playGame()

    else:
            
        print("Thank you for playing, goodbye")
        
#If playing against computer
        
def playAgainstComputer():
    
    print("-" * 25)
    print("PLAYER VS COMPUTER")
    print("-" * 25)
    
    player1 = input("Enter player 1 name: ")
    computer = "Computer"

    pile1 = random.randint(2, 10)
    pile2 = random.randint(2, 10)

    print("-" * 25)
    print(" Token pile 1:", pile1 * "O")
    print(" Token pile 2:", pile2 * "O")
    print("-" * 25)
    
    currentPlayer = player1  
    while pile1 > 0 and pile2 > 0:
        
#Stating player turn and which pile to remove from

        print("-" * 25)
        print(currentPlayer.upper(), "TURN")
        print("-" * 25)

        if currentPlayer == computer:

#Computers Turn

            computerChoosesPile = random.randint(1, 2)

                
            print("Computer chooses token pile:", computerChoosesPile)
            computerRemoveTokens = random.randint(1, 4)
            print("Computer removes", computerRemoveTokens * "O", "token(s)")
            
            if computerChoosesPile == 1:
                pile1 = pile1 - computerRemoveTokens
                print("Pile 1 now has ", pile1 * "O", " token(s) left")
            else:
                pile2 = pile2 - computerRemoveTokens
                print( "Pile 2 now has ", pile2 * "O", " token(s) left")
        else:
            while True:    
                pileChoice = int(input(currentPlayer + " which pile do you want to take tokens from, pile 1 or pile 2? "))

#remove Tokens from pile choice from player 1
        
                if pileChoice == 1:
                    while True:
                        removeTokens = int(input("How many tokens to remove? "))
                        if removeTokens <= 0 or removeTokens > pile1:
                            print("That's an invalid number, try again")
                        
                        else:
                        
                            pile1 = pile1 - removeTokens
                            print("Pile 1 now has ", pile1 * "O", " token(s) left")
         
                            break       
#remove Tokens from pile choice from computer
                        
                elif pileChoice == 2:
                    while True:
                        removeTokens = int(input("How many tokens to remove? "))
                        if removeTokens <= 0 or removeTokens > pile2:
                            print("That's an invalid number, try again")
                        
                        else:
                        
                            pile2 = pile2 - removeTokens
                            print("Pile 2 now has ", pile2 * "O", " token(s) left")
         
                            break 
                                           
                   
                else:
                    print("error, please choose only 1 or 2")
                    
                if pileChoice == 1 or pileChoice == 2:
                    break
                    
# Decide who's turn is next                   

        
        if currentPlayer == player1:
            currentPlayer = computer
            
        else:
            currentPlayer = player1
            
# Decide who's won
    print("DECIDING...")
    if pile1 and pile2 <= 0:
        winner = computer
    else:
        winner = player1
    

       
    print("Winner...congratulations,", winner,"!")       
    playAgain()
    
#If playing against another player    

def playAgainstPlayer():

    print("-" * 25)
    print("PLAYER VS PLAYER")
    print("-" * 25)
    player1 = input("Enter player 1 name: ")
    player2 = input("Enter player 2 name: ")

    pile1 = random.randint(2, 10)
    pile2 = random.randint(2, 10)

    print("Token pile 1:", pile1 * "O")
    print("Token pile 2:", pile2 * "O")
    currentPlayer = player1
    while pile1 > 0 and pile2 > 0:
    
#get valid move


        while True:
            print("-" * 25)
            print(currentPlayer.upper(), "TURN")
            print("-" * 25)
            pileChoice = int(input(currentPlayer + " which pile do you want to take tokens from, pile 1 or pile 2? "))

#remove Tokens from pile choice from pile 1
        
            if pileChoice == 1:
                while True:
                    removeTokens = int(input("How many tokens to remove? "))
                    if removeTokens <= 0 or removeTokens > pile1:
                        print("That's an invalid number, try again")
                        
                    else:
                        
                        pile1 = pile1 - removeTokens
                        print("Pile 1 now has ", pile1 * "O", " token(s) left")
         
                        break   

#remove Tokens from pile choice from pile 2
            
            elif pileChoice == 2:
                while True:
                    removeTokens = int(input("How many tokens to remove? "))
                    if removeTokens <= 0 or removeTokens > pile2:
                        print("That's an invalid number, try again")
                        
                    else:
                        
                        pile2 = pile2 - removeTokens
                        print("pile 2 now has ", pile2 * "O", " token(s) left")
         
                        break   



            else:
                print("error, please choose only 1 or 2")
            if pileChoice == 1 or pileChoice == 2:
                break

# Decide who's turn is next

        if currentPlayer == player1:
            currentPlayer = player2
        else:
            currentPlayer = player1

# Decide who's won

    print("DECIDING...")
    if playerOnePile <= 0:
        winner = player2
    else:
        winner = player1
        
        
    print("Winner, congratulations!", winner)
    playAgain()    
    
    
def playGame():
  
    gameType = input(str("Enter 1 for 1 v computer or 2 for 2 players? "))
    if gameType == "1":
        playAgainstComputer()
    elif gameType == "2":
        playAgainstPlayer()
            
    else:
        print("Invalid choice, try again")
        return(gameType)
    


playGame()
Reply
#2
*UPDATE*

I just realised the code I entered didn't indent anything so, it's probably best to use the zip file
Reply
#3
This is wrong:
    while pile1 > 0 and pile2 > 0:
The loop runs as long as pile1 > 0 AND pile2 > 0. If either pile < =0, the loops stops. You want this:
    while pile1 > 0 or pile2 > 0:
It would make more sense to use an array instead of multiple variables. A traditional game of NIM can make the piles like this:
piles = [1, 3, 5, 7]
For your game with 2 piles of random size:
piles = [randint(2, 10) for _ in range(2)]
Having the piles in an array simplifies testing if the game is done.
while sum(piles) > 0:
I don't like how you implemented the player vs player and player vs computer game play. Your functions playAgainstComputer() and playAgainstPlayer() contain a lot of duplicate code. I would write a function for the computer making a play (computer_play) and a function for a player making a play (player_play). Something like this:
def computer_play(piles):
    Randomly select pile and number of tokens to remove.
    piles[pile] -= tokens


def player_play(piles, player):
     Print piles an get user inputs for pile and tokens to remove.
     piles[pile] -= tokens


def play(player1, player2):
    """Play a game of NIM.  Player that removes the last token loses."""
    piles = [0, 1, 3, 5, 7]
    player = player1
    while sum(piles) > 0:
        if player == "Computer":
            computer_play(piles)
        else:
            player_play(piles, player)
        player = player1 if player == player2 else player2

    # Game is over.  Who won?
    if player == "Computer":
        print("The computer won.")
    else:
        print(f"Congratulations {player}.  You won!")


while True:
    try:
        num_players = int(input("Enter number of players (1, 2): "))
        if num_players in (1, 2):
            break
    except ValueError:
        pass

if num_players == 1:
    play(input("Enter player name: ").title(), "Computer")
else:
    play(input("Enter player 1 name: ").title(), input("Enter player 2 name: ").title())
Reply
#4
By what rules are you playing Nim?

A simple version is: start with 10 beans. You may take 1 or 2 beans each time. Whoever takes the last bean or beans wins.
Reply


Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020