-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathBoard.py
137 lines (114 loc) · 4.25 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
import numpy as np
import random
class Board_2048:
def __init__( self, width=4, height=4 ):
self.width = width
self.height = height
self.board = self.get_init_board()
def get_copy( self ):
copy = Board_2048( width=self.width, height=self.height )
copy.set_board( self.board )
return copy
def set_board( self, new_board ):
if new_board.shape == self.board.shape:
self.board = np.copy( new_board )
else:
raise Exception( "cannot set_board with different shape" )
def total( self ):
return sum( filter( None, self.board.flatten() ) )
def max( self ):
return max( filter( None, self.board.flatten() ) )
def shape( self ):
return ( self.height, self.width )
def board_str( self ):
def get_lines():
cap_str = "+"
fill_str = "|"
for _ in range(self.width):
cap_str = cap_str + "-----+"
fill_str = fill_str + " |"
return (cap_str + "\n", fill_str + "\n")
(cap_line, fill_line) = get_lines()
def row_str( row ):
def e_str( e ):
return "" if e is None else str(e)
ret = "|"
for e in row:
ret = ret + e_str(e).center( 5, ' ' ) + "|"
return ret + "\n"
brd = cap_line
for row in self.board:
brd = brd + fill_line + row_str( row ) + fill_line + cap_line
return brd
def print_game( self ):
print( self.board_str() )
def get_init_board( self ):
arr = [[None for _ in range( self.width ) ] for _ in range( self.height ) ]
return np.array(arr)
def place_random_tile( self, val=2 ):
opts = list(zip(*np.where(self.board == None)))
if(len(opts) != 0):
idx = random.sample(opts, 1)[0]
self.board[idx[0]][idx[1]] = val
def try_slide( self, direction ):
temp_board = np.copy( self.board )
res = self.slide( direction )
del self.board
self.board = temp_board
return res
def stuck( self ):
moved = False
for d in [ 'u', 'd', 'l', 'r' ]:
_, m = self.try_slide( d )
moved = moved or m
return not moved
def slide( self, direction ):
def in_place_compress_left( arr ):
cur_i = 0
move_to = 0
cur_val = None
cur_val_orig_idx = None
moved = False
points = 0
while cur_i < len( arr ):
if cur_val is None and arr[cur_i] is not None:
cur_val = arr[cur_i]
cur_val_orig_idx = cur_i
elif cur_val is not None and cur_val == arr[cur_i]:
arr[move_to] = cur_val * 2
points = points + cur_val * 2
moved = True
cur_val = None
move_to = move_to + 1
elif arr[cur_i] is not None and cur_val != arr[cur_i]:
arr[move_to] = cur_val
if move_to != cur_val_orig_idx:
moved = True
cur_val = arr[cur_i]
cur_val_orig_idx = cur_i
move_to = move_to + 1
cur_i = cur_i + 1
arr[move_to] = cur_val
if cur_val_orig_idx is not None and move_to != cur_val_orig_idx:
moved = True
move_to = move_to + 1
while move_to < len( arr ):
arr[move_to] = None
move_to = move_to + 1
return ( points, moved )
def rc_get( val, direc ):
if direc == 'u':
return self.board[:,val]
if direc == 'd':
return self.board[::-1,val]
if direc == 'l':
return self.board[val]
if direc == 'r':
return self.board[val][::-1]
points = 0
moved = False
for i in range( self.height if direction in [ 'l', 'r' ] else self.width ):
( p, m ) = in_place_compress_left( rc_get( i, direction ) )
points = points + p
moved = moved or m
return ( points, moved )