aW1wb3J0IHB5Z2FtZQppbXBvcnQgcmFuZG9tCgojIOioreWumgpTQ1JFRU5fV0lEVEgsIFNDUkVFTl9IRUlHSFQgPSAzMDAsIDYwMApCTE9DS19TSVpFID0gMzAKQ09MVU1OUywgUk9XUyA9IFNDUkVFTl9XSURUSCAvLyBCTE9DS19TSVpFLCBTQ1JFRU5fSEVJR0hUIC8vIEJMT0NLX1NJWkUKCiMg44Of44OO44Gu5b2i77yI5bqn5qiZ77yJClNIQVBFUyA9IFsKICAgIFtbMSwgMSwgMSwgMV1dLCAjIEkKICAgIFtbMSwgMV0sIFsxLCAxXV0sICMgTwogICAgW1swLCAxLCAwXSwgWzEsIDEsIDFdXSwgIyBUCiAgICBbWzEsIDEsIDBdLCBbMCwgMSwgMV1dLCAjIFMKICAgIFtbMCwgMSwgMV0sIFsxLCAxLCAwXV0sICMgWgpdCgpjbGFzcyBUZXRyaXM6CiAgICBkZWYgX19pbml0X18oc2VsZik6CiAgICAgICAgc2VsZi5ncmlkID0gW1swIGZvciBfIGluIHJhbmdlKENPTFVNTlMpXSBmb3IgXyBpbiByYW5nZShST1dTKV0KICAgICAgICBzZWxmLm5ld19waWVjZSgpCgogICAgZGVmIG5ld19waWVjZShzZWxmKToKICAgICAgICBzZWxmLnNoYXBlID0gcmFuZG9tLmNob2ljZShTSEFQRVMpCiAgICAgICAgc2VsZi5jb2xvciA9IChyYW5kb20ucmFuZGludCg1MCwgMjU1KSwgcmFuZG9tLnJhbmRpbnQoNTAsIDI1NSksIHJhbmRvbS5yYW5kaW50KDUwLCAyNTUpKQogICAgICAgIHNlbGYueCwgc2VsZi55ID0gQ09MVU1OUyAvLyAyIC0gbGVuKHNlbGYuc2hhcGVbMF0pIC8vIDIsIDAKCiAgICBkZWYgbW92ZShzZWxmLCBkeCwgZHkpOgogICAgICAgIGlmIG5vdCBzZWxmLmNoZWNrX2NvbGxpc2lvbihzZWxmLnggKyBkeCwgc2VsZi55ICsgZHkpOgogICAgICAgICAgICBzZWxmLnggKz0gZHgKICAgICAgICAgICAgc2VsZi55ICs9IGR5CiAgICAgICAgICAgIHJldHVybiBUcnVlCiAgICAgICAgcmV0dXJuIEZhbHNlCgogICAgZGVmIGNoZWNrX2NvbGxpc2lvbihzZWxmLCBueCwgbnkpOgogICAgICAgIGZvciByLCByb3cgaW4gZW51bWVyYXRlKHNlbGYuc2hhcGUpOgogICAgICAgICAgICBmb3IgYywgdmFsIGluIGVudW1lcmF0ZShyb3cpOgogICAgICAgICAgICAgICAgaWYgdmFsOgogICAgICAgICAgICAgICAgICAgIGlmIG54ICsgYyAmbHQ7IDAgb3IgbnggKyBjICZndDs9IENPTFVNTlMgb3IgbnkgKyByICZndDs9IFJPV1Mgb3Igc2VsZi5ncmlkW255ICsgcl1bbnggKyBjXToKICAgICAgICAgICAgICAgICAgICAgICAgcmV0dXJuIFRydWUKICAgICAgICByZXR1cm4gRmFsc2UKCiAgICBkZWYgZnJlZXplKHNlbGYpOgogICAgICAgIGZvciByLCByb3cgaW4gZW51bWVyYXRlKHNlbGYuc2hhcGUpOgogICAgICAgICAgICBmb3IgYywgdmFsIGluIGVudW1lcmF0ZShyb3cpOgogICAgICAgICAgICAgICAgaWYgdmFsOiBzZWxmLmdyaWRbc2VsZi55ICsgcl1bc2VsZi54ICsgY10gPSBzZWxmLmNvbG9yCiAgICAgICAgc2VsZi5jbGVhcl9yb3dzKCkKICAgICAgICBzZWxmLm5ld19waWVjZSgpCgogICAgZGVmIGNsZWFyX3Jvd3Moc2VsZik6CiAgICAgICAgc2VsZi5ncmlkID0gW3JvdyBmb3Igcm93IGluIHNlbGYuZ3JpZCBpZiBhbnkodiA9PSAwIGZvciB2IGluIHJvdyldCiAgICAgICAgd2hpbGUgbGVuKHNlbGYuZ3JpZCkgJmx0OyBST1dTOgogICAgICAgICAgICBzZWxmLmdyaWQuaW5zZXJ0KDAsIFswIGZvciBfIGluIHJhbmdlKENPTFVNTlMpXSkKCmRlZiBtYWluKCk6CiAgICBweWdhbWUuaW5pdCgpCiAgICBzY3JlZW4gPSBweWdhbWUuZGlzcGxheS5zZXRfbW9kZSgoU0NSRUVOX1dJRFRILCBTQ1JFRU5fSEVJR0hUKSkKICAgIGNsb2NrID0gcHlnYW1lLnRpbWUuQ2xvY2soKQogICAgZ2FtZSA9IFRldHJpcygpCiAgICBkcm9wX3RpbWUgPSAwCgogICAgd2hpbGUgVHJ1ZToKICAgICAgICBzY3JlZW4uZmlsbCgoMCwgMCwgMCkpCiAgICAgICAgZHJvcF90aW1lICs9IGNsb2NrLmdldF9yYXd0aW1lKCkKICAgICAgICBjbG9jay50aWNrKCkKCiAgICAgICAgaWYgZHJvcF90aW1lICZndDsgNTAwOiAjIDAuNeenkuOBlOOBqOOBq+iQveS4iwogICAgICAgICAgICBpZiBub3QgZ2FtZS5tb3ZlKDAsIDEpOiBnYW1lLmZyZWV6ZSgpCiAgICAgICAgICAgIGRyb3BfdGltZSA9IDAKCiAgICAgICAgZm9yIGV2ZW50IGluIHB5Z2FtZS5ldmVudC5nZXQoKToKICAgICAgICAgICAgaWYgZXZlbnQudHlwZSA9PSBweWdhbWUuUVVJVDogcmV0dXJuCiAgICAgICAgICAgIGlmIGV2ZW50LnR5cGUgPT0gcHlnYW1lLktFWURPV046CiAgICAgICAgICAgICAgICBpZiBldmVudC5rZXkgPT0gcHlnYW1lLktfTEVGVDogZ2FtZS5tb3ZlKC0xLCAwKQogICAgICAgICAgICAgICAgaWYgZXZlbnQua2V5ID09IHB5Z2FtZS5LX1JJR0hUOiBnYW1lLm1vdmUoMSwgMCkKICAgICAgICAgICAgICAgIGlmIGV2ZW50LmtleSA9PSBweWdhbWUuS19ET1dOOiBnYW1lLm1vdmUoMCwgMSkKCiAgICAgICAgIyDmj4/nlLsKICAgICAgICBmb3Igciwgcm93IGluIGVudW1lcmF0ZShnYW1lLmdyaWQpOgogICAgICAgICAgICBmb3IgYywgdmFsIGluIGVudW1lcmF0ZShyb3cpOgogICAgICAgICAgICAgICAgaWYgdmFsOiBweWdhbWUuZHJhdy5yZWN0KHNjcmVlbiwgdmFsLCAoYypCTE9DS19TSVpFLCByKkJMT0NLX1NJWkUsIEJMT0NLX1NJWkUtMSwgQkxPQ0tfU0laRS0xKSkKICAgICAgICBmb3Igciwgcm93IGluIGVudW1lcmF0ZShnYW1lLnNoYXBlKToKICAgICAgICAgICAgZm9yIGMsIHZhbCBpbiBlbnVtZXJhdGUocm93KToKICAgICAgICAgICAgICAgIGlmIHZhbDogcHlnYW1lLmRyYXcucmVjdChzY3JlZW4sIGdhbWUuY29sb3IsICgoZ2FtZS54K2MpKkJMT0NLX1NJWkUsIChnYW1lLnkrcikqQkxPQ0tfU0laRSwgQkxPQ0tfU0laRS0xLCBCTE9DS19TSVpFLTEpKQogICAgICAgIAogICAgICAgIHB5Z2FtZS5kaXNwbGF5LmZsaXAoKQoKaWYgX19uYW1lX18gPT0gJnF1b3Q7X19tYWluX18mcXVvdDs6CiAgICBtYWluKCkK
import pygame
import random
# 設定
SCREEN_WIDTH, SCREEN_HEIGHT = 300, 600
BLOCK_SIZE = 30
COLUMNS, ROWS = SCREEN_WIDTH // BLOCK_SIZE, SCREEN_HEIGHT // BLOCK_SIZE
# ミノの形(座標)
SHAPES = [
[[1, 1, 1, 1]], # I
[[1, 1], [1, 1]], # O
[[0, 1, 0], [1, 1, 1]], # T
[[1, 1, 0], [0, 1, 1]], # S
[[0, 1, 1], [1, 1, 0]], # Z
]
class Tetris:
def __init__(self):
self.grid = [[0 for _ in range(COLUMNS)] for _ in range(ROWS)]
self.new_piece()
def new_piece(self):
self.shape = random.choice(SHAPES)
self.color = (random.randint(50, 255), random.randint(50, 255), random.randint(50, 255))
self.x, self.y = COLUMNS // 2 - len(self.shape[0]) // 2, 0
def move(self, dx, dy):
if not self.check_collision(self.x + dx, self.y + dy):
self.x += dx
self.y += dy
return True
return False
def check_collision(self, nx, ny):
for r, row in enumerate(self.shape):
for c, val in enumerate(row):
if val:
if nx + c < 0 or nx + c >= COLUMNS or ny + r >= ROWS or self.grid[ny + r][nx + c]:
return True
return False
def freeze(self):
for r, row in enumerate(self.shape):
for c, val in enumerate(row):
if val: self.grid[self.y + r][self.x + c] = self.color
self.clear_rows()
self.new_piece()
def clear_rows(self):
self.grid = [row for row in self.grid if any(v == 0 for v in row)]
while len(self.grid) < ROWS:
self.grid.insert(0, [0 for _ in range(COLUMNS)])
def main():
pygame.init()
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
clock = pygame.time.Clock()
game = Tetris()
drop_time = 0
while True:
screen.fill((0, 0, 0))
drop_time += clock.get_rawtime()
clock.tick()
if drop_time > 500: # 0.5秒ごとに落下
if not game.move(0, 1): game.freeze()
drop_time = 0
for event in pygame.event.get():
if event.type == pygame.QUIT: return
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT: game.move(-1, 0)
if event.key == pygame.K_RIGHT: game.move(1, 0)
if event.key == pygame.K_DOWN: game.move(0, 1)
# 描画
for r, row in enumerate(game.grid):
for c, val in enumerate(row):
if val: pygame.draw.rect(screen, val, (c*BLOCK_SIZE, r*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1))
for r, row in enumerate(game.shape):
for c, val in enumerate(row):
if val: pygame.draw.rect(screen, game.color, ((game.x+c)*BLOCK_SIZE, (game.y+r)*BLOCK_SIZE, BLOCK_SIZE-1, BLOCK_SIZE-1))
pygame.display.flip()
if __name__ == "__main__":
main()