python 命令行 俄罗斯方块

    技术2025-08-11  7

    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

    Processed: 0.010, SQL: 9