棋盘的types设计,设计了棋手和点位;棋手是为了区分先手后手,敌方我方;比如后手固定是黑棋或者是位于棋盘下方的棋手,我这里约定为统一先手为“执黑方“;敌方拿到棋盘的时候,如果设计的是从对方手上获得, 那么需要根据player来确定是否要翻转棋局。
import enum
from collections import namedtuple
__all__ = [
'Player',
'Point',
]
class Player(enum.Enum):
black = 0
white = 1
@property
def other(self):
return Player.black if self == Player.white else Player.white
def __str__(self):
return 'black' if self == Player.black else 'white'
# Point class is used to represent a location on the board.
class Point(namedtuple('Point', 'row col')):
pass
棋盘的board、move、gamestate设计:
import numpy as np
import copy
from amazontypes import Player, Point
# class IllegalMoveError(Exception):
# pass
class IllegalMoveError(Exception):
def __init__(self, message="Illegal move attempted", *args):
super(IllegalMoveError, self).__init__(message, *args) # Correct usage of super in Python 2
self.message = message # Store the message in an instance variable
def __str__(self):
# This method returns the string representation of the error, which will be used when the error is printed
return self.message
class Board:
def __init__(self, size=10):
self.size = size
self.board = np.zeros((3, size, size), dtype=int)
self.init_amazons_positions()
self.stage = 0
self.selected_amazon = None
def init_amazons_positions(self):
positions = [Point(1, 4), Point(1, 7), Point(4, 1), Point(4, 10),
Point(7, 1), Point(7, 10), Point(10, 4), Point(10, 7)]
for i, pos in enumerate(positions):
self.board[0 if i < 4 else 1, pos.row - 1, pos.col - 1] = 1
def select_amazon(self, point):
if self.stage != 0:
raise IllegalMoveError("Not in the selection stage")
if self.board[0, point.row - 1, point.col - 1] != 1:
raise IllegalMoveError("No amazon at selected position")
self.selected_amazon = point
self.stage = 1
def move_amazon(self, point):
if self.stage != 1:
raise IllegalMoveError("Not in the move stage")
if not self.is_queen_move(self.selected_amazon, point):
raise IllegalMoveError("Invalid move for amazon")
self.board[0, self.selected_amazon.row - 1, self.selected_amazon.col - 1] = 0
self.board[0, point.row - 1, point.col - 1] = 1
self.selected_amazon = point
self.stage = 2
def place_obstacle(self, point):
if self.stage != 2:
raise IllegalMoveError("Not in the obstacle placement stage")
if self.board[:, point.row - 1, point.col - 1].any():
raise IllegalMoveError("Obstacle cannot be placed here")
self.board[2, point.row - 1, point.col - 1] = 1
self.stage = 0
def is_queen_move(self, start, end):
if (start.row == end.row and start.col == end.col) or self.board[:, end.row - 1, end.col - 1].any():
return False
dy, dx = end.row - start.row, end.col - start.col
if abs(dy) != abs(dx) and dy != 0 and dx != 0:
return False
step_y = (dy and (1 if dy > 0 else -1))
step_x = (dx and (1 if dx > 0 else -1))
y, x = start.row + step_y - 1, start.col + step_x - 1
while (y + 1, x + 1) != (end.row, end.col):
if self.board[:, y, x].any():
return False
y += step_y
x += step_x
return True
def has_stone(self, row, col):
# Adjust from 1-based to 0-based indexing internally
return self.board[:, row - 1, col - 1].any()
def __deepcopy__(self, memory_dict=None):
if memory_dict is None:
memory_dict = {}
# Check if the object is already in the memory dictionary
if id(self) in memory_dict:
return memory_dict[id(self)]
# Create a new copy and add it to the memory dictionary
new_board = Board(self.size)
memory_dict[id(self)] = new_board
new_board.board = np.copy(self.board)
new_board.stage = self.stage
new_board.selected_amazon = copy.deepcopy(self.selected_amazon, memory_dict)
return new_board
class Move:
def __init__(self, action, point):
self.action = action
self.point = point
@classmethod
def select(cls, point):
return cls('select', point)
@classmethod
def move(cls, point):
return cls('move', point)
@classmethod
def place(cls, point):
return cls('place', point)
class GameState:
def __init__(self, board, next_player, previous=None, move=None):
self.board = copy.deepcopy(board)
self.next_player = next_player
self.previous_state = previous
self.last_move = move
def apply_move(self, move):
new_board = copy.deepcopy(self.board)
if move.action == 'select':
new_board.select_amazon(move.point)
elif move.action == 'move':
new_board.move_amazon(move.point)
elif move.action == 'place':
new_board.place_obstacle(move.point)
return GameState(new_board, self.next_player.other, self, move)
@classmethod
def new_game(cls):
board = Board()
return GameState(board, Player.black)
GameState存储棋盘的任何一手的实际状态;Move是某一手的所有动作;Board定义了棋盘的格式和所有合法的动作和先后顺序。
参与讨论
(Participate in the discussion)
参与讨论