Search code examples
turtle-graphicspython-idle

Turtle not responding IDLE


I wrote this code with turtle library. The problem is that when I run this code in IDLE,everything works fine until it gets to the input in the function 'putBall()' ,and the window become 'not responding'. I tried several suggestions from google like 'turtle.done' in end of code or 'turtle.done' in the end of each one of the functions,but in seems do nothing in both cases. I want to add that I tried this code in online service 'Trinket' and it work fine.

import turtle

def initialize_pen_screen():
  s=turtle.getscreen()
  s.setup(600,600)
  t = turtle.Turtle()
  ballOne = turtle.Turtle()
  ballOne.shape('turtle')
  ballOne.fillcolor("red")
  ballOne.pencolor("red")
  ballTwo = turtle.Turtle()
  ballTwo.shape('turtle')
  ballTwo.fillcolor("blue")
  ballTwo.pencolor("blue")
  t.shape("turtle")
  s.bgcolor("gray")
  return [t,ballOne,ballTwo]

def initialize_pen_screen_saviour():
  t = turtle.Turtle()
  ballOne = turtle.Turtle()
  ballOne.shape('turtle')
  ballOne.fillcolor("red")
  ballOne.pencolor("red")
  ballTwo = turtle.Turtle()
  ballTwo.shape('turtle')
  ballTwo.fillcolor("blue")
  ballTwo.pencolor("blue")
  t.shape("turtle")
  return [t,ballOne,ballTwo]
  
def initialize_first(t,ballOne,ballTwo):
  t.rt(180)
  t.penup()
  t.fd(150)
  t.lt(90)
  t.pensize(10)
  ballOne.lt(90)
  ballOne.penup()
  ballOne.fd(90)
  ballTwo.lt(90)
  ballTwo.penup()
  ballTwo.fd(150)
  ballOne.rt(90)
  ballTwo.rt(90)

#draw line that goes down
def stamp_up(t):
  t.pendown()
  t.stamp()
  t.fd(250) #depends how long column
  #print(t.pos(),'UP')
  t.lt(90)
  t.penup()
  
#draw line that goes up  
def stamp_down(t):
  t.fd(70)
  #print(t.pos(),'Down')
  t.lt(90)
  t.pendown()
  t.stamp()
  t.fd(250) #depends how long column
  t.rt(90)
  t.penup()
  t.fd(70)
  t.rt(90)

#draw ball and save coordinate of reserved position in column   
def move_ball(chosenBall,x,y):
  chosenBall.goto(x+20,y+20)
  chosenBall.fd(15)
  chosenBall.dot(50)
  newClosedPos=[x,y+50]
  chosenBall.goto(0,150)
  return newClosedPos

#put ball in table,and save another reserved position in column  
def putBall(currentMove):
  print("which column to put your ball?")    
  column=input()
  if(column=='1'):
    x=closedColumnOne[len(closedColumnOne)-1][0]
    y=closedColumnOne[len(closedColumnOne)-1][1]
    newClose=move_ball(currentMove,x,y)
    closedColumnOne.append(newClose)
  elif(column=='2'):
    x=closedColumnTwo[len(closedColumnTwo)-1][0]
    y=closedColumnTwo[len(closedColumnTwo)-1][1]
    newClose=move_ball(currentMove,x,y)
    closedColumnTwo.append(newClose)
  elif(column=='3'):
    x=closedColumnThree[len(closedColumnThree)-1][0]
    y=closedColumnThree[len(closedColumnThree)-1][1]
    newClose=move_ball(currentMove,x,y)
    closedColumnThree.append(newClose)
  elif(column=='4'):
    x=closedColumnFour[len(closedColumnFour)-1][0]
    y=closedColumnFour[len(closedColumnFour)-1][1]
    newClose=move_ball(currentMove,x,y)
    closedColumnFour.append(newClose)
  elif(column=='5'):
    x=closedColumnFive[len(closedColumnFive)-1][0]
    y=closedColumnFive[len(closedColumnFive)-1][1]
    newClose=move_ball(currentMove,x,y)
    closedColumnFive.append(newClose)
  return column

#tell state of world after put ball in table
def afterPutBall(SelectedColumn,columnBalls,tableSize,tableBall):
  for k in range(0,tableSize): 
    for i in range(0,tableSize):  
      if(int(SelectedColumn)==k+1 and columnBalls[k][i]==0):
        columnBalls[k][i]=tableBall
        break
    else:
      continue
    break
  return columnBalls

#check if we in a win state 
def checkWin(tableSize,columnBalls):
    for k in range(0,tableSize-1):
      for i in range(0,tableSize-1):
        flagRow=1
        flagColumn=1
        flagDiagonalRight=1
        flagDiagonalLeft=1
        for j in range(0,tableSize-1):
          #row win
          if(columnBalls[j][i]==columnBalls[j+1][i] and columnBalls[j][i]!=0):
               flagRow+=1
          elif(flagRow!=0):
              flagRow=1
          #column win     
          if(columnBalls[i][j]==columnBalls[i][j+1] and columnBalls[i][j]!=0):
               flagColumn+=1
               #print(flagColumn)
          elif(flagColumn!=0):
              flagColumn=1
          #diagonal right
          if(i+j+1<=tableSize-1 and i+j<=tableSize-1 and j+k<=tableSize-1 and j+k+1<=tableSize-1): #end table
            if(columnBalls[j+k][i+j]==columnBalls[j+k+1][i+j+1] and columnBalls[j+k][i+j]!=0):
                flagDiagonalRight+=1
            elif(flagDiagonalRight!=0):
                flagDiagonalRight=1
          #diagonal left
          if(tableSize-j-i-1>=0 and tableSize-j-i-2>=0 and j+k<=tableSize-1 and j+k+1<=tableSize-1): #end table
            if(columnBalls[j+k][tableSize-j-i-1]==columnBalls[j+k+1][tableSize-j-i-2] and columnBalls[j+k][tableSize-j-i-1]!=0):
                flagDiagonalLeft+=1
            elif(flagDiagonalLeft!=0):
                flagDiagonalLeft=1 
          if flagRow==4 or flagColumn==4 or flagDiagonalLeft==4 or flagDiagonalRight==4:
            return True
    
    return False 
    
    
def score_board():
  score=turtle.Turtle()
  score.ht()
  score.color("green")
  #score board
  turtle.pensize(5)
  turtle.speed(6)
  turtle.penup()
  turtle.goto(-250,150)
  turtle.pendown()
  turtle.rt(90)
  for i in range(0,2):
    turtle.fd(100)
    turtle.lt(90)
    turtle.fd(130)
    turtle.lt(90)
    turtle.fd(100)
    turtle.lt(90)
    turtle.fd(150-i*20)
    turtle.lt(90)
  turtle.penup()
  turtle.ht()
  #turtle.setposition(150,100)
  #score write
  score.speed('fastest')
  score.penup()
  score.goto(-250,150)
  score.rt(90)
  score.fd(50)
  score.lt(90)
  score.fd(35)
  return score
  
def write_score(score,redPoints,bluePoints):
  score.clear()
  score.write(str(redPoints)+'-'+str(bluePoints),move=False ,font=("Verdana",
                                    18, "normal"), align="left")

#build table
def build_table(tableSize,table,opponentOne,opponentTwo):
    table.speed(6)
    initialize_first(table,opponentOne,opponentTwo)
    size_iter=int((tableSize-1)/2)
    for i in range(0,size_iter+1):
      stamp_up(table)
      stamp_down(table)
    if(tableSize%2==0): #even size table
        stamp_up(table)
    table.goto(0,250)
    table.lt(90)  
    #tableSize=(2*(i+1)-1)
    
if 'main':
  playAgain='yes'
  s=turtle.getscreen()
  s.setup(1000,1000)
  s.bgcolor("gray")
  score=score_board()
  redPoints=0
  bluePoints=0
  while(playAgain=='yes' or playAgain=='Yes'):
    tools=initialize_pen_screen_saviour()
    table=tools[0]
    opponentOne=tools[1]
    opponentTwo=tools[2]
    closedColumnOne=[[-150.0, -250.0]]
    closedColumnTwo=[[-80.0, -250.0]]
    closedColumnThree=[[-10.0, -250.0]]
    closedColumnFour=[[60.0, -250.0]]
    closedColumnFive=[[130.0, -250.0]]
    tableSize=8
    build_table(tableSize,table,opponentOne,opponentTwo)
    
    #initilize table state balls
    columnBalls=[]
    for i in range(0,tableSize):
      columnBall=[0]*tableSize
      columnBalls.append(columnBall)
    print(columnBalls)  
    myBall='A'
    playAgain='yes'
    #max moves:25
    for i in range(0,25):
      win=False
      print("Player "+myBall+" play now")
      if(myBall=='A'):
        currentMove=opponentOne
        myBall='B'
        tableBall='A'
      else:
        currentMove=opponentTwo
        myBall='A'
        tableBall='B'
      SelectedColumn=putBall(currentMove)
      columnBalls=afterPutBall(SelectedColumn,columnBalls,tableSize,tableBall)
      print(columnBalls)
      win=checkWin(tableSize,columnBalls)
      if(win):
        #update score player blue
        if(tableBall=='B'):
          write_score(score,redPoints,bluePoints+1)
          bluePoints+=1
        #update score player red  
        else:
          write_score(score,redPoints+1,bluePoints)
          redPoints+=1                          
        print('player '+tableBall+' WIN!!')
        print('Do you want to play again?')
        playAgain=input()
        if(playAgain=='no' or playAgain=='No'):
          break
        elif(playAgain=='yes' or playAgain=='Yes'):
          table.reset()
          opponentOne.reset()
          opponentTwo.reset()
          break

  #t.reset()
  #t.clear()

Solution

  • Please read https://stackoverflow.com/help/minimal-reproducible-example.

    Lines 80-81 of your code

      print("which column to put your ball?")    
      column=input('')
    

    print a prompt to the interactive shell and pause the turtle screen while the turtle code waits for a response entered in the separate shell or terminal window. (column = input('which column' would do the same.) To enter a column, the user must click on the window with the 'which column' prompt. One you do so, entering numbers works fine.

    A difference between IDLE and other ways from running a Python module is that IDLE sends your code to a separate process, different from the IDLE UI process, for execution. I believe that this is why clicking on the turtle window gives you the paused message that does not appear when running your code otherwise. I would have to do more experiements to determine whether this is true for all turtle programs that seek input from the terminal/shell.

    In any case, it is not normal for GUI programs to request input from the terminal/shell. Turtle provides textinput and numinput methods and function. Try using one of them.