python 命令行 俄羅斯方塊

import time
import os 
import sys
import numpy as np

from pynput.keyboard import Listener as kLis
from pynput.keyboard import Key as kKey
from pynput.keyboard import Controller as kCtl
import keyboard
from pynput.mouse import Button as mBut
from pynput.mouse import Controller as mCtl
import random

# 遊戲界面定義
shape = [15, 10]
data = np.zeros((shape[0]+2, shape[1]+2), dtype=int, order='C')
data[:, 0] = 2 # 左
data[:, data.shape[1] - 1] = 2 # 右
data[0] = 3 # 上
data[data.shape[0] - 1] = 4  # 下

# 方塊
shape01 = [
    [
        [
            [0, 0, 0],
            [1, 0, 0],
            [1, 1, 1]
        ], [
            [1, 1, 0],
            [1, 0, 0],
            [1, 0, 0]
        ], [
            [0, 0, 0],
            [1, 1, 1],
            [0, 0, 1]
        ], [
            [0, 0, 1],
            [0, 0, 1],
            [0, 1, 1]
        ],
    ],
    [
        [
            [0, 0, 0],
            [0, 0, 1],
            [1, 1, 1]
        ], [
            [1, 0, 0],
            [1, 0, 0],
            [1, 1, 0]
        ], [
            [0, 0, 0],
            [1, 1, 1],
            [1, 0, 0]
        ], [
            [0, 1, 1],
            [0, 0, 1],
            [0, 0, 1]
        ],
    ], [
        [
            [0, 0, 0],
            [0, 1, 0],
            [1, 1, 1]
        ], [
            [0, 1, 0],
            [0, 1, 1],
            [0, 1, 0]
        ], [
            [0, 0, 0],
            [1, 1, 1],
            [0, 1, 0]
        ], [
            [0, 1, 0],
            [1, 1, 1],
            [0, 0, 0]
        ],
    ], [
        [
            [0, 1, 0],
            [0, 1, 0],
            [0, 1, 0]
        ], [
            [0, 0, 0],
            [1, 1, 1],
            [0, 0, 0]
        ], [
            [0, 1, 0],
            [0, 1, 0],
            [0, 1, 0]
        ], [
            [0, 0, 0],
            [1, 1, 1],
            [0, 0, 0]
        ],
    ], [
        [
            [1, 0],
            [1, 1]
        ], [
            [1, 1],
            [1, 0]
        ], [
            [1, 1],
            [0, 1]
        ], [
            [0, 1],
            [1, 1]
        ],
    ], [
        [[1]],
        [[1]],
        [[1]],
        [[1]]
    ]
]

shape01_len = 24

shape_id = 24 -1 

b_h = '^------------------^'
b_b = '|                  |'
b_f = 'v------------------v'
ds = data.shape

# 遊戲主界面, [當前形狀編碼, 形狀位置], 下一個形狀編碼, 分數
def print_game(data, es, dn, score):
    sc_x = 2
    sc_y = int(ds[0] * 0.2)
    dn_x = 2
    dn_y = int(ds[0] * 0.5)

    # ------------- 分數顯示 -------------
    bl = len(b_b)
    sc_l = 'score: '+str(score)
    sc_l = '| ' + sc_l + ' ' * (bl - len(sc_l) - 4) + ' |'
    # ------------- ------------- -------------
    
    # ------------- 下一個形狀 -------------
    dn_l = 'next:'
    dn_l = '| ' + dn_l + ' ' * (bl - len(dn_l) - 4) + ' |'
    dn_s = []
    for i in shape01[dn // 4][dn % 4]:
        s = '|      ' 
        for j in i:
            if j == 0:
                s += '  '
            elif j == 1:
                s += 'x '
        s += ' ' * (bl - len(s) - 3) + '  |'
        dn_s.append(s)
    # ------------- ------------- -------------

    # ------------- 移動圖像位置 -------------
    tes = []
    for ei, i in enumerate(shape01[es[0] // 4][es[0] % 4]):
        if ei + es[1] < 0:
            ts = '  '
        else:
            ts = '0 '
            pass
        s = ts * es[2]
        for j in i:
            if j == 0:
                s += ts
            elif j == 1:
                s += 'x '
        s += ts * (ds[1] - len(s)//2)
        tes.append(s)
    # ------------- ------------- -------------

    # ------------- 遊戲界面 -------------
    for ei, i in enumerate(data):
        # ------- 顯示界面 -------
        print('%2s' % ei,end=' ')
        gd = []
        for j in i:
            if j == 0: gd.append( '  ')
            elif j == 1: gd.append('x ')
            elif j == 2: gd.append('| ')
            elif j == 3: gd.append('  ')
            elif j == 4: gd.append('--')
        if ei >= es[1] - 2 and ei < es[1] + len(shape01[es[0] // 4][es[0] % 4]) - 2:
            for em, m in enumerate(shape01[es[0] // 4][es[0] % 4][ei + 2-es[1]]):
                if m == 1 and (es[2]+em)-1 < len(gd):
                    gd[(es[2]+em)-1] = 'x '
        print(''.join(gd), end='')
        
        # ------ 狀態界面 -------
        if ei == 0:
            print(b_h,end='')
        elif ei == ds[0]-1:
            print(b_f, end='')
        elif ei == sc_y:
            print(sc_l, end='')
        elif ei == dn_y:
            print(dn_l, end='')
        elif ei > dn_y + 1 and ei < dn_y + len(dn_s) + 2:
            print(dn_s[ei-dn_y-2], end='')
        else:
            print(b_b, end='')
        print()
    # ------------- ------------- -------------



def is_stand (data, es):
    for ei,i in enumerate(shape01[es[0]//4][es[0] % 4]):
        for ej, j in enumerate(i):
            dt = data[es[1]+ei-1, es[2]+ej-1]
            if j == 1 and (dt == 1 or dt == 4):
                return True
    return False


def is_over(data, es):
    for ei, i in enumerate(shape01[es[0]//4][es[0] % 4]):
        for ej, j in enumerate(i):
            dt = data[es[1] + ei - 2, es[2] + ej - 2]
            # print(dt, end = ' ')
            if j == 1 and dt == 3:
                return True
        # print()
    return False

score = 0

def do_clean(data):在這裏插入代碼片
    global score
    line_count = []
    line = np.ones([shape[1]], dtype=int)
    for ea, a in enumerate(data[1:-1]):
        if np.equal(a[1:-1], line).all():
            line_count.append(ea)
    for li in line_count:
        data[2: li + 2, 1:-1] = data[1: li + 1, 1:-1]
    data[1][1:-1] = np.zeros([shape[1]], dtype=int)
    score += len(line_count)
    # pass 


def can_change(data, es):
    for ei, i in enumerate(shape01[es[0]//4][es[0] % 4]):
        for ej, j in enumerate(i):
            dt = data[es[1] + ei - 2, es[2] + ej - 2]
            if j == 1 and (dt in [1,2,4]):
                return False
    return True


nx_sh_id = random.randrange(0, shape01_len)

ps_y = 0
ps_x = 0
sh_id =0
stime = 1

def press(key):
    global ps_x
    global ps_y
    global sh_id
    global nx_sh_id
    global stime
    
    if str(key).strip('\'') == 'a':
        if can_change(data, [sh_id, ps_y, ps_x]):
            ps_x -= 1
    elif str(key).strip('\'') == 'd':
        if can_change(data, [sh_id, ps_y, ps_x+2]):
            ps_x += 1
    elif str(key).strip('\'') == 'w':
        t1 = sh_id % 4
        t2 = sh_id // 4
        t3 = t2*4 + (t1+1)%4
        if can_change(data, [t3, ps_y, ps_x+]):
            sh_id = t3
    elif str(key).strip('\'') == 's':
        # ps_y = 
        stime = 0.2

    print('\033[2K\033[1A \033[1C')
    print("\033[2J")
    print_game(data, [sh_id, ps_y, ps_x], nx_sh_id, score)
    sys.stdout.flush()


listener = kLis(on_press=press) 
listener.start()

while True:
    sh_id = nx_sh_id
    nx_sh_id = random.randrange(0, shape01_len)
    ps_y = 0
    ps_x = ds[1]//2-len(shape01[sh_id//4][sh_id % 4][0])//2
    stime = 1
    while True:
        ps_y += 1
        print("\033[2J")
        print_game(data, [sh_id, ps_y, ps_x], nx_sh_id, score)
        time.sleep(stime)
        
        # 判斷是否結束下墜
        df = is_stand(data, [sh_id, ps_y, ps_x])
        if df:
            print('done')
            break
    s_w = len(shape01[sh_id // 4][sh_id % 4][0])
    s_h = len(shape01[sh_id // 4][sh_id % 4])
    # 判斷是否完結
    if is_over(data, [sh_id, ps_y, ps_x]):
        print('game over')
        break
        
    data[ps_y-2:ps_y+s_h-2, ps_x-1:ps_x +
         s_w-1] += np.array(shape01[sh_id // 4][sh_id % 4], dtype=int)
    # 判斷是否消行
    do_clean(data)

listener.join()

按鍵 功能 備註
a 向左
d 向右
w 變形
s 加速下落

代碼運行需要 pynput

pip install pynput

運行效果

 0                         ^------------------^
 1 |                     | |                  |
 2 |                     | |                  |
 3 |       x x x         | | score: 3         |
 4 |         x           | |                  |
 5 |                     | |                  |
 6 |                     | |                  |
 7 |                     | |                  |
 8 |                     | | next:            |
 9 |                     | |                  |
10 |                     | |      x           |
11 | x                   | |                  |
12 | x                   | |                  |
13 | x   x           x x | |                  |
14 | x x x x x x x x   x | |                  |
15 | x x   x x x x x x x | |                  |
16 ------------------------v------------------v

學習了一些庫的使用,實現還是挺簡單的,供大家參考。
一個小遊戲,難度不大,我也是給朋友展示python的功能,促進學習興趣。


項目 上傳到 gitee 上了 https://gitee.com/hocker/tetris

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章