This repository has been archived by the owner on Mar 19, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
board.py
184 lines (146 loc) · 6.48 KB
/
board.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
from tile import Tile
LIGHT_COLOR = (0, 0, 0) # White
DARK_COLOR = (255, 255, 255) # Black
class Board:
class NoSloveException(Exception):
"""For Cursur debug"""
pass
class InvalidMoveException(Exception):
"""The algorithms' solution contain invalid movement."""
pass
def __init__(self, size: tuple, start_pos: dict = {"x": 0, "y": 0}) -> None:
if size[0] != size[1]:
raise Exception("Not a Square Board")
self._size = size
self._tiles = self.make_tiles()
self._current_pos = start_pos
self._current_step = 1
self._path_log = []
self.get_tile(start_pos["x"], start_pos["y"]).set_state(True)
self._path_log.append([start_pos["y"], start_pos["x"]])
def get_tiles(self) -> Tile:
return self._tiles
def get_tile(self, x: int, y: int) -> Tile:
return self.get_tiles()[x][y]
def get_mouse_tile_pos(self, pos: tuple, screen_size: list) -> tuple:
"""For mouse debug, get current tile relative to the mouse cursor.
Args:
pos (tuple): mouse posistion
screen_size (list): screen size
Returns:
tuple: coresponding tile position
"""
tile_pos_x = tile_pos_y = 0
offset = int(screen_size[0] / self.get_size())
x_found = y_found = False
for i in range(self.get_size()):
if x_found == False:
if pos[0] > offset * i and pos[0] < offset * (i + 1):
tile_pos_x = i
x_found = True
if y_found == False:
if pos[1] > offset * i and pos[1] < offset * (i + 1):
tile_pos_y = i
y_found = True
return tile_pos_x, tile_pos_y
def get_step_count(self) -> int:
return self._current_step
def get_paths(self) -> list:
return self._path_log
def show_path(self) -> None:
print(self._path_log)
def move(self, target_pos: dict) -> bool:
"""Knight move from current posistion to target posisiton
Args:
target_pos (dict): target posistion
Returns:
bool: True if valid move. else False
"""
target_tile = self.get_tile(target_pos["x"], target_pos["y"])
if (
self.check_legal_move(self._current_pos, target_pos) is True
and target_tile.is_visited() == False
):
target_tile.set_state(True)
target_tile.set_step(self._current_step + 1)
self._current_step += 1
self._current_pos = target_pos
self._path_log.append([target_pos["y"], target_pos["x"]])
return True
return False
def check_legal_move(self, current_pos: dict, target_pos: dict) -> bool:
legal_moves = []
board_edge = self.get_size()
# find legal pos for current_pos
# can be optimzied? if it works, just dont touch it for now [lst97]
if current_pos["x"] + 2 < board_edge:
if current_pos["y"] + 1 < board_edge:
# tile that already moved not count as legal
target_tile = self.get_tile(current_pos["x"] + 2, current_pos["y"] + 1)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] + 2, current_pos["y"] + 1])
if current_pos["y"] - 1 > -1:
target_tile = self.get_tile(current_pos["x"] + 2, current_pos["y"] - 1)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] + 2, current_pos["y"] - 1])
if current_pos["x"] - 2 > -1:
if current_pos["y"] + 1 < board_edge:
target_tile = self.get_tile(current_pos["x"] - 2, current_pos["y"] + 1)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] - 2, current_pos["y"] + 1])
if current_pos["y"] - 1 > -1:
target_tile = self.get_tile(current_pos["x"] - 2, current_pos["y"] - 1)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] - 2, current_pos["y"] - 1])
if current_pos["y"] + 2 < board_edge:
if current_pos["x"] + 1 < board_edge:
target_tile = self.get_tile(current_pos["x"] + 1, current_pos["y"] + 2)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] + 1, current_pos["y"] + 2])
if current_pos["x"] - 1 > -1:
target_tile = self.get_tile(current_pos["x"] - 1, current_pos["y"] + 2)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] - 1, current_pos["y"] + 2])
if current_pos["y"] - 2 > -1:
if current_pos["x"] + 1 < board_edge:
target_tile = self.get_tile(current_pos["x"] + 1, current_pos["y"] - 2)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] + 1, current_pos["y"] - 2])
if current_pos["x"] - 1 > -1:
target_tile = self.get_tile(current_pos["x"] - 1, current_pos["y"] - 2)
if target_tile.is_visited() is False:
legal_moves.append([current_pos["x"] - 1, current_pos["y"] - 2])
if len(legal_moves) == 0 and self._current_step < pow(self.get_size(), 2):
raise Board.NoSloveException("No Any Legel Move!")
target_move = []
for _, i in target_pos.items():
target_move.append(i)
is_legal = False
# Knight must move, cant stay
for move in legal_moves:
if move == target_move:
is_legal = True
break
return is_legal
def get_size(self) -> int:
return self._size[0]
def get_current_pos(self) -> dict:
return self._current_pos
def set_current_pos(self, pos: dict) -> None:
self._current_pos = pos
def make_tiles(self) -> list:
"""Make tile objects for board data
Returns:
list: list of Tile objects.
"""
tiles = list()
for y in range(self._size[0]):
tiles.append([])
for x in range(self._size[1]):
tiles[y].append(
Tile(
{"x": x, "y": y},
DARK_COLOR if abs(x - y) % 2 == 0 else LIGHT_COLOR,
)
)
return tiles