import sys
import time
import random
# myCompiler環境(CUI)の制約に対応するためcursesを使用
try:
import curses
except ImportError:
print("この環境ではcursesライブラリがサポートされていないか、ターミナル環境が必要です。")
sys.exit()
# ゲームボードのサイズ
BOARD_WIDTH = 10
BOARD_HEIGHT = 20
# テトロミノ(ブロック)の形状定義
SHAPES = {
'I': [[1, 1, 1, 1]],
'O': [[1, 1], [1, 1]],
'T': [[0, 1, 0], [1, 1, 1]],
'S': [[0, 1, 1], [1, 1, 0]],
'Z': [[1, 1, 0], [0, 1, 1]],
'J': [[1, 0, 0], [1, 1, 1]],
'L': [[0, 0, 1], [1, 1, 1]]
}
class Tetris:
def __init__(self):
self.board = [[0] * BOARD_WIDTH for _ in range(BOARD_HEIGHT)]
self.score = 0
self.game_over = False
self.new_piece()
def new_piece(self):
self.current_shape = random.choice(list(SHAPES.values()))
self.piece_y = 0
self.piece_x = BOARD_WIDTH // 2 - len(self.current_shape[0]) // 2
if self.check_collision(self.piece_y, self.piece_x, self.current_shape):
self.game_over = True
def check_collision(self, dy, dx, shape):
for y, row in enumerate(shape):
for x, val in enumerate(row):
if val:
ny, nx = dy + y, dx + x
if nx < 0 or nx >= BOARD_WIDTH or ny >= BOARD_HEIGHT:
return True
if ny >= 0 and self.board[ny][nx]:
return True
return False
def lock_piece(self):
for y, row in enumerate(self.current_shape):
for x, val in enumerate(row):
if val:
self.board[self.piece_y + y][self.piece_x + x] = 1
self.clear_lines()
self.new_piece()
def clear_lines(self):
new_board = [row for row in self.board if not all(row)]
lines_cleared = BOARD_HEIGHT - len(new_board)
self.score += lines_cleared * 100
while len(new_board) < BOARD_HEIGHT:
new_board.insert(0, [0] * BOARD_WIDTH)
self.board = new_board
def move(self, dy, dx):
if not self.check_collision(self.piece_y + dy, self.piece_x + dx, self.current_shape):
self.piece_y += dy
self.piece_x += dx
return True
if dy > 0:
self.lock_piece()
return False
def rotate(self):
# 行列を時計回りに回転
rotated = [list(x) for x in zip(*self.current_shape[::-1])]
if not self.check_collision(self.piece_y, self.piece_x, rotated):
self.current_shape = rotated
def draw_game(stdscr, game):
stdscr.clear()
# スコア表示
stdscr.addstr(0, 0, f"SCORE: {game.score}")
stdscr.addstr(1, 0, "Controls: [A]Left [D]Right [S]Down [W]Rotate [Q]Quit")
# 描画用のバッファ作成
display_board = [row[:] for row in game.board]
for y, row in enumerate(game.current_shape):
for x, val in enumerate(row):
if val and (game.piece_y + y) < BOARD_HEIGHT:
display_board[game.piece_y + y][game.piece_x + x] = 2
# 枠とボードの描画
stdscr.addstr(2, 0, "+" + "-" * (BOARD_WIDTH * 2) + "+")
for y in range(BOARD_HEIGHT):
line = "|"
for x in range(BOARD_WIDTH):
if display_board[y][x] == 0:
line += " "
else:
line += "[]"
line += "|"
stdscr.addstr(3 + y, 0, line)
stdscr.addstr(3 + BOARD_HEIGHT, 0, "+" + "-" * (BOARD_WIDTH * 2) + "+")
if game.game_over:
stdscr.addstr(BOARD_HEIGHT // 2 + 2, BOARD_WIDTH - 4, "GAME OVER", curses.A_BOLD)
stdscr.refresh()
def main(stdscr):
# 初期設定
curses.curs_set(0)
stdscr.nodelay(True)
stdscr.timeout(100)
game = Tetris()
last_drop = time.time()
drop_interval = 0.5 # ブロックが落ちる速度(秒)
while not game.game_over:
draw_game(stdscr, game)
# キー入力処理
try:
key = stdscr.getch()
except Exception:
key = -1
if key == ord('q') or key == ord('Q'):
break
elif key == ord('a') or key == ord('A'):
game.move(0, -1)
elif key == ord('d') or key == ord('D'):
game.move(0, 1)
elif key == ord('s') or key == ord('S'):
game.move(1, 0)
elif key == ord('w') or key == ord('W'):
game.rotate()
# 時間経過による自動落下
if time.time() - last_drop > drop_interval:
game.move(1, 0)
last_drop = time.time()
# ゲームオーバー時の最終画面表示
draw_game(stdscr, game)
time.sleep(3)
if __name__ == '__main__':
curses.wrapper(main)
To embed this project on your website, copy the following code and paste it into your website's HTML: