-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathboard.py
147 lines (130 loc) · 4.85 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
import numpy
import random
import time
POSITION_EMPTY = 0
POSITION_QUEEN = 1
class Board:
def __init__(self,row,col):
self.rows = row
self.cols = col
self.__initBoard()
# Add a new queen at a random position
def addRandomQueen(self):
while True:
x = random.randrange(0,self.rows)
y = random.randrange(0,self.cols)
if self.__isPositionEmpty(x,y):
self.board[x][y] = POSITION_QUEEN
break
self.queenCount += 1
self.queenPositions.append((x,y))
self.score = self.evaluateBoard()
# Add 8 new queens
def add8Queens(self):
for i in range(0,8):
self.addRandomQueen()
def __initBoard(self):
self.board = numpy.zeros((self.rows,self.cols))
self.queenCount = 0
self.queenPositions = []
self.score = 0
self.goal = 0
# Check if the given position is empty
def __isPositionEmpty(self,x,y):
if self.board[x][y] == POSITION_EMPTY:
return True
else:
return False
# Reset the board and generate an initial state
def randomRestart(self):
self.__initBoard()
self.add8Queens()
# Draw the board
def drawBoard(self):
for i in range(self.rows):
for k in range(self.cols):
if self.board[i,k] == POSITION_EMPTY:
print("[ ]",end="")
elif self.board[i,k] == POSITION_QUEEN:
print("[W]",end="")
print("") # Newline
print("") # Newline
def moveQueen(self,queen,newX,newY):
if self.__isPositionEmpty(newX,newY):
queenPosition = self.queenPositions[queen]
self.board[queenPosition[0],queenPosition[1]] = POSITION_EMPTY
self.board[newX,newY] = POSITION_QUEEN
self.queenPositions[queen] = (newX,newY)
def evaluateBoard(self):
currentScore = 0
for queen in range(0,self.queenCount):
queenX = self.queenPositions[queen][0]
queenY = self.queenPositions[queen][1]
eval1 = self.__horizontalEvaluation(queen,queenX)
eval2 = self.__verticalEvaluation(queen,queenY)
eval3 = self.__diagonalEvaluation(queen,queenX,queenY)
currentScore += eval1 + eval2 + eval3
return currentScore
def __horizontalEvaluation(self,queen,x):
count = 0
for i in range(0,self.queenCount):
if i == queen:
continue
elif self.queenPositions[i][0] == x:
count += 1
return count
def __verticalEvaluation(self,queen,y):
count = 0
for i in range(0,self.queenCount):
if i == queen:
continue
elif self.queenPositions[i][1] == y:
count += 1
return count
def __diagonalEvaluation(self,queen,x,y):
count = 0
for i in range(0,self.queenCount):
if i == queen:
continue
else:
queenX = self.queenPositions[i][0]
queenY = self.queenPositions[i][1]
if abs(x - queenX) == abs(y - queenY):
count += 1
return count
def solveWithHillClimbing(self):
startTime = time.clock()
randomRestartCount = 0
moveCount = 0
stuck = 0
while True:
moveFound = None
newScore = self.score
for queen in range(0,self.queenCount):
oldPosition = self.queenPositions[queen] # Queen's current position
for k in range(0,self.rows):
self.moveQueen(queen,k,oldPosition[1])
evaluation = self.evaluateBoard()
if (evaluation < newScore):
moveFound = (queen,k,oldPosition[1])
newScore = evaluation
self.moveQueen(queen,oldPosition[0],oldPosition[1])
for k in range(0,self.cols):
self.moveQueen(queen,oldPosition[0],k)
evaluation = self.evaluateBoard()
if (evaluation < newScore):
moveFound = (queen,oldPosition[0],k)
newScore = evaluation
self.moveQueen(queen,oldPosition[0],oldPosition[1])
if moveFound == None:
self.randomRestart()
randomRestartCount += 1
else:
self.score = newScore
self.moveQueen(moveFound[0],moveFound[1],moveFound[2])
moveCount += 1
if self.score == self.goal:
endTime = time.clock()
elapsed = endTime - startTime
self.drawBoard()
return (moveCount,randomRestartCount,elapsed)