728x90
import pygame
import sys
import random
# -------------------- Configuration --------------------
BOARD_SIZE = 9 # 9x9 board for simplicity
CELL_SIZE = 60 # Distance between intersections (in pixels)
MARGIN = 40 # Margin around the board (in pixels)
WINDOW_SIZE = MARGIN * 2 + CELL_SIZE * (BOARD_SIZE - 1)
FPS = 30 # Frames per second
# Board representation:
# 0 -> empty, 1 -> Black (human), 2 -> White (computer)
# -------------------- Helper Functions --------------------
def get_neighbors(row, col, board_size):
"""Return adjacent board coordinates (up, down, left, right)."""
neighbors = []
if row > 0:
neighbors.append((row - 1, col))
if row < board_size - 1:
neighbors.append((row + 1, col))
if col > 0:
neighbors.append((row, col - 1))
if col < board_size - 1:
neighbors.append((row, col + 1))
return neighbors
def get_group_and_liberties(board, row, col):
"""
Given a board and a starting position, return the full group of connected
stones (same color) and a set of adjacent empty positions (liberties).
"""
color = board[row][col]
group = set()
liberties = set()
stack = [(row, col)]
while stack:
r, c = stack.pop()
if (r, c) in group:
continue
group.add((r, c))
for nr, nc in get_neighbors(r, c, len(board)):
if board[nr][nc] == 0:
liberties.add((nr, nc))
elif board[nr][nc] == color and (nr, nc) not in group:
stack.append((nr, nc))
return group, liberties
def remove_group(board, group):
"""Remove a captured group of stones from the board."""
for r, c in group:
board[r][c] = 0
def apply_move(board, row, col, color):
"""
Try to apply a move for the given color at (row, col).
Returns a new board state if the move is legal (after removing any captures),
or None if the move is illegal.
"""
# Copy the board to simulate the move.
new_board = [r[:] for r in board]
if new_board[row][col] != 0:
return None # The cell is already occupied.
new_board[row][col] = color
enemy_color = 2 if color == 1 else 1
# Check enemy neighbors for possible capture.
for nr, nc in get_neighbors(row, col, len(board)):
if new_board[nr][nc] == enemy_color:
group, liberties = get_group_and_liberties(new_board, nr, nc)
if len(liberties) == 0:
remove_group(new_board, group)
# Check if the newly placed stone's group has any liberties.
group, liberties = get_group_and_liberties(new_board, row, col)
if len(liberties) == 0:
# Illegal move (suicide) if no liberties remain.
return None
return new_board
def get_all_legal_moves(board, color):
"""Return a list of all legal moves (row, col) for the given color."""
moves = []
for r in range(len(board)):
for c in range(len(board)):
if board[r][c] == 0:
new_board = apply_move(board, r, c, color)
if new_board is not None:
moves.append((r, c))
return moves
def computer_move(board, color):
"""Compute a legal move for the computer (random selection)."""
legal_moves = get_all_legal_moves(board, color)
if legal_moves:
move = random.choice(legal_moves)
new_board = apply_move(board, move[0], move[1], color)
return new_board, move
else:
return board, None # No legal move; the computer passes.
def pixel_to_board(x, y):
"""
Convert pixel coordinates (x, y) to the nearest board intersection.
Returns (row, col) or None if outside the board area.
"""
board_col = round((x - MARGIN) / CELL_SIZE)
board_row = round((y - MARGIN) / CELL_SIZE)
if board_col < 0 or board_col >= BOARD_SIZE or board_row < 0 or board_row >= BOARD_SIZE:
return None
# Compute the exact center of the intersection.
center_x = MARGIN + board_col * CELL_SIZE
center_y = MARGIN + board_row * CELL_SIZE
# Check if the click is close enough.
if abs(x - center_x) < CELL_SIZE / 2 and abs(y - center_y) < CELL_SIZE / 2:
return board_row, board_col
return None
def draw_board(screen, board):
"""Render the Go board and stones."""
# Fill the background with a wood-like color.
screen.fill((222, 184, 135))
# Draw grid lines.
for i in range(BOARD_SIZE):
start_pos = (MARGIN, MARGIN + i * CELL_SIZE)
end_pos = (MARGIN + (BOARD_SIZE - 1) * CELL_SIZE, MARGIN + i * CELL_SIZE)
pygame.draw.line(screen, (0, 0, 0), start_pos, end_pos, 2)
for j in range(BOARD_SIZE):
start_pos = (MARGIN + j * CELL_SIZE, MARGIN)
end_pos = (MARGIN + j * CELL_SIZE, MARGIN + (BOARD_SIZE - 1) * CELL_SIZE)
pygame.draw.line(screen, (0, 0, 0), start_pos, end_pos, 2)
# Draw stones.
for r in range(BOARD_SIZE):
for c in range(BOARD_SIZE):
if board[r][c] != 0:
center = (MARGIN + c * CELL_SIZE, MARGIN + r * CELL_SIZE)
if board[r][c] == 1:
stone_color = (0, 0, 0)
else:
stone_color = (255, 255, 255)
pygame.draw.circle(screen, stone_color, center, CELL_SIZE // 2 - 2)
# Add a black outline for white stones.
if board[r][c] == 2:
pygame.draw.circle(screen, (0, 0, 0), center, CELL_SIZE // 2 - 2, 2)
pygame.display.flip()
# -------------------- Main Game Loop --------------------
def main():
pygame.init()
screen = pygame.display.set_mode((WINDOW_SIZE, WINDOW_SIZE))
pygame.display.set_caption("Local Go (Baduk) Game")
clock = pygame.time.Clock()
# Initialize an empty board.
board = [[0 for _ in range(BOARD_SIZE)] for _ in range(BOARD_SIZE)]
current_player = 1 # 1 for human (Black), 2 for computer (White)
running = True
while running:
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.MOUSEBUTTONDOWN:
# Human (Black) makes a move.
if current_player == 1:
pos = pygame.mouse.get_pos()
move = pixel_to_board(pos[0], pos[1])
if move:
r, c = move
new_board = apply_move(board, r, c, current_player)
if new_board is not None:
board = new_board
current_player = 2
else:
print("Illegal move!")
# Computer (White) makes a move.
if current_player == 2:
pygame.time.wait(500) # Pause briefly for a natural feel.
board, comp_move = computer_move(board, current_player)
if comp_move is not None:
print(f"Computer played at {comp_move}")
else:
print("Computer passes (no legal moves).")
current_player = 1
draw_board(screen, board)
clock.tick(FPS)
pygame.quit()
sys.exit()
if __name__ == '__main__':
main()
728x90
'hacking sorcerer' 카테고리의 다른 글
over the pil in one second (0) | 2025.02.28 |
---|---|
피아노 게임 (0) | 2025.02.25 |
한글 키보드 냠해요 (initial하게 만든 거라 약간 오류 있을 수 있어용) (0) | 2025.02.04 |
자~ 골라요 골라 (0) | 2025.01.21 |
수학을 한다는 거 (0) | 2024.11.26 |