0

I've written a very simple program that has multiple threads that is supposed to print out to the terminal. One thread prints out an array of 10 stars, where the other thread is supposed to run in the background waiting to detect any keyboard presses. What I cannot solve is the output in the terminal does not print out properly if the second thread is running. If the second thread is stopped then the output is what is desired.

Full code (as requested):

#ASCII Frogger

from random import randint
import time
import sys, termios, tty, os
import threading    

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    try:
        tty.setraw(sys.stdin.fileno())
        ch = sys.stdin.read(1)

    finally:
        termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    return ch

def resetPositions():
        pos = ["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]
        return pos


def threadKeyPressDetection():
    button_delay = 0.2

    while True:
            char = getch();

            if (char == "p"):
                #print("Stop!")
                exit(0)

def threadGame():

    positions = ["*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]

    startingPos = randint(0, 9)

    frogPosition = startingPos

    i = 0
    ii = 0
    while i < 10:
        # if player press left go down in grid if space

        # if player press right go up in grid if space

        while ii < 10:
            if i < 5:
                positions[4] = (5 - i)
            print positions[ii],
            ii += 1
        ii = 0

        if i == 5:
            print "\n\n\n        GO        "

        print "\n"
        positions = resetPositions()

        if i > 5:
            positions[frogPosition] = '!'

        i += 1
        time.sleep(1)


try:
    t1 = threading.Thread(target=threadKeyPressDetection)
    t2 = threading.Thread(target=threadGame)

    t1.start()
    t2.start()

    t1.join()
    t2.join()

except:
    print("Error occured - unable to start thread")

Desired output:

* * * * 3 * * * * *

* * * * 2 * * * * *

* * * * 1 * * * * *

        GO

* * * * * * * * * *

* * * * * * ! * * *

Current output:

* * * * 5 * * * * *

            * * * * 4 * * * * *

                                        * * * * 3 * * * * *

                                                            * * * * 2 * * * * *

                                                                                * * * * 1 * * * * *

                                                                                                    * * * * * * * * * *


                                                                                                                                GO
eyllanesc
  • 235,170
  • 19
  • 170
  • 241
Biscuit
  • 53
  • 12

2 Answers2

2

The problem occurs here:

tty.setraw(sys.stdin.fileno())
  ch = sys.stdin.read(1)

The tty is set to raw mode and then told to wait to read a char. While this thread is waiting for input, the other thread continues to output. It continues to output with the tty in raw mode. You can check this is the error by changing getchr() to just

def getchr():
  tty.setraw(sys.stdin.fileno())
  exit(0)

This will put the tty in raw mode and then kill the thread immediately. Using this, you will still get the same, undesired output even though only 1 thread is running.

The easiest fix would be to use a method from here.

Tyler Marshall
  • 489
  • 3
  • 9
-2

Need to change tty.setraw to tty.setcbreak

Dharman
  • 30,962
  • 25
  • 85
  • 135