Tic Tac Toe game: I'm very confused why my code does not run when the user inputs one of the positional variables

82 Views Asked by At

For some reason, I cannot use a variable to define a space within this certain subset of the function

from turtle import *
john = Turtle()


def naughts(nposition):
    john.penup()
    john.goto(nposition)
    john.right(90)
    john.forward(120)
    john.left(90)
    john.pendown()
    john.circle(120)
    
def crosses(cposition):
    john.penup()
    john.goto(cposition)
    john.pendown()
    john.left(45)
    for x in range(4):
        john.forward(150)
        john.backward(150)
        john.left(90)
    john.right(45)


def main():
    
    pos1= (-400, 400)
    pos2= (0, 400)
    pos3= (400, 400)
    pos4= (-400, 0)
    pos5= (0, 0)
    pos6= (400, 0)
    pos7= -400, -400
    pos8= 0, -400
    pos9= 400, -400
    
    john.penup()
    john.goto(-200, -600)
    john.pendown()
    
    john.left(90)
    john.forward(1200)
    
    john.penup()
    john.goto(200, -600)
    john.pendown()
    
    john.forward(1200)
    john.left(90)
    
    john.penup()
    john.goto(600, -200)
    john.pendown()
    
    john.forward(1200)
    
    john.penup()
    john.goto(600,200)
    john.pendown()
    
    john.forward(1200)
    
    for turns in range(5):
        
        dake = input("Naughts, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        
        naughts(dake)
        ecks = input("Crosses, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        crosses(ecks)
            
if __name__ == "__main__":
    main()

With the variables at the very end, it returns

"TypeError: Vec2D.new() takes 3 positional arguments but 5 were given", and I'm unsure why.

I have tried to input the positional variables by themselves, which has worked.

2

There are 2 best solutions below

0
Anton Chernyshov On
john = Turtle()
POSITIONS = {"pos1":(-400, 400),
    "pos2": (0, 400),
    "pos3": (400, 400),
    "pos4": (-400, 0),
    "pos5":(0, 0),
    "pos6": (400, 0),
    "pos7": (-400, -400),
    "pos8": (0, -400),
    "pos9": (400, -400)}
john.speed(0) ## makes john very fast
def naughts(nposition):
    john.penup()
    john.goto(nposition)
    john.right(90)
    john.forward(120)
    john.left(90)
    john.pendown()
    john.circle(120)
    
def crosses(cposition):
    john.penup()
    john.goto(cposition)
    john.pendown()
    john.left(45)
    for x in range(4):
        john.forward(150)
        john.backward(150)
        john.left(90)
    john.right(45)


def main():
    john.penup()
    john.goto(-200, -600)
    john.pendown()
    
    john.left(90)
    john.forward(1200)
    
    john.penup()
    john.goto(200, -600)
    john.pendown()
    
    john.forward(1200)
    john.left(90)
    
    john.penup()
    john.goto(600, -200)
    john.pendown()
    
    john.forward(1200)
    
    john.penup()
    john.goto(600,200)
    john.pendown()
    
    john.forward(1200)
    
    for turns in range(5):
        
        dake = input("Naughts, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        dake = POSITIONS[dake]
        naughts(dake)
        ecks = input("Crosses, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        ecks = POSITIONS[ecks]
        crosses(ecks)
            
if __name__ == "__main__":
    main()

This fixes the problem you were having. What I did was make a dictionary containing the coordinates of the moves, and assigned the pos1, pos2... as keys so when the user enters the keys, POSITIONS[dake] returns the coordinates of the dake input.

The error was caused because input() returns a string, and parsing a string into the .goto() attribute caused a Typerror.

Now onto win detection...

0
Claudio On

The trouble you face is that you need pixel positions which are pairs of integer values, but the user input delivers a string instead.

Let's make it easy for the start and create a list lstPos of defined positions which can be used to turn inputs like 1, 2, ... ,9 into appropriate coordinates for the turtle to start drawing.

The code below tries to achieve proper function with as less changes to the original code as possible. Notice that in Python list indices start with 0, so a list with 9 items has indices from 0 to 8 (the reason for the -1 in the specification of the index). The int(nposition) expression makes an integer out of a by user input string.

The code below fixes with small changes to the original code the issue of requesting 10 input values instead of only 9 possible asking for the tenth input in order to quit and close the turtle window.

Notice that the positions and the list of positions are not defined within the main function as it is the case in your original code. This makes the positions and the list of positions global values instead of local within the the main() function. Global values can then be easily accessed within the naughts(nposition) and crosses(nposition) functions.

from turtle import *
john = Turtle()

pos1= (-400, 400)
pos2= (0, 400)
pos3= (400, 400)
pos4= (-400, 0)
pos5= (0, 0)
pos6= (400, 0)
pos7= (-400, -400)
pos8= (0, -400)
pos9= (400, -400)
lstPos=[pos1,pos2,pos3,pos4,pos5,pos6,pos7,pos8,pos9]

def naughts(nposition):
    john.penup()
    john.goto(lstPos[int(nposition)-1])
    john.right(90)
    john.forward(120)
    john.left(90)
    john.pendown()
    john.circle(120)
    
def crosses(cposition):
    john.penup()
    john.goto(lstPos[int(cposition)-1])
    john.pendown()
    john.left(45)
    for x in range(4):
        john.forward(150)
        john.backward(150)
        john.left(90)
    john.right(45)

def main():
    john.penup()
    john.goto(-200, -600)
    john.pendown()
    john.left(90)
    john.forward(1200)
    john.penup()
    john.goto(200, -600)
    john.pendown()
    john.forward(1200)
    john.left(90)
    john.penup()
    john.goto(600, -200)
    john.pendown()
    john.forward(1200)
    john.penup()
    john.goto(600,200)
    john.pendown()
    john.forward(1200)
    
    for turns in range(4):
        dake = input("Naughts, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        naughts(dake)
        ecks = input("Crosses, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
        crosses(ecks)

    dake = input("Naughts, please choose pos1, pos2, pos3, pos4, pos5, pos6, pos7, pos8, pos9: ")
    naughts(dake)
    input("Enter to exit/quit")
            
if __name__ == "__main__":
    main()