TetrisRL/game.py

180 lines
5.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import random
BLOCK_FILL_LOC = [
[[9, 10, 12, 13], [4, 8, 9, 13]],
[[8, 9, 13, 14], [5, 8, 9, 12]],
[[8, 12, 13, 14], [4, 5, 8, 12], [8, 9, 10, 14], [5, 9, 12, 13]],
[[10, 12, 13, 14], [4, 8, 12, 13], [8, 9, 10, 12], [4, 5, 9, 13]],
[[9, 12, 13, 14], [4, 8, 9, 12], [8, 9, 10, 13], [5, 8, 9, 13]],
[[8, 9, 12, 13]],
[[12, 13, 14, 15], [1, 5, 9, 13]]
]
class Board():
'''
|
--|-------------
0 | |----
| |
| |
|
|
19 |
'''
def __init__(self) -> None:
self.block = [[0 for _ in range(10)] for _ in range(20)]
def place(self, block):
'''
把現在的方塊擺進去 board代表確定方塊位置了
'''
self.block = view(self, block)
def checkScore(self) -> int:
'''
檢查是否有連線,並回傳該動作得到的分數
'''
score = 0
for row in range(20):
flag = True
for col in range(10):
if self.block[row][col] == 0:
flag = False
break
if flag:
score += 1
self.block[0] = [0 for i in range(10)]
for updateRow in range(row, 0, -1):
self.block[updateRow] = self.block[updateRow-1]
return score
class Block():
def __init__(self, block_id:int, board:Board) -> None:
self.block_id = block_id
self.x, self.y = 3, -2
self.status = 0
self.block = [[0 for i in range(4)] for i in range(4)]
self.board = board
self.update()
def reset(self):
block_id = random.randint(0, 6)
self.__init__(block_id, self.board)
def update(self):
id = self.block_id
status = self.status
block = [[0 for i in range(4)] for i in range(4)]
counter = 0
for i in range(4):
for j in range(4):
if counter in BLOCK_FILL_LOC[id][status]:
block[i][j] = 1
counter += 1
self.block = block
def show(self) -> None:
for i in range(4):
for j in range(4):
if self.block[i][j]:
print('', end='')
else:
print('', end='')
print()
def rotate(self) -> None:
self.status = (self.status+1)%len(BLOCK_FILL_LOC[self.block_id])
self.update()
if(isCollision(self, self.board)):
self.status = (self.status-1)%len(BLOCK_FILL_LOC[self.block_id])
self.update()
return False
else:
return True
def fall(self) -> bool:
self.y += 1
if(isCollision(self, self.board)):
self.y -= 1
self.board.place(self)
self.reset()
if(isCollision(self, self.board)):
raise Exception("GAME OVER")
return False
else:
return True
def shiftRight(self) -> bool:
self.x += 1
if(isCollision(self, self.board)):
self.x -= 1
return False
else:
return True
def shiftLeft(self) -> bool:
self.x -= 1
if(isCollision(self, self.board)):
self.x += 1 # 修正
return False
else:
return True
class TetrisGame():
def __init__(self) -> None:
block_id = random.randint(0, 6)
self.board = Board()
self.block = Block(block_id, self.board)
self.score = 0
self.done = False
def action(self, mode):
if mode == 'd':
try:
self.block.fall()
except:
print("GAME OVER")
self.done = True
elif mode == 'l':
self.block.shiftLeft()
elif mode == 'r':
self.block.shiftRight()
elif mode == 'f':
self.block.rotate()
self.score += self.board.checkScore()
def view(self):
return view(self.board, self.block)
def view(board:Board, block:Block) -> list:
views = []
for row in board.block:
views.append([])
for col in row:
views[-1].append(col)
for onBlockY in range(4):
onBoardY = block.y+onBlockY
if onBoardY >= 0:
for onBlockX in range(4):
onBoardX = block.x+onBlockX
if onBoardX >= 10:
break
if block.block[onBlockY][onBlockX] == 1:
views[onBoardY][onBoardX] = 1
return views
def isCollision(block:Block, board:Board) -> bool:
for onBlockY in range(4):
onBoardY = block.y+onBlockY
for onBlockX in range(4):
onBoardX = block.x+onBlockX
if block.block[onBlockY][onBlockX]==1:
if onBoardX >= 10 or onBoardX < 0 or onBoardY >= 20 or onBoardY < 0:
return True
if board.block[onBoardY][onBoardX]==1:
return True
return False