-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathboard.py
150 lines (130 loc) · 4.97 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
import random
from typing import Final
# *****************************************************************************
# Execution: none
# Dependencies: nonez
# Representation of a n-puzzle board object
# @author Eduardo Ch. Colorado
# ******************************************************************************/
class Board(object):
"""
Defines a Board for the n-puzzle game
"""
# Constructor
def __init__(self, blocks: list[list[int]]):
"""
Creates an instance of a board
Internally, the content of the board is represented as 1D array
where each row in the 2D board is append to the right, from top
to bottom
Also the Manhattan and Hamming are calculated as private properties of the class
"""
self.n: Final[int] = len(blocks)
self.linear_board: list[int] = []
self.Manhattan: int = 0
self.Hamming: int = 0
for i in range(self.n):
for j in range(self.n):
entry = blocks[i][j]
self.linear_board.append(entry)
if entry != 0:
self.Manhattan += abs(i - (entry - 1) // self.n) + abs(
j - ((entry - 1) % self.n)
)
if entry != self.n * i + j + 1:
self.Hamming += 1
def dimension(self):
"""Size of the board game"""
return self.n
def manhattan(self):
"""Manhattan distance"""
return self.Manhattan
def hamming(self):
"""Hamming distance"""
return self.Hamming
def inversions(self):
pass
def is_goal(self) -> bool:
"""Determine when a given board is the goal board"""
for i in range(0, self.n * self.n - 1):
if self.linear_board[i] != i + 1:
return False # if the linear array is not sorted in ascending order, then the board is not the goal board
return True
def __get_board(self):
return self.linear_board
def __swap(self, Idx: int, nIdx: int):
"""Swap one valid place in the blank tile"""
neighbor = [
[self.linear_board[i * self.n + j] for j in range(self.n)]
for i in range(self.n)
]
i, j = Idx // self.n, Idx % self.n
l, m = nIdx // self.n, nIdx % self.n
temp = self.linear_board[nIdx]
neighbor[i][j] = temp
neighbor[l][m] = 0
return neighbor
##Overload the comparison method
def __eq__(self, other):
if isinstance(other, self.__class__):
return self.__dict__ == other.__dict__
else:
return False
# if(self == other): return True
# if(other == None): return False
# if(not isinstance(other, Board)): return False
# other_board = other.__get_board()
# for i in range(self.n*self.n):
# if(self.linear_board[i] != other_board[i]): return False
# return True
# Iterate through the possibles bottom, up, left and right blank tiles moves (we called them neighbors)
def neighbors(self):
"""
Return the possible boards after moving the blank tile to valid positions
with respect to the reference Board
"""
# search where the blank space is placed
idx = self.linear_board.index(0)
# create a neighbor list
L: list[Board] = []
if idx // self.n != 0:
L.append(Board(self.__swap(idx, idx - self.n))) # up neighbor
if (idx + 1) // self.n == idx // self.n:
L.append(Board(self.__swap(idx, idx + 1))) # right neighbor
if idx + self.n < self.n**2:
L.append(Board(self.__swap(idx, idx + self.n))) # botton neighopur
if (idx - 1) // self.n == idx // self.n and idx - 1 >= 0:
L.append(Board(self.__swap(idx, idx - 1))) # left neighbor
while len(L) != 0:
yield L.pop()
def __str__(self) -> str:
s = "\n".join(
" ".join([str(self.linear_board[i * self.n + j]) for j in range(self.n)])
for i in range(self.n)
)
return s + "\n"
# n = 3
# a = list(random.sample(range(n*n),n*n))
# blocks1 = [[a[n*i+j] for j in range(n)] for i in range(n) ]
# blocks2 = [[a[n*i+j] for j in range(n)] for i in range(n) ]
# temp = blocks2[1][2]
# blocks2[1][2] = blocks2[2][1]
# blocks2[2][1] = temp
# s = "\n".join(' '.join([str(blocks[i][j]) for j in range(3)]) for i in range(3))
# board1 = Board(blocks1)
# board2 = Board(blocks2)
# print(board1)
# print()
# print(board2)
# print()
# print(board1 == board2)
# print()
# print(board1.is_goal())
# print()
# print(board1.is_goal())
# print()
# for neighbor in board1.neighbors():
# print(neighbor)
# print('Manhattan distannce: ' + str(neighbor.manhattan()))
# print('Hamming distance: ' + str(neighbor.hamming()))
# print()