Skip to content

Commit 8aba976

Browse files
Merge pull request #188 from varous7/master
Game 2048 using Pyhton GUI
2 parents 4cef0f5 + 4dd8e7a commit 8aba976

File tree

1 file changed

+295
-0
lines changed

1 file changed

+295
-0
lines changed

GUI/2048.py

+295
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,295 @@
1+
from __future__ import print_function
2+
import tkinter as tk
3+
import tkinter.messagebox as messagebox
4+
import random
5+
6+
class Grid:
7+
def __init__ (self, n):
8+
self.size = n
9+
self.cells = self.generate_empty_grid()
10+
self.compressed = False
11+
self.merged = False
12+
self.moved = False
13+
self.current_score = 0
14+
15+
def random_cell(self):
16+
cell = random.choice(self.retreive_empty_cells())
17+
i = cell[0]
18+
j = cell[1]
19+
self.cells[i][j] = 2 if random.random() < 0.9 else 4
20+
21+
def retreive_empty_cells(self):
22+
empty_cells = []
23+
for i in range(self.size):
24+
for j in range(self.size):
25+
if self.cells[i][j] == 0:
26+
empty_cells.append((i,j))
27+
return empty_cells
28+
29+
def generate_empty_grid(self):
30+
return [[0] * self.size for i in range(self.size)]
31+
32+
def transpose(self):
33+
self.cells = [list(t) for t in zip(*self.cells)]
34+
35+
def reverse(self):
36+
for i in range(self.size):
37+
start = 0
38+
end = self.size - 1
39+
while start < end:
40+
self.cells[i][start], self.cells[i][end] = self.cells[i][end], self.cells[i][start]
41+
start += 1
42+
end -= 1
43+
44+
def clear_flags(self):
45+
self.compressed = False
46+
self.merged = False
47+
self.moved = False
48+
49+
def left_compress(self):
50+
self.compressed = False
51+
new_grid = self.generate_empty_grid()
52+
for i in range(self.size):
53+
count=0
54+
for j in range(self.size):
55+
if self.cells[i][j] != 0:
56+
new_grid[i][count] = self.cells[i][j]
57+
if count !=j:
58+
self.compressed = True
59+
count += 1
60+
self.cells = new_grid
61+
62+
def left_merge(self):
63+
self.merged = False
64+
for i in range(self.size):
65+
for j in range(self.size -1):
66+
if self.cells[i][j] == self.cells[i][j+1] and self.cells[i][j] != 0:
67+
self.cells[i][j]*= 2
68+
self.cells[i][j+1] = 0
69+
self.current_score += self.cells[i][j]
70+
self.merged = True
71+
print('left merged')
72+
73+
def found_2048(self):
74+
for i in range(self.size):
75+
for j in range(self.size):
76+
if self.cells[i][i] >= 2048:
77+
return True
78+
return False
79+
80+
def has_empty_cells(self):
81+
for i in range(self.size):
82+
for j in range(self.size):
83+
if self.cells[i][j] == 0:
84+
return True
85+
return False
86+
87+
def can_merge(self):
88+
for i in range(self.size):
89+
for j in range(self.size-1):
90+
if self.cells[i][j] == self.cells[i][j+1]:
91+
return True
92+
for j in range(self.size):
93+
for i in range(self.size - 1):
94+
if self.cells[i][j] == self.cells[i+1][j]:
95+
return True
96+
return False
97+
98+
def set_cells(self, cells):
99+
self.cells=cells
100+
101+
def print_grid(self):
102+
print('='*40)
103+
for i in range(self.size):
104+
for j in range(self.size):
105+
print('%d\t', self.cells[i][j], end='')
106+
print()
107+
print('='*40)
108+
109+
class GamePanel:
110+
'''The GUI view class of the 2048 game show'''
111+
CELL_PADDING= 10
112+
BACKGROUND_COLOR = '#92877d'
113+
EMPTY_CELL_COLOR='#9e948a'
114+
CELL_BACKGROUND_COLOR_DICT = {
115+
'2': '#eee4da',
116+
'4': '#ede0c8',
117+
'8': '#f2b179',
118+
'16': '#f59563',
119+
'32': '#f67c5f',
120+
'64': '#f65a3b',
121+
'128': '#edcf72',
122+
'256': '#edcc61',
123+
'512': '#edc850',
124+
'1024': '#edc53f',
125+
'2048': '#edc22e',
126+
'beyond': '#3c3a32'}
127+
128+
CELL_COLOR_DICT = {
129+
'2': '#776e65',
130+
'4': '#776e65',
131+
'8':'#f9f6f2',
132+
'16': '#f9f6f2',
133+
'32': '#f9f6f2',
134+
'64': '#f9f6f2',
135+
'128': '#f9f6f2',
136+
'256': '#f9f6f2',
137+
'512': '#f9f6f2',
138+
'1024': '#f9f6f2',
139+
'2048': '#f9f6f2',
140+
'beyond': '#19f6f2'}
141+
142+
FONT=('COMIC SANS', 18, 'bold')
143+
UP_KEYS = ('Up')
144+
DOWN_KEYS = ('Down')
145+
LEFT_KEYS = ('Left')
146+
RIGHT_KEYS = ('Right')
147+
148+
def __init__(self, grid):
149+
self.grid = grid
150+
self.root = tk.Tk()
151+
self.root.title('2048')
152+
self.background = tk.Frame(self.root, bg= GamePanel.BACKGROUND_COLOR)
153+
self.cell_labels = []
154+
for i in range(self.grid.size):
155+
row_labels =[]
156+
for j in range(self.grid.size):
157+
label = tk.Label(self.background, text='',
158+
bg=GamePanel.EMPTY_CELL_COLOR, justify=tk.CENTER,
159+
font=GamePanel.FONT, width=4, height=2)
160+
label.grid(row=i, column=j, padx=10, pady=10)
161+
row_labels.append(label)
162+
self.cell_labels.append(row_labels)
163+
self.background.grid()
164+
165+
def paint(self):
166+
for i in range(self.grid.size):
167+
for j in range(self.grid.size):
168+
if self.grid.cells[i][j]== 0:
169+
self.cell_labels[i][j].configure(text='', bg=GamePanel.EMPTY_CELL_COLOR)
170+
else:
171+
cell_text = str(self.grid.cells[i][j])
172+
if self.grid.cells[i][j]>2048:
173+
bg_color=GamePanel.CELL_BACKGROUND_COLOR_DICT.get("beyond")
174+
fg_color=GamePanel.CELL_COLOR_DICT.get("beyond")
175+
else:
176+
bg_color = GamePanel.CELL_BACKGROUND_COLOR_DICT.get(cell_text)
177+
fg_color = GamePanel.CELL_COLOR_DICT.get(cell_text)
178+
self.cell_labels[i][j].configure(text=cell_text,
179+
bg=bg_color, fg=fg_color)
180+
181+
class Game:
182+
'''The main Game class which is the controller of the whole game.'''
183+
def __init__ (self, grid, panel):
184+
self.grid = grid
185+
self.panel=panel
186+
self.start_cells_num=2
187+
self.over=False
188+
self.won = False
189+
self.keep_playing=False
190+
191+
def is_game_terminated(self):
192+
return self.over or (self.won and (not self.keep_playing))
193+
194+
def start(self):
195+
self.add_start_cells()
196+
self.panel.paint()
197+
self.panel.root.bind('<Key>', self.key_handler)
198+
self.panel.root.mainloop()
199+
200+
def add_start_cells(self):
201+
for i in range(self.start_cells_num):
202+
self.grid.random_cell()
203+
204+
def can_move(self):
205+
return self.grid.has_empty_cells() or self.grid.can_merge()
206+
207+
def key_handler(self, event):
208+
if self.is_game_terminated():
209+
return
210+
211+
self.grid.clear_flags()
212+
key_value = event.keysym
213+
214+
print('{} key pressed'.format(key_value))
215+
if key_value in GamePanel.UP_KEYS:
216+
self.up()
217+
#self.grid.print_grid
218+
elif key_value in GamePanel.LEFT_KEYS:
219+
self.left()
220+
#self.grid print_grid
221+
elif key_value in GamePanel.DOWN_KEYS:
222+
self.down()
223+
#self.grid.print_grid()
224+
elif key_value in GamePanel.RIGHT_KEYS:
225+
self.right()
226+
#self.grid.print_grid()
227+
else:
228+
pass
229+
230+
self.panel.paint()
231+
print('Score: {}'.format(self.grid.current_score))
232+
if self.grid.found_2048():
233+
self.you_win()
234+
if not self.keep_playing:
235+
return
236+
237+
if self.grid.moved:
238+
self.grid.random_cell()
239+
240+
self.panel.paint()
241+
if not self.can_move():
242+
self.over = True
243+
self.game_over()
244+
245+
def you_win(self):
246+
if not self.won:
247+
self.won = True
248+
print('You Win!')
249+
if messagebox.askyesno('2048', 'You Win!\n'
250+
'Are you going to continue the 2048 game?'):
251+
self.keep_playing = True
252+
253+
def game_over(self):
254+
print('Game Over!')
255+
messagebox.showinfo('2048', 'Oops!\n'
256+
'Game Over!')
257+
258+
def up(self):
259+
self.grid.transpose()
260+
self.grid.left_compress()
261+
self.grid.left_merge()
262+
self.grid.moved = self.grid.compressed or self.grid.merged
263+
self.grid.left_compress()
264+
self.grid.transpose()
265+
266+
def left(self):
267+
self.grid.left_compress()
268+
self.grid.left_merge()
269+
self.grid.moved = self.grid.compressed or self.grid.merged
270+
self.grid.left_compress()
271+
272+
def down(self):
273+
self.grid.transpose()
274+
self.grid.reverse()
275+
self.grid.left_compress()
276+
self.grid.left_merge()
277+
self.grid .moved = self.grid.compressed or self.grid.merged
278+
self.grid.left_compress()
279+
self.grid.reverse()
280+
self.grid.transpose()
281+
282+
def right(self):
283+
self.grid.reverse()
284+
self.grid.left_compress()
285+
self.grid.left_merge()
286+
self.grid.moved = self.grid.compressed or self.grid.merged
287+
self.grid.left_compress()
288+
self.grid.reverse()
289+
290+
if __name__ == '__main__':
291+
size = 4
292+
grid = Grid(size)
293+
panel = GamePanel(grid)
294+
game2048 = Game(grid, panel)
295+
game2048.start()

0 commit comments

Comments
 (0)