Search code examples
pythonmatrixlogicdice

Logic Error in a matrix roll dice program in Python


I have the following code for a simple game that lets player1 and player2 take turns to roll two six sided dice(die). On reaching 49 (the last number in the matrix) a player will win. Players start at 1 and then move up the number that is rolled (total of both die).

I have three errors (logic errors) in my code that I need some help with.

1)The winner functionality doesn't work. If a player reaches 49 or is close (see output at the end) it doesn't logically allow them to win. (just keep pressing enter to run a test and see the peculiar output pasted below). Player 1 AND Player 2 can reach 49 but it doesn't take them to the "winner()" module. Why? I have used ">=" correctly or have I not?

Having said that, in one test: Player 2 reached 49, and it didn't go to the winner() module:

    Press Enter to continue
Player 2, it's your turn to roll the dice: Press r to roll:>>>
Player2: You rolled a: 4 and a 6 which gives you a: 10
You have moved 10 spaces to position:....... 49

2)On exiting the program completely and starting again, the values of player1position and player2position are reset to 0 and it works. But if I just go to main() to replay the game, these values are not reset. I don't fully understand the usage and declaration of global variables and initialisation. Can anyone shed some light and an explanation/suggestion would help

3)Negative numbers aren't dealt with accurately. If on any turn a player throw TWO of the SAME number, they are meant to go back for the number rolled. e.g. if 2 and 2 rolled, the player goes back 4. However, if the player goes back when they are 5, 10 spaces, to -5, the next turn doesn't add up the total for player1position or player2position and the counting is messed up. I've tried various fixes and I'd be interested in any comments, suggestions and improvements.

The erroneous output is below:

First, this is the matrix:

*************LOADING GAME******************
Welcome: player1 and player2
[43, 44, 45, 46, 47, 48, 49]
[42, 41, 40, 39, 38, 37, 36]
[29, 30, 31, 32, 33, 34, 35]
[28, 27, 26, 25, 24, 23, 22]
[15, 16, 17, 18, 19, 20, 21]
[14, 13, 12, 11, 10, 9, 8]
[1, 2, 3, 4, 5, 6, 7]

The code that is relevant is as follows:

import sys
import csv
import random 
def main():
    startscreen()

def loadstartgame(player1,player2):
    with open("messages.txt","r") as f:
        idnumber="1"
        fReader=csv.reader(f)
        for row in fReader:
            for field in row:
                if field==idnumber:
                                       print(row[2])


        start=input("Start?:>>")

        if start=="s" or "S":

            callmatrix(player1,player2,7)

def startscreen():
    print("******************************Welcome to CONQUER THE MATRIX****************************")
    print("You can take on a friend in this game")
    player1=input("Enter name of Player 1: ")
    player2=input("Enter name of Player 2: ")
    print("Welcome ...", player1,"and, ", player2, "...Are you ready?")
    response=input("Yes or No? Player 1 - perhaps you could confirm please: ")
    if response=="yes" or "Yes" or "yEs" or "YeS":
        loadstartgame(player1, player2)
    else:
        sys.exit()



def matrix(n): 
    grid = [[1 + i + n * j for i in range(n)] for j in range(n)] 
    for row in grid[1::2]:
        row.reverse()    
    return grid[::-1][:]

def callmatrix(player1,player2, n):
    print("*************LOADING GAME******************")
    print("Welcome:", player1,"and", player2)
    for i in matrix(n):
            print(i)
    playing = True
    playerturns(player1,player2,playing)


def playerturns(player1,player2,playing):

    print(" - - - - - - - - - - ")
    print("Press Enter to continue")

    while(playing):     
        roll=input()
        if roll=="":
            RollTwoDiceP1(player1,player2)

        else:
            break
    RollTwoDiceP2(player1,player2)


global player1position #declare a local variable called player1position
player1position=0 #set the global variable before the start of this sub to 0
def RollTwoDiceP1(player1,player2):
    global player1position

    print("player1position in PLAYER1ROLL", player1position)
    #print("player1position at stat of RollTwoDicep1", player1position) #a test that prints the current value of player 1 position
    turn=input("Player 1, it's your turn to roll the dice: Press r to roll:>>>")
    die1=random.randint(1,6)
    die2=random.randint(1,6)
    #die1=5 #for testing purposes
    #die2=5 #for testing purposes
    roll=die1+die2    
    print("Player1: You rolled a:", die1, "and a", die2, "which gives you a:", roll)
    playing = False

    matrixlist=matrix(7)

    if die1==die2:
        gobackspacesP1(roll,player1,player2)
    else:
        print("You have moved", roll, "spaces to position:.......",matrixlist[6][0]+(roll+player1position))
    #print("playerposition plus roll:", player1position+roll) #a test that prints the playerposition+roll - this always comes up to 1 more than it should do on the location, so below substract 1, to make it produce an accurate location on the matrix for a particular roll
    player1position=matrixlist[6][0]+(roll+player1position)
    if player1position>=49:
                winner()
    else:
                playerturns(player1,player2,playing)

#global player1position
#global player2position
def gobackspacesP1(roll,player1,player2):
    global player1position
    if player1position<=1:
        player1position=0
        print("Oh dear - sorry you are now back to square 1 - literally!")
    else:
        print("Oh dear -you are now back on the matrix to position:", (1+player1position)-roll)
        matrixlist=matrix(7)
        #new player1position=the first playerposition minus the roll (rather than add it) and + 1 (as the initial position is always 1)
        player1position=1+(player1position-roll)
        #player1position=matrixlist[6][0]+(roll+player1position)-roll
    playing=False
    print("player1position in goback", player1position)
    playerturns(player1,player2,playing)



def gobackspacesP2(roll,player1,player2):
    global player2position
    if player2position<=1:
        player2position=0
        print("Oh dear - sorry you are now back to square 1 - literally!")
    else:
        print("Oh dear -you are now back on the matrix to position:", (1+player2position)-roll)
        matrixlist=matrix(7)
        #new player1position=the first playerposition minus the roll (rather than add it) and + 1 (as the initial position is always 1)
        player2position=1+(player2position-roll)
        #player1position=matrixlist[6][0]+(roll+player1position)-roll
    playing=True
    print("player2position in goback", player2position)
    playerturns(player1,player2,playing)


global player2position
player2position=0
def RollTwoDiceP2(player1,player2):
    global player2position
#Remember you need to add the functioanlity for a double identical dice roll to this subroutine for Player2 as well. 
    turn=input("Player 2, it's your turn to roll the dice: Press r to roll:>>>")
    die1=random.randint(1,6)
    die2=random.randint(1,6)
    roll=die1+die2    
    print("Player2: You rolled a:", die1, "and a", die2, "which gives you a:", roll)
    playing = True
    matrixlist=matrix(7)

    if die1==die2:
        gobackspacesP2(roll,player1,player2)
    else:
        print("You have moved", roll, "spaces to position:.......",matrixlist[6][0]+(roll+player2position))
    #print("playerposition plus roll:", player1position+roll) #a test that prints the playerposition+roll - this always comes up to 1 more than it should do on the location, so below substract 1, to make it produce an accurate location on the matrix for a particular roll
    player2position=matrixlist[6][0]+(roll+player2position)
    if player2position>=49:
                winner()
    else:
                playerturns(player1,player2,playing)

def winner():
    print("Ahh, it appears you have won! Congratulations!")
    sys.exit()

def easygrid():
    grid=[[43,44,45,46,47,48,49],[42,41,40,39,38,37,36],[29,30,31,32,33,34,35],[28, 27, 26, 25,24,23,22], [15,16,17, 18, 19, 20, 21], [14, 13, 12, 11, 10, 9, 8], [1, 2, 3,4,5,6,7]]
    for i in grid:
        print(i)
main()

I'd also be interested in any comments about my use of global variables and how best to use/not use them in this context.

I do not want a class based solution, so the answer would have to be a fix to this.

ERRONEOUS OUTPUT 1 (only player 2 wins, even though Player 1 should have won) LAST FEW ROLLS leading up to the win:

player1position in PLAYER1ROLL 38
Player 1, it's your turn to roll the dice: Press r to roll:>>>
Player1: You rolled a: 3 and a 5 which gives you a: 8
You have moved 8 spaces to position:....... 47
- - - - - - - - - - 
Press Enter to continue
Player 2, it's your turn to roll the dice: Press r to roll:>>>
Player2: You rolled a: 6 and a 5 which gives you a: 11
You have moved 11 spaces to position:....... 43
- - - - - - - - - - 
Press Enter to continue

player1position in PLAYER1ROLL 46
Player 1, it's your turn to roll the dice: Press r to roll:>>>
Player1: You rolled a: 3 and a 5 which gives you a: 8
You have moved 8 spaces to position:....... 55
- - - - - - - - - - 
Press Enter to continue
Player 2, it's your turn to roll the dice: Press r to roll:>>> 
Player2: You rolled a: 6 and a 1 which gives you a: 7
You have moved 7 spaces to position:....... 50
You've won! Congratulations!

Solution

  • The bug was in this line: (in the RollTwoDice1 and RollTwoDice2 subs)

    player1position=matrixlist[6][0]+(roll+player1position)
    

    the matrixlist[6][0] was added an erroneous +1, which when removed sorted the logic error.

    Also: (in the gobacktospaces subs)

     player2position=1+(player2position-roll)
    

    It had an extra -1 in it, which kept skewing the results for both the winner functionality and the adding up.