Series entry

Programming Tetris Robot in Python3

Found the problem

In the test process, found that the program error, but close the timer, do not automatically fall will not have a problem. The reason is that the Timer will start a new thread, thread and the main thread will create a resource conflict.

The solution

The first thing that comes to mind is locking. The game logic is simple, and locking should be easy to solve. But whether I add it coarse-grained or as fine-grained as possible, I’m going to end up deadlocking. Finally, after printing, I found that the program stopped at tkinter.Canvas. Move, which I personally think is a bug of tkinter. This road is blocked. Try another way. Start a worker thread and do all the operations, the main thread and the timer operation, just submit the task to the worker thread. By having only one worker thread do the task, you avoid the problem of resource conflicts.

lock

Lock scheme analysis

Keyboard response locks

tickLock[0] = True
with curTetrisLock:
    print("-------+++---00000000--- get lock", tickLock)
    if ke.keysym == 'Left':
        self.game.moveLeft()
    if ke.keysym == 'Right':
        self.game.moveRight()
    if ke.keysym == 'Up':
        self.game.rotate()
    if ke.keysym == 'Down':
        self.game.moveDown()
    if ke.keysym == 'space':
        self.game.moveDownEnd()
print("-------+++---00000000--- lose lock", tickLock)

The timer responds to the lock

def tickoff(self):
    if self.gameRunningStatus == 1:
        if not tickLock[0]:
            with curTetrisLock:
                print("------------------ get lock", tickLock[1])
                self.moveDown()
            print("================== lose lock", tickLock[1])
        self.tick = Timer(self.gameSpeedInterval / 1000, self.tickoff)
        self.tick.start()

Problem orientation

The program ends up at tkinter.Canvas. Move in the Block class, which is triggered by the timer each time and cannot be released.



Those of you who are interested can go to the project, switch over to the Lockbug branch and work on it, and I’ve written a lot of printouts to help you pinpoint problems.

Add worker thread

Task unit design

Add a Queue, the keyboard response and the timer response add units of work to the Queue, and the worker thread processes these tasks one by one. The task unit is designed as follows:

("cmd",(data))

Each task unit is a duple (to facilitate data deconstruction), the first is a string, is a command; The second is a tuple, which is a packet (also designed to be easy to deconstruct), defined by each command.

The worker thread

def opWork(self): while True: if not opQueue.empty(): cmd,data = opQueue.get() if op == "Left": self.moveLeft() elif op == "Right": self.moveRight() elif op == "Up": self.rotate() elif op == "Down": Self. moveDown() elif op == "space": self.moveDownEnd() elif op == "quit": break else: time.sleep(0.01)

Keyboard response modification

def processKeyboardEvent(self, ke):
    if self.game.getGameRunningStatus() == 1:
        if ke.keysym == 'Left':
            opQueue.put(('Left',()))
        if ke.keysym == 'Right':
            opQueue.put(('Right',()))
        if ke.keysym == 'Up':
            opQueue.put(('Up',()))
        if ke.keysym == 'Down':
            opQueue.put(('Down',()))
        if ke.keysym == 'space':
            opQueue.put(('space',()))

Timer modification

The main function of the game control, in the box falling to the bottom, the elimination of layers, statistics score, speed level determination, the game is over determination and the next box will be moved into the game space and regeneration into a box display space in the next box.

def tickoff(self):
    if self.gameRunningStatus == 1:
        opQueue.put(('Down'),())
        self.tick = Timer(self.gameSpeedInterval / 1000, self.tickoff)
        self.tick.start()

The project address

https://gitee.com/zhoutk/ptetris or https://github.com/zhoutk/ptetris

Operation method

1. install python3, git
2. git clone https://gitee.com/zhoutk/ptetris (or download and unzip source code)
3. cd ptetris
4. python3 tetris

This project surpport windows, linux, macOs

on linux, you must install tkinter first, use this command:  
sudo apt install python3-tk

Related projects

C++ version has been implemented, project address:

https://gitee.com/zhoutk/qtetris