콘텐츠로 이동

Board

Board 클래스는 테트리스 게임 보드의 상태를 관리하고, 충돌 감지, 줄 클리어, 특징 계산 등의 기능을 제공합니다.

API Reference

Board

Board(height: int = 20, width: int = 10)

Manages the Tetris game board state and operations.

Responsibilities: - Board state management (initialization, copying) - Collision detection - Line clearing - Feature extraction (holes, bumpiness, height)

Initialize a new board.

Parameters:

Name Type Description Default
height int

Number of rows in the board

20
width int

Number of columns in the board

10
Source code in rl_tetris/core/board.py
def __init__(self, height: int = 20, width: int = 10):
    """
    Initialize a new board.

    Args:
        height: Number of rows in the board
        width: Number of columns in the board
    """
    self.height = height
    self.width = width
    self._state = None
    self.reset()

reset

reset() -> None

Reset the board to an empty state.

Source code in rl_tetris/core/board.py
def reset(self) -> None:
    """Reset the board to an empty state."""
    self._state = [[0] * self.width for _ in range(self.height)]

get_state

get_state() -> List[List[int]]

Get a copy of the current board state.

Returns:

Type Description
List[List[int]]

A deep copy of the board state

Source code in rl_tetris/core/board.py
def get_state(self) -> List[List[int]]:
    """
    Get a copy of the current board state.

    Returns:
        A deep copy of the board state
    """
    return [row[:] for row in self._state]

set_state

set_state(state: List[List[int]]) -> None

Set the board state.

Parameters:

Name Type Description Default
state List[List[int]]

The new board state

required
Source code in rl_tetris/core/board.py
def set_state(self, state: List[List[int]]) -> None:
    """
    Set the board state.

    Args:
        state: The new board state
    """
    if len(state) != self.height or any(len(row) != self.width for row in state):
        raise ValueError(f"Invalid board state dimensions. Expected {self.height}x{self.width}")
    self._state = [row[:] for row in state]

check_collision

check_collision(piece_shape: List[List[int]], x: int, y: int) -> bool

Check if placing a piece at the given position would cause a collision.

Parameters:

Name Type Description Default
piece_shape List[List[int]]

2D array representing the piece shape

required
x int

Column position of the piece's top-left corner

required
y int

Row position of the piece's top-left corner

required

Returns:

Type Description
bool

True if collision occurs, False otherwise

Source code in rl_tetris/core/board.py
def check_collision(self, piece_shape: List[List[int]], x: int, y: int) -> bool:
    """
    Check if placing a piece at the given position would cause a collision.

    Args:
        piece_shape: 2D array representing the piece shape
        x: Column position of the piece's top-left corner
        y: Row position of the piece's top-left corner

    Returns:
        True if collision occurs, False otherwise
    """
    for py in range(len(piece_shape)):
        for px in range(len(piece_shape[py])):
            # Skip empty cells in the piece
            if piece_shape[py][px] == 0:
                continue

            board_x = x + px
            board_y = y + py

            # Check boundaries
            if not self.is_valid_position(board_x, board_y):
                return True

            # Check if cell is already occupied
            if self._state[board_y][board_x] > 0:
                return True

    return False

place_piece

place_piece(piece_shape: List[List[int]], x: int, y: int) -> None

Place a piece on the board (modifies board state).

Parameters:

Name Type Description Default
piece_shape List[List[int]]

2D array representing the piece shape

required
x int

Column position of the piece's top-left corner

required
y int

Row position of the piece's top-left corner

required
Source code in rl_tetris/core/board.py
def place_piece(self, piece_shape: List[List[int]], x: int, y: int) -> None:
    """
    Place a piece on the board (modifies board state).

    Args:
        piece_shape: 2D array representing the piece shape
        x: Column position of the piece's top-left corner
        y: Row position of the piece's top-left corner
    """
    for py in range(len(piece_shape)):
        for px in range(len(piece_shape[py])):
            if piece_shape[py][px] > 0:
                board_y = y + py
                board_x = x + px
                if self.is_valid_position(board_x, board_y):
                    if self._state[board_y][board_x] == 0:
                        self._state[board_y][board_x] = piece_shape[py][px]

clear_full_rows

clear_full_rows() -> int

Clear all full rows from the board and return the number cleared.

Returns:

Type Description
int

Number of rows cleared

Source code in rl_tetris/core/board.py
def clear_full_rows(self) -> int:
    """
    Clear all full rows from the board and return the number cleared.

    Returns:
        Number of rows cleared
    """
    rows_to_delete = []
    for i, row in enumerate(self._state):
        if 0 not in row:
            rows_to_delete.append(i)

    if rows_to_delete:
        self._remove_rows(rows_to_delete)

    return len(rows_to_delete)

get_holes

get_holes() -> int

Count the number of holes in the board. A hole is an empty cell with at least one filled cell above it.

Returns:

Type Description
int

Number of holes

Source code in rl_tetris/core/board.py
def get_holes(self) -> int:
    """
    Count the number of holes in the board.
    A hole is an empty cell with at least one filled cell above it.

    Returns:
        Number of holes
    """
    num_holes = 0
    for col_idx in range(self.width):
        # Find first filled cell in column
        row = 0
        while row < self.height and self._state[row][col_idx] == 0:
            row += 1

        # Count empty cells below first filled cell
        for check_row in range(row + 1, self.height):
            if self._state[check_row][col_idx] == 0:
                num_holes += 1

    return num_holes

get_bumpiness_and_height

get_bumpiness_and_height() -> Tuple[int, int]

Calculate the bumpiness and total height of the board.

Bumpiness is the sum of absolute differences between adjacent column heights. Total height is the sum of all column heights.

Returns:

Type Description
Tuple[int, int]

Tuple of (bumpiness, total_height)

Source code in rl_tetris/core/board.py
def get_bumpiness_and_height(self) -> Tuple[int, int]:
    """
    Calculate the bumpiness and total height of the board.

    Bumpiness is the sum of absolute differences between adjacent column heights.
    Total height is the sum of all column heights.

    Returns:
        Tuple of (bumpiness, total_height)
    """
    board_array = np.array(self._state)
    mask = board_array != 0

    # Calculate height of each column
    # If column has any filled cell, height = height - first_filled_row
    # Otherwise height = 0
    invert_heights = np.where(
        mask.any(axis=0),
        np.argmax(mask, axis=0),
        self.height
    )
    heights = self.height - invert_heights

    total_height = np.sum(heights)

    # Calculate bumpiness (sum of absolute height differences)
    if len(heights) > 1:
        diffs = np.abs(heights[:-1] - heights[1:])
        total_bumpiness = np.sum(diffs)
    else:
        total_bumpiness = 0

    return int(total_bumpiness), int(total_height)

get_column_heights

get_column_heights() -> List[int]

Get the height of each column.

Returns:

Type Description
List[int]

List of column heights

Source code in rl_tetris/core/board.py
def get_column_heights(self) -> List[int]:
    """
    Get the height of each column.

    Returns:
        List of column heights
    """
    board_array = np.array(self._state)
    mask = board_array != 0
    invert_heights = np.where(
        mask.any(axis=0),
        np.argmax(mask, axis=0),
        self.height
    )
    heights = self.height - invert_heights
    return heights.tolist()

Usage Examples

기본 사용법

from rl_tetris.core import Board, Piece

# 보드 생성 (20x10)
board = Board(height=20, width=10)
board.reset()

# 피스 생성
piece = Piece(piece_type=0)  # I 피스

# 충돌 검사
can_place = not board.check_collision(piece, x=5, y=18)
if can_place:
    board.place_piece(piece, x=5, y=18)

# 줄 클리어
lines_cleared = board.clear_full_rows()
print(f"Cleared {lines_cleared} lines")

특징 추출

# 보드 특징 계산
holes = board.get_holes()
bumpiness, height = board.get_bumpiness_and_height()
heights = board.get_column_heights()

print(f"Holes: {holes}")
print(f"Bumpiness: {bumpiness}")
print(f"Total Height: {height}")
print(f"Column Heights: {heights}")

상태 관리

# 상태 저장/복원
saved_state = board.get_state()
# ... 게임 진행 ...
board.set_state(saved_state)  # 이전 상태로 복원

See Also