Series entry
"Python3 Programming Actual Tetris Robot"
problem found
During the test, it was found that there was a program error, but the timer was turned off and there would be no problem without automatic falling. The reason is that the Timer will open a new thread, which will cause resource conflicts with the main thread.
solution
The first thing that comes to mind is locking. The game logic is very simple, and locking should be easy to solve the problem. But no matter if I add coarse-grained or fine-grained as much as possible, it will deadlock in the end. Finally, I printed it and found that the program stopped at tkinter.Canvas.move. I personally think this is a bug in tkinter.
This road fails, so change your mind. Open a worker thread to complete all operations. The main thread and timer operations are just submitting tasks to the worker thread. That is, only one worker thread is allowed to do the task, thus avoiding the problem of resource conflicts.
Lock
Analysis of Locking Scheme
Keyboard response lock
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)
Timer response 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()
identify the problem
The program finally stopped at tkinter.Canvas.move in the Block class, which was triggered by the timer each time and could not be released.
Interested students can go to the project and switch to the lockbug branch to study. I wrote a lot of printouts to facilitate problem location.
Increase worker threads
Task unit design
A new Queue is added. The keyboard response and timer response add task units to the queue, and the worker threads process these tasks one by one. The task unit is designed as follows:
("cmd",(data))
Each task unit is a two-tuple (convenient for data deconstruction), the first is a string, which is a command; the second is a tuple, which is a data packet (also designed in a convenient way to deconstruct), by each Each command is self-defined.
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 transformation
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 transformation
The main function of game control. After the cube drops to the bottom, it will eliminate the layer, count the score, determine the speed level, determine whether the game is over, and move the next cube into the game space and generate a cube to display in the next cube display space.
def tickoff(self):
if self.gameRunningStatus == 1:
opQueue.put(('Down'),())
self.tick = Timer(self.gameSpeedInterval / 1000, self.tickoff)
self.tick.start()
project address
https://gitee.com/zhoutk/ptetris
或
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 items
C++ version has been implemented, project address:
https://gitee.com/zhoutk/qtetris
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。