26.2.4
touch
Saturday, June 6, 2026
Monday, May 11, 2026
Wednesday, April 29, 2026
Wednesday, April 22, 2026
Thursday, March 12, 2026
Sunday, March 1, 2026
AIサンプル
import pygame
import random
pygame.init()
# ========= サイズ =========
WIDTH, HEIGHT = 20, 40
CELL = 24
HALF = CELL // 2
screen = pygame.display.set_mode((WIDTH * CELL, HEIGHT * CELL))
clock = pygame.time.Clock()
# ========= SRS キック =========
JLSTZ_KICKS = {
(0,1): [(0,0),(-1,0),(-1,1),(0,-2),(-1,-2)],
(1,0): [(0,0),(1,0),(1,-1),(0,2),(1,2)],
(1,2): [(0,0),(1,0),(1,-1),(0,2),(1,2)],
(2,1): [(0,0),(-1,0),(-1,1),(0,-2),(-1,-2)],
(2,3): [(0,0),(1,0),(1,1),(0,-2),(1,-2)],
(3,2): [(0,0),(-1,0),(-1,-1),(0,2),(-1,2)],
(3,0): [(0,0),(-1,0),(-1,-1),(0,2),(-1,2)],
(0,3): [(0,0),(1,0),(1,1),(0,-2),(1,-2)],
}
I_KICKS = {
(0,1): [(0,0),(-2,0),(1,0),(-2,-1),(1,2)],
(1,0): [(0,0),(2,0),(-1,0),(2,1),(-1,-2)],
(1,2): [(0,0),(-1,0),(2,0),(-1,2),(2,-1)],
(2,1): [(0,0),(1,0),(-2,0),(1,-2),(-2,1)],
(2,3): [(0,0),(2,0),(-1,0),(2,1),(-1,-2)],
(3,2): [(0,0),(-2,0),(1,0),(-2,-1),(1,2)],
(3,0): [(0,0),(1,0),(-2,0),(1,-2),(-2,1)],
(0,3): [(0,0),(-1,0),(2,0),(-1,2),(2,-1)],
}
# ========= テトリミノ =========
PIECES = {
"I": {
0: [(0,1),(1,1),(2,1),(3,1)],
1: [(2,0),(2,1),(2,2),(2,3)],
2: [(0,2),(1,2),(2,2),(3,2)],
3: [(1,0),(1,1),(1,2),(1,3)],
},
"O": {
0: [(1,0),(2,0),(1,1),(2,1)],
1: [(1,0),(2,0),(1,1),(2,1)],
2: [(1,0),(2,0),(1,1),(2,1)],
3: [(1,0),(2,0),(1,1),(2,1)],
},
"T": {
0: [(1,0),(0,1),(1,1),(2,1)],
1: [(1,0),(1,1),(2,1),(1,2)],
2: [(0,1),(1,1),(2,1),(1,2)],
3: [(1,0),(0,1),(1,1),(1,2)],
},
"S": {
0: [(1,0),(2,0),(0,1),(1,1)],
1: [(1,0),(1,1),(2,1),(2,2)],
2: [(1,1),(2,1),(0,2),(1,2)],
3: [(0,0),(0,1),(1,1),(1,2)],
},
"Z": {
0: [(0,0),(1,0),(1,1),(2,1)],
1: [(2,0),(1,1),(2,1),(1,2)],
2: [(0,1),(1,1),(1,2),(2,2)],
3: [(1,0),(0,1),(1,1),(0,2)],
},
"J": {
0: [(0,0),(0,1),(1,1),(2,1)],
1: [(1,0),(2,0),(1,1),(1,2)],
2: [(0,1),(1,1),(2,1),(2,2)],
3: [(1,0),(1,1),(0,2),(1,2)],
},
"L": {
0: [(2,0),(0,1),(1,1),(2,1)],
1: [(1,0),(1,1),(1,2),(2,2)],
2: [(0,1),(1,1),(2,1),(0,2)],
3: [(0,0),(1,0),(1,1),(1,2)],
},
}
# ========= ペンタミノ 0° 定義(ここから自動で 4 回転生成) =========
PENTA_BASE = {
"P5": [(0,0),(1,0),(0,1),(1,1),(0,2)],
"P5U": [(0,0),(1,0),(0,1),(1,1),(1,2)],
"X5": [(1,0),(0,1),(1,1),(2,1),(1,2)],
"T5": [(1,0),(0,1),(1,1),(2,1),(1,2)],
"U5": [(0,0),(2,0),(0,1),(1,1),(2,1)],
}
def gen_rotations(shape):
rots = {}
cur = shape
for r in range(4):
min_x = min(x for x, y in cur)
min_y = min(y for x, y in cur)
norm = [(x - min_x, y - min_y) for x, y in cur]
rots[r] = norm
nxt = []
for x, y in cur:
nx = -y
ny = x
nxt.append((nx, ny))
cur = nxt
return rots
for name, base in PENTA_BASE.items():
PIECES[name] = gen_rotations(base)
# ========= 盤面 =========
board = [[0]*WIDTH for _ in range(HEIGHT)]
# ========= 基本関数 =========
def can_place_blocks(blocks, x, y):
for dx, dy in blocks:
nx, ny = x + dx, y + dy
if nx < 0 or nx >= WIDTH or ny < 0 or ny >= HEIGHT:
return False
if board[ny][nx] == 1:
return False
return True
def place_blocks(blocks, x, y):
for dx, dy in blocks:
nx, ny = x + dx, y + dy
board[ny][nx] = 1
def draw(active_blocks, ax, ay, hide=None, falling=None):
screen.fill((0,0,0))
for yy in range(HEIGHT):
for xx in range(WIDTH):
if board[yy][xx] == 1:
if hide and (xx,yy) in hide:
continue
pygame.draw.rect(screen, (0,200,200),
(xx*CELL, yy*CELL, CELL-1, CELL-1))
if falling:
for fx, fy in falling:
pygame.draw.rect(screen, (255,80,80),
(fx*CELL, fy, CELL-1, CELL-1))
if active_blocks:
for dx, dy in active_blocks:
pygame.draw.rect(screen, (200,200,0),
((ax+dx)*CELL, (ay+dy)*CELL, CELL-1, CELL-1))
pygame.display.flip()
# ========= 回転 =========
def rotate_srs(piece_type, rot, x, y):
new_rot = (rot + 1) % 4
blocks_new = PIECES[piece_type][new_rot]
if piece_type == "O":
if can_place_blocks(blocks_new, x, y):
return new_rot, x, y
return rot, x, y
if piece_type in ("I","J","L","S","T","Z"):
kicks = I_KICKS if piece_type == "I" else JLSTZ_KICKS
for ox, oy in kicks.get((rot, new_rot), [(0,0)]):
nx, ny = x + ox, y + oy
if can_place_blocks(blocks_new, nx, ny):
return new_rot, nx, ny
return rot, x, y
if piece_type in ("P5","P5U","X5","T5","U5"):
SIMPLE_KICKS = [
(0,0),(1,0),(-1,0),(0,-1),(0,1),
(1,-1),(-1,-1),(1,1),(-1,1)
]
for ox, oy in SIMPLE_KICKS:
nx, ny = x + ox, y + oy
if can_place_blocks(blocks_new, nx, ny):
return new_rot, nx, ny
return rot, x, y
# ========= 行消し =========
def clear_lines_once():
new_board = []
cleared = []
for y in range(HEIGHT):
if all(board[y]):
cleared.append(y)
else:
new_board.append(board[y])
if not cleared:
return []
while len(new_board) < HEIGHT:
new_board.insert(0, [0]*WIDTH)
for y in range(HEIGHT):
board[y] = new_board[y]
return cleared
# ========= 縦穴落下アニメーション =========
def cascade_animation(cleared, active_blocks, ax, ay):
if not cleared:
return
bottom = max(cleared)
target = bottom + 1
if target >= HEIGHT:
return
fall_cols = []
segments = {}
for x in range(WIDTH):
if board[target][x] != 0:
continue
ys = []
for y in range(target-1, -1, -1):
if board[y][x] == 1:
ys.append(y)
else:
break
if 1 <= len(ys) <= 4:
ys.sort()
fall_cols.append(x)
segments[x] = ys
if not fall_cols:
return
fall_info = {}
hide = set()
for x in fall_cols:
ys = segments[x]
for y in ys:
hide.add((x,y))
y_bottom = ys[-1]
stop_row = HEIGHT - 1
for yy in range(y_bottom+1, HEIGHT):
if board[yy][x] == 1:
stop_row = yy - 1
break
h = len(ys)
final_rows = list(range(stop_row - h + 1, stop_row + 1))
fall_info[x] = []
for y, fr in zip(ys, final_rows):
fall_info[x].append({
"x": x,
"start": y*CELL,
"cur": y*CELL,
"end": fr*CELL
})
anim = True
while anim:
anim = False
falling_blocks = []
pygame.event.pump()
for x in fall_cols:
for b in fall_info[x]:
if b["cur"] < b["end"]:
b["cur"] = min(b["cur"] + HALF, b["end"])
anim = True
falling_blocks.append((b["x"], b["cur"]))
draw(None, 0, 0, hide=hide, falling=falling_blocks)
pygame.time.delay(50)
for x in fall_cols:
ys = segments[x]
for y in ys:
board[y][x] = 0
for b in fall_info[x]:
final_row = b["end"] // CELL
board[final_row][x] = 1
draw(None, 0, 0)
pygame.time.delay(80)
# ========= せり上がり =========
def rise_shift_animation():
global rise_hole_x, rise_dir, rise_same_count
new_row = [1] * WIDTH
new_row[rise_hole_x] = 0
for y in range(HEIGHT - 1):
board[y] = board[y + 1][:]
board[HEIGHT - 1] = new_row
rise_same_count += 1
if rise_same_count >= 5:
rise_same_count = 0
rise_hole_x += rise_dir
if rise_hole_x <= 0:
rise_hole_x = 0
rise_dir = 1
elif rise_hole_x >= WIDTH - 1:
rise_hole_x = WIDTH - 1
rise_dir = -1
draw(None, 0, 0)
pygame.time.delay(120)
# ========= 行消し後の処理 =========
def resolve_all(active_blocks, ax, ay):
while True:
cleared = clear_lines_once()
if not cleared:
break
draw(None, 0, 0)
pygame.time.delay(150)
cascade_animation(cleared, active_blocks, ax, ay)
rise_shift_animation()
# ========= 初期 5 行の地面 =========
def init_ground_rows():
global rise_hole_x, rise_dir, rise_same_count
rise_hole_x = WIDTH // 2
rise_dir = 1
rise_same_count = 5
for i in range(5):
new_row = [1] * WIDTH
new_row[rise_hole_x] = 0
board[HEIGHT - 1 - i] = new_row[:]
# ========= 新しいミノ =========
def new_piece():
ptype = random.choice(list(PIECES.keys()))
rot = 0
x = WIDTH // 2 - 2
y = 0
return ptype, rot, x, y
# ========= 初期化 =========
init_ground_rows()
piece_type, rot, x_pos, y_pos = new_piece()
fall_timer = 0
move_cd = 0
rot_cd = 0
# ========= メインループ =========
running = True
while running:
clock.tick(60)
fall_timer += 1
move_cd = max(0, move_cd - 1)
rot_cd = max(0, rot_cd - 1)
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
active_blocks = PIECES[piece_type][rot]
keys = pygame.key.get_pressed()
# --- 左右移動 ---
if move_cd == 0:
if keys[pygame.K_LEFT] and can_place_blocks(active_blocks, x_pos - 1, y_pos):
x_pos -= 1
move_cd = 8
if keys[pygame.K_RIGHT] and can_place_blocks(active_blocks, x_pos + 1, y_pos):
x_pos += 1
move_cd = 8
# --- 回転 ---
if rot_cd == 0 and (keys[pygame.K_UP] or keys[pygame.K_SPACE]):
new_rot, nx, ny = rotate_srs(piece_type, rot, x_pos, y_pos)
rot, x_pos, y_pos = new_rot, nx, ny
rot_cd = 12
# --- 下移動(ソフトドロップ) ---
if keys[pygame.K_DOWN] and can_place_blocks(active_blocks, x_pos, y_pos + 1):
y_pos += 1
# --- 自動落下 ---
if fall_timer >= 30:
fall_timer = 0
if can_place_blocks(active_blocks, x_pos, y_pos + 1):
y_pos += 1
else:
place_blocks(active_blocks, x_pos, y_pos)
resolve_all(active_blocks, x_pos, y_pos)
piece_type, rot, x_pos, y_pos = new_piece()
if not can_place_blocks(PIECES[piece_type][rot], x_pos, y_pos):
print("GAME OVER")
running = False
draw(PIECES[piece_type][rot], x_pos, y_pos)
pygame.quit()
Subscribe to:
Posts (Atom)