Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
terminal上でテトリスで遊ぶ。テトリミノはカラーで描画される。実行環境: python3.X, `pip install pygame`, Windows or Linux
# -*- coding: utf-8 -*-
import pygame
from pygame.locals import *
import numpy as np
import subprocess
class Color:
"""print文に色をつける
用例:print(f'赤:{Color.RED}これは赤色文字です{Color.RESET}')
参考:https://www.nomuramath.com/kv8wr0mp/
"""
BLACK = '\033[30m' # (文字)黒
RED = '\033[31m' # (文字)赤
GREEN = '\033[32m' # (文字)緑
YELLOW = '\033[33m' # (文字)黄
BLUE = '\033[34m' # (文字)青
MAGENTA = '\033[35m' # (文字)マゼンタ
CYAN = '\033[36m' # (文字)シアン
WHITE = '\033[37m' # (文字)白
COLOR_DEFAULT = '\033[39m' # 文字色をデフォルトに戻す
BOLD = '\033[1m' # 太字
UNDERLINE = '\033[4m' # 下線
INVISIBLE = '\033[08m' # 不可視
REVERCE = '\033[07m' # 文字色と背景色を反転
BG_BLACK = '\033[40m' # (背景)黒
BG_RED = '\033[41m' # (背景)赤
BG_GREEN = '\033[42m' # (背景)緑
BG_YELLOW = '\033[43m' # (背景)黄
BG_BLUE = '\033[44m' # (背景)青
BG_MAGENTA = '\033[45m' # (背景)マゼンタ
BG_CYAN = '\033[46m' # (背景)シアン
BG_WHITE = '\033[47m' # (背景)白
BG_DEFAULT = '\033[49m' # 背景色をデフォルトに戻す
RESET = '\033[0m' # 全てリセット
class Tetris(object):
def __init__(self):
pygame.init()
pygame.display.set_mode((1, 1))
print("") # pygame text
self.board_size = [20, 10]
self.mino_col = {1: Color.BG_CYAN,
2: Color.BG_YELLOW,
3: Color.BG_MAGENTA,
4: Color.BG_BLUE,
5: Color.BG_DEFAULT,
6: Color.BG_GREEN,
7: Color.BG_RED,
" ": Color.COLOR_DEFAULT}
self.init_t4mino()
self.init_board()
self.gen_t4mino()
def init_board(self):
"""ボードを初期化する
"""
self.board = np.zeros(self.board_size, dtype=np.int)
def init_t4mino(self):
"""テトリミノを初期化する
"""
# including rotation table
self.t4mino_li = [
# i
[[[1, i] for i in range(4)],
[[i, 1] for i in range(4)]] * 2,
# o
[[[0, 0], [0, 1], [1, 0], [1, 1]]] * 4,
# t
[[[0, 1]] + [[1, i] for i in range(3)],
[[1, 2]] + [[i, 1] for i in range(3)],
[[2, 1]] + [[1, i] for i in range(3)],
[[1, 0]] + [[i, 1] for i in range(3)]],
# j
[[[0, 0]] + [[1, i] for i in range(3)],
[[0, 2]] + [[i, 1] for i in range(3)],
[[2, 2]] + [[1, i] for i in range(3)],
[[2, 0]] + [[i, 1] for i in range(3)]],
# l
[[[0, 2]] + [[1, i] for i in range(3)],
[[2, 2]] + [[i, 1] for i in range(3)],
[[2, 0]] + [[1, i] for i in range(3)],
[[0, 0]] + [[i, 1] for i in range(3)]],
# s
[[[0, 1], [0, 2], [1, 0], [1, 1]],
[[0, 0], [1, 0], [1, 1], [2, 1]]] * 2,
# z
[[[0, 0], [0, 1], [1, 1], [1, 2]],
[[0, 1], [1, 0], [1, 1], [2, 0]]] * 2
]
def game(self):
"""ゲームのメイン部分
30 fps -> 1 frame: 33 ms
"""
print("H:Left,L:Right,F/A:Rotate")
print("Type Command: ")
while self.yet():
pygame.time.wait(300)
self.display()
_pt = self.pt.copy()
key = self.get_key_input()
self.move(key)
self.move() # テトリミノを1個下げる
if _pt == self.pt:
self.save_board()
self.gen_t4mino()
print('END')
def yet(self) -> bool:
"""ゲームの終了条件
"""
mid = self.board_size[1] // 2
if (self.board[0, mid-2:mid+2] == 0).all():
return True
return False
def save_board(self):
"""ボードを保存する
"""
pt = self.pt
for ix in self.t4mino_li[self.cur][self.rot]:
self.board[ix[0]+pt[0], ix[1]+pt[1]] = self.cur + 1
# flush
for i in range(self.board_size[0]):
if (self.board[i] != 0).all():
for i_ in reversed(range(i)):
self.board[i_+1] = self.board[i_]
def element(self, i: int, j: int) -> str:
"""ボードに表示する要素
"""
ix_li = self.t4mino_li[self.cur][self.rot]
pt = self.pt
for ix in ix_li:
if ix[0]+pt[0] == i and ix[1]+pt[1] == j:
return self.cur + 1
tmp = self.board[i, j]
return ' ' if tmp == 0 else tmp
def display(self):
"""ボードの表示
"""
ix_li = self.t4mino_li[self.cur][self.rot]
pt = self.pt
for i in range(self.board_size[0]):
print('{:>2}|'.format(i), end='')
for j in range(self.board_size[1]):
e = self.element(i, j)
print(self.mino_col[e], end='')
print(e, end='')
print(Color.RESET, end='')
print('|')
print('--+' + '-' * self.board_size[1] + '+')
print("\033[{}A".format(self.board_size[0]+2), end="")
print("\r", sep="")
def get_key_input(self) -> str:
key = ""
for event in pygame.event.get():
# キーを押したとき
if event.type == KEYDOWN:
if event.key == K_ESCAPE:
key = "escape"
if event.key == K_LEFT:
key = "h"
if event.key == K_RIGHT:
key = "l"
if event.key == K_UP:
key = "f"
if event.key == K_DOWN:
key = "a"
return key
def move(self, to: str = ' ') -> bool:
"""テトリミノの移動や回転をする
"""
pt = self.pt
# left
if to == 'h':
q_li = [pt[0], pt[1]-1, self.rot]
# right
elif to == 'l':
q_li = [pt[0], pt[1]+1, self.rot]
# rotate right
elif to == 'f':
q_li = [pt[0], pt[1], (self.rot+1) % 4]
# rotate left
elif to == 'a':
q_li = [pt[0], pt[1], (self.rot-1) % 4]
# down
else:
q_li = [pt[0]+1, pt[1], self.rot]
for ix in self.t4mino_li[self.cur][q_li[-1]]:
if ix[0]+q_li[0] >= self.board_size[0] \
or ix[1]+q_li[1] < 0 \
or ix[1]+q_li[1] >= self.board_size[1] \
or self.board[ix[0]+q_li[0], ix[1]+q_li[1]] != 0:
return False
pt[0], pt[1], self.rot = q_li
return True
def gen_t4mino(self):
"""テトリミノを生成する
"""
self.cur = np.random.randint(7)
# i, otjlst
self.pt = [0, self.board_size[1] // 2 - (2 if self.cur == 0 else 1)]
self.pt = [0, self.board_size[1] // 2 - 1]
self.rot = 0
if __name__ == '__main__':
# Windows の場合
subprocess.run('cls', shell=True) # terminalの出力をすべて消去
# Linux の場合
# subprocess.run('clear') # terminalの出力をすべて消去
t = Tetris()
t.game()
@dannyso16
Copy link
Author

dannyso16 commented Dec 31, 2020

プレイの様子
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment