Lập trình game Tetris đơn giản trên Micro:bit

Hướng dẫn lập trình game Tetris trên Micro:bit

Bạn có từng mê mẩn với trò chơi Tetris huyền thoại? Trong dự án này, chúng ta sẽ lập trình một phiên bản đơn giản của Tetris ngay trên màn hình LED 5×5 của Micro:bit! Bạn sẽ học cách sử dụng vòng lặp, điều kiện, mảng và nút bấm để điều khiển khối rơi xuống. Một dự án vừa học vừa chơi rất lý tưởng cho học sinh, sinh viên và người yêu thích lập trình!

Thiết bị sử dụng trong bài hướng dẫn này

430.000 
550.000 
30.000 

Ngoài ra, bạn cần thêm máy tính có trình duyệt truy cập https://python.microbit.org/v/3 để thực hiện code và nạp code cho Micro:bit

Cách chơi 

Sẽ có 4 khối được thiết kế như hình dưới:

  • Khối (block) sáng sẽ rơi từ trên xuống màn hình LED.

  • Người chơi dùng nút A để di chuyển trái, nút B để di chuyển phải và ấn cả hai nút để xoay khối.

  • Nếu khối chạm đáy hoặc khối khác, nó sẽ đứng yên.

  • Nếu xếp đầy một hàng, hàng đó sẽ biến mất và bạn được 10 điểm.

  • Trò chơi kết thúc khi các khối chạm đỉnh màn hình.

VIDEO DEMO

PYTHON CODE

from microbit import *
from random import choice

#Set up the tetris grid
grid=[[1,0,0,0,0,0,1],[1,0,0,0,0,0,1],[1,0,0,0,0,0,1],[1,0,0,0,0,0,1],[1,0,0,0,0,0,1],[1,1,1,1,1,1,1]]
#Store a list of 4 bricks, each brick is a 2x2 grid
bricks = [[9,9],[9,0]],[[9,9],[0,9]],[[9,9],[9,9]],[[9,9],[0,0]]
#select a brick randomly and position it at the center/top of the grid (y=0,x=3)
brick = choice(bricks)
x=3
y=0
frameCount=0

#A function to return the maximum of two values
def max(a,b):
    if a>=b:
        return a
    else:
        return b
        
#A function to hide the 2x2 brick on the LED screen
def hideBrick():
    if x>0:
        display.set_pixel(x-1,y,grid[y][x])
    if x<5:
        display.set_pixel(x+1-1,y,grid[y][x+1])
    if x>0 and y<4:
        display.set_pixel(x-1,y+1,grid[y+1][x])
    if x<5 and y<4:
        display.set_pixel(x+1-1,y+1,grid[y+1][x+1])
        
#A function to show the 2x2 brick on the LED screen
def showBrick():
    if x>0:
        display.set_pixel(x-1,y,max(brick[0][0],grid[y][x]))
    if x<5:
        display.set_pixel(x+1-1,y,max(brick[0][1],grid[y][x+1]))
    if x>0 and y<4:
        display.set_pixel(x-1,y+1,max(brick[1][0],grid[y+1][x]))
    if x<5 and y<4:   
        display.set_pixel(x+1-1,y+1,max(brick[1][1],grid[y+1][x+1]))

#A function to rotate the 2x2 brick
def rotateBrick():
    pixel00 = brick[0][0]
    pixel01 = brick[0][1]
    pixel10 = brick[1][0]
    pixel11 = brick[1][1]
    #Check if the rotation is possible
    if not ((grid[y][x]>0 and pixel00>0) or (grid[y+1][x]>0 and pixel10>0) or (grid[y][x+1]>0 and pixel01>0) or (grid[y+1][x+1]>0 and pixel11>0)):
        hideBrick()        
        brick[0][0] = pixel10
        brick[1][0] = pixel11
        brick[1][1] = pixel01
        brick[0][1] = pixel00
        showBrick()     

#A function to move/translate the brick
def moveBrick(delta_x,delta_y):
    global x,y
    move=False
    #Check if the move if possible: no collision with other blocks or borders of the grid
    if delta_x==-1 and x>0:
        if not ((grid[y][x-1]>0 and brick[0][0]>0) or (grid[y][x+1-1]>0 and brick[0][1]>0) or (grid[y+1][x-1]>0 and brick[1][0]>0) or (grid[y+1][x+1-1]>0 and brick[1][1]>0)):
            move=True
    elif delta_x==1 and x<5:
        if not ((grid[y][x+1]>0 and brick[0][0]>0) or (grid[y][x+1+1]>0 and brick[0][1]>0) or (grid[y+1][x+1]>0 and brick[1][0]>0) or (grid[y+1][x+1+1]>0 and brick[1][1]>0)):
            move=True
    elif delta_y==1 and y<4:   
        if not ((grid[y+1][x]>0 and brick[0][0]>0) or (grid[y+1][x+1]>0 and brick[0][1]>0) or (grid[y+1+1][x]>0 and brick[1][0]>0) or (grid[y+1+1][x+1]>0 and brick[1][1]>0)):
            move=True
    #If the move is possible, update x,y coordinates of the brick
    if move:      
        hideBrick()
        x+=delta_x
        y+=delta_y
        showBrick()
        
    #Return True or False to confirm if the move took place
    return move    

#A function to check for and remove completed lines
def checkLines():
    global score
    removeLine=False
    #check each line one at a time
    for i in range(0, 5):
        #If 5 blocks are filled in (9) then a line is complete (9*5=45)
        if (grid[i][1]+grid[i][2]+grid[i][3]+grid[i][4]+grid[i][5])==45:
            removeLine = True
            #Increment the score (10 pts per line)
            score+=10
            #Remove the line and make all lines above fall by 1:
            for j in range(i,0,-1):
                grid[j] = grid[j-1]
            grid[0]=[1,0,0,0,0,0,1]    
    if removeLine:
        #Refresh the LED screen
        for i in range(0, 5):
            for j in range(0, 5):
                display.set_pixel(i,j,grid[j][i+1])
    return removeLine
    
gameOn=True
score=0
showBrick()
#Main Program Loop - iterates every 50ms
while gameOn:
    sleep(50)
    frameCount+=1
    #Capture user inputs
    if button_a.is_pressed() and button_b.is_pressed():
        rotateBrick() 
    elif button_a.is_pressed():
        moveBrick(-1,0)
    elif button_b.is_pressed():
        moveBrick(1,0)
    
    #Every 15 frames try to move the brick down
    if frameCount==15 and moveBrick(0,1) == False:
        frameCount=0
        #The move was not possible, the brick stays in position
        grid[y][x]=max(brick[0][0],grid[y][x])
        grid[y][x+1]=max(brick[0][1],grid[y][x+1])
        grid[y+1][x]=max(brick[1][0],grid[y+1][x])
        grid[y+1][x+1]=max(brick[1][1],grid[y+1][x+1])
        
        if checkLines()==False and y==0:
            #The brick has reached the top of the grid - Game Over
            gameOn=False   
        else:
            #select a new brick randomly
            x=3
            y=0
            brick = choice(bricks)
            showBrick()
    
    if frameCount==15:
       frameCount=0

#End of Game
sleep(2000)
display.scroll("Game Over: Score: " + str(score))

Ý tưởng mở rộng

  • Thêm nhiều loại khối.

  • Kết nối 2 người chơi bằng radio để gửi điểm.

  • Thêm âm thanh khi ghi điểm hoặc game over.

Kết luận

Dự án game Tetris trên Micro:bit là một ví dụ thú vị cho thấy chỉ với phần cứng đơn giản, bạn vẫn có thể tạo ra những trò chơi hấp dẫn bằng lập trình. Qua đó, bạn không chỉ luyện kỹ năng viết mã mà còn rèn tư duy logic, sáng tạo và giải quyết vấn đề. Nếu bạn chưa có Micro:bit, đây là thời điểm tuyệt vời để bắt đầu hành trình học lập trình và sáng tạo của riêng bạn với một thiết bị nhỏ gọn, dễ dùng và cực kỳ thú vị.