-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathminesweeper.py
More file actions
162 lines (134 loc) · 5.52 KB
/
minesweeper.py
File metadata and controls
162 lines (134 loc) · 5.52 KB
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
# -*- coding: utf-8 -*-
"""
Spyder Editor
This is a temporary script file.
"""
import numpy as np
import random
import math
from pandas import *
class Board():
SNAPSHOT_SIZE = 8
def __init__(self,rows,cols):
self.rewards={'WIN':1, 'LOSE':-1, 'PROGRESS':0.3, 'GUESS':-0.3, 'NO_PROGRESS' : -0.3}
self.rows = rows
self.cols = cols
self.ntiles = rows*cols
self.board = np.full((rows,cols), -1,dtype = float) # what user sees
# -1 meaning unopened, 0-8 indicates numbers
self.mines = np.full((rows,cols), 0) # 0 means not bomb, 1 means bomb
self.opened = 0
self.n_wins = 0
self.n_progress = 0
for row in range(rows):
for col in range(cols):
self.mines[(row,col)] = 0
def reset(self):
self.board = np.full((self.rows,self.cols), -1,dtype = float) # what user sees
# -1 meaning unopened, 0-8 indicates numbers
self.mines = np.full((self.rows,self.cols), 0) # 0 means not bomb, 1 means bomb
self.opened = 0
self.n_progress = 0
for row in range(self.rows):
for col in range(self.cols):
self.mines[(row,col)] = 0
def set_mines_about(self,row_center,col_center,num_mines):
self.num_mines = num_mines
sample_points = list(range((self.rows)*(self.cols)))
for i in range(-1,2):
for j in range(-1,2):
if self.is_in_bounds(row_center+i,col_center+j):
sample_points.remove((row_center+i)*self.cols + (col_center+j))
# Set the mines on the board that is not around the center point
cords = random.sample(sample_points, num_mines)
for cord in cords:
row = math.floor(cord/self.cols)
col = cord % self.cols
self.mines[(row,col)] = 1
# open the center point
self.dig(row_center, col_center)
def get_neighbors(self, r, c):
neighbors = []
for col in range(c-1, c+2):
for row in range(r-1, r+2):
if ((r != row or c != col) and
(0 <= col < self.cols) and
(0 <= row < self.rows)):
neighbors.append(self.board[row,col])
return np.array(neighbors)
def dig(self,row,col):
# print("Opening ( %d, %d ) ..." % (row, col))
current_state = np.copy(self.board)
# If the tile is a bomb
if self.mines[row,col] == 1:
# print("GAME LOST, BOMB DETECTED")
board3d = self.board3D()
return board3d, self.rewards['LOSE'], True
elif self.board[row,col] == -1: # NOT A BOMB && UNOPENED
counter = 0
self.opened += 1
for i in range(-1,2):
for j in range(-1,2):
if self.is_in_bounds(row+i,col+j):
if self.mines[(row + i,col+j)] == 1:
counter += 1
self.board[(row,col)] = counter/8
if self.opened == (self.ntiles - self.num_mines):
self.n_wins += 1
self.n_progress += 1
# print("GAME WON, CONGRATULATIONS!!")
board3d = self.board3D()
return board3d, self.rewards['WIN'], True
# If there are no bombs around it, open until they find one
if counter == 0:
for i in range(-1,2):
for j in range(-1,2):
if self.is_in_bounds(row+i,col+j):
if self.board[(row+i,col+j)] == -1:
self.dig(row + i,col+j)
# print("Progressed ...")
board3d = self.board3D()
if np.sum(self.board == -1) == np.sum(current_state == -1):
# print("NO PROGRESS")
return board3d, self.rewards['NO_PROGRESS'], False
else:
neighbors = self.get_neighbors(row, col)
if all(t==-1 for t in neighbors): # if guess (all neighbors are unsolved)
# print("GUESS")
return board3d, self.rewards['GUESS'], False
else:
self.n_progress += 1
return board3d, self.rewards['PROGRESS'], False
else:
print("INVALID MOVE")
board3d = self.board3D()
return board3d, self.rewards['NO_PROGRESS'], False
def board3D(self):
return np.reshape(self.board,(self.rows,self.cols,1))
def printBoard(self):
print(self.board * 8)
def printMines(self):
print(self.mines)
def d(self,row,col):
self.dig(row,col)
print(self)
def is_in_bounds(self,row,col):
if row < 0 or row >= self.rows or col < 0 or col >= self.cols:
return False
return True
def get_board3d(self):
return np.reshape(self.board,(self.rows,self.cols,1))
def get_snapshot(self,row,col):
assert(row >= 0 and row <= self.rows + self.SNAPSHOT_SIZE)
assert(col >= 0 and col <= self.cols + self.SNAPSHOT_SIZE)
return self.board[row:row+self.SNAPSHOT_SIZE, col:col+self.SNAPSHOT_SIZE]
def dig_at_snapshot(self,snap_row,snap_col,row_in_snap,col_in_snap):
return self.dig(snap_row + row_in_snap, snap_col + col_in_snap)
def __str__(self):
print(self.board * 8)
return""
'''
np.set_printoptions(precision=3)
b = Board(16,16)
b.set_mines_about(4,4,40)
b.d(4,4)'''