Skip to content

Commit a77c152

Browse files
Merge pull request #183 from Mounika-39/feature/2048-game
Add animated 2048 game with web integration
2 parents 9f830a1 + e3a9b99 commit a77c152

4 files changed

Lines changed: 706 additions & 0 deletions

File tree

games/2048-Game/2048-Game.py

Lines changed: 290 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,290 @@
1+
import tkinter as tk
2+
import random
3+
import os
4+
5+
GRID_SIZE = 4
6+
CELL_SIZE = 100
7+
CELL_PADDING = 10
8+
BACKGROUND_COLOR = "#92877d"
9+
EMPTY_CELL_COLOR = "#9e948a"
10+
11+
TILE_COLORS = {
12+
2: "#eee4da",
13+
4: "#ede0c8",
14+
8: "#f2b179",
15+
16: "#f59563",
16+
32: "#f67c5f",
17+
64: "#f65e3b",
18+
128: "#edcf72",
19+
256: "#edcc61",
20+
512: "#edc850",
21+
1024: "#edc53f",
22+
2048: "#edc22e"
23+
}
24+
25+
TEXT_COLORS = {
26+
2: "#776e65",
27+
4: "#776e65",
28+
8: "#f9f6f2",
29+
16: "#f9f6f2",
30+
32: "#f9f6f2",
31+
64: "#f9f6f2",
32+
128: "#f9f6f2",
33+
256: "#f9f6f2",
34+
512: "#f9f6f2",
35+
1024: "#f9f6f2",
36+
2048: "#f9f6f2"
37+
}
38+
39+
HIGH_SCORE_FILE = "highscore.txt"
40+
41+
42+
class Game2048:
43+
def __init__(self, root):
44+
self.root = root
45+
self.root.title("2048 Game")
46+
47+
self.score = 0
48+
self.high_score = self.load_high_score()
49+
50+
self.main_frame = tk.Frame(root, bg=BACKGROUND_COLOR)
51+
self.main_frame.grid()
52+
53+
self.score_label = tk.Label(
54+
root,
55+
text=f"Score: 0 High Score: {self.high_score}",
56+
font=("Arial", 16, "bold")
57+
)
58+
self.score_label.grid(pady=10)
59+
60+
self.restart_button = tk.Button(
61+
root,
62+
text="Restart Game",
63+
font=("Arial", 12, "bold"),
64+
command=self.restart_game
65+
)
66+
self.restart_button.grid(pady=5)
67+
68+
self.cells = []
69+
self.board = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]
70+
71+
self.create_grid()
72+
self.add_new_tile()
73+
self.add_new_tile()
74+
self.update_grid()
75+
76+
self.root.bind("<Key>", self.handle_keypress)
77+
78+
def load_high_score(self):
79+
if os.path.exists(HIGH_SCORE_FILE):
80+
with open(HIGH_SCORE_FILE, "r") as file:
81+
return int(file.read())
82+
return 0
83+
84+
def save_high_score(self):
85+
with open(HIGH_SCORE_FILE, "w") as file:
86+
file.write(str(self.high_score))
87+
88+
def create_grid(self):
89+
for row in range(GRID_SIZE):
90+
row_cells = []
91+
92+
for col in range(GRID_SIZE):
93+
frame = tk.Frame(
94+
self.main_frame,
95+
bg=EMPTY_CELL_COLOR,
96+
width=CELL_SIZE,
97+
height=CELL_SIZE
98+
)
99+
100+
frame.grid(
101+
row=row,
102+
column=col,
103+
padx=CELL_PADDING,
104+
pady=CELL_PADDING
105+
)
106+
107+
label = tk.Label(
108+
self.main_frame,
109+
text="",
110+
bg=EMPTY_CELL_COLOR,
111+
justify=tk.CENTER,
112+
font=("Arial", 24, "bold"),
113+
width=4,
114+
height=2
115+
)
116+
117+
label.grid(
118+
row=row,
119+
column=col,
120+
padx=CELL_PADDING,
121+
pady=CELL_PADDING
122+
)
123+
124+
row_cells.append(label)
125+
126+
self.cells.append(row_cells)
127+
128+
def add_new_tile(self):
129+
empty_cells = []
130+
131+
for row in range(GRID_SIZE):
132+
for col in range(GRID_SIZE):
133+
if self.board[row][col] == 0:
134+
empty_cells.append((row, col))
135+
136+
if empty_cells:
137+
row, col = random.choice(empty_cells)
138+
self.board[row][col] = 2 if random.random() < 0.9 else 4
139+
140+
def update_grid(self):
141+
for row in range(GRID_SIZE):
142+
for col in range(GRID_SIZE):
143+
value = self.board[row][col]
144+
145+
if value == 0:
146+
self.cells[row][col].configure(
147+
text="",
148+
bg=EMPTY_CELL_COLOR
149+
)
150+
else:
151+
self.cells[row][col].configure(
152+
text=str(value),
153+
bg=TILE_COLORS.get(value, "#3c3a32"),
154+
fg=TEXT_COLORS.get(value, "#f9f6f2")
155+
)
156+
157+
self.score_label.configure(
158+
text=f"Score: {self.score} High Score: {self.high_score}"
159+
)
160+
161+
self.root.update_idletasks()
162+
163+
def compress(self, row):
164+
new_row = [num for num in row if num != 0]
165+
166+
new_row += [0] * (GRID_SIZE - len(new_row))
167+
168+
return new_row
169+
170+
def merge(self, row):
171+
for i in range(GRID_SIZE - 1):
172+
if row[i] == row[i + 1] and row[i] != 0:
173+
row[i] *= 2
174+
self.score += row[i]
175+
row[i + 1] = 0
176+
177+
return row
178+
179+
def move_left(self):
180+
moved = False
181+
182+
new_board = []
183+
184+
for row in self.board:
185+
compressed = self.compress(row)
186+
merged = self.merge(compressed)
187+
final = self.compress(merged)
188+
189+
if final != row:
190+
moved = True
191+
192+
new_board.append(final)
193+
194+
self.board = new_board
195+
196+
return moved
197+
198+
def reverse(self):
199+
self.board = [row[::-1] for row in self.board]
200+
201+
def transpose(self):
202+
self.board = [list(row) for row in zip(*self.board)]
203+
204+
def move_right(self):
205+
self.reverse()
206+
moved = self.move_left()
207+
self.reverse()
208+
return moved
209+
210+
def move_up(self):
211+
self.transpose()
212+
moved = self.move_left()
213+
self.transpose()
214+
return moved
215+
216+
def move_down(self):
217+
self.transpose()
218+
moved = self.move_right()
219+
self.transpose()
220+
return moved
221+
222+
def check_game_over(self):
223+
for row in range(GRID_SIZE):
224+
for col in range(GRID_SIZE):
225+
if self.board[row][col] == 0:
226+
return False
227+
228+
if col < GRID_SIZE - 1:
229+
if self.board[row][col] == self.board[row][col + 1]:
230+
return False
231+
232+
if row < GRID_SIZE - 1:
233+
if self.board[row][col] == self.board[row + 1][col]:
234+
return False
235+
236+
return True
237+
238+
def handle_keypress(self, event):
239+
key = event.keysym
240+
241+
moved = False
242+
243+
if key == "Left":
244+
moved = self.move_left()
245+
246+
elif key == "Right":
247+
moved = self.move_right()
248+
249+
elif key == "Up":
250+
moved = self.move_up()
251+
252+
elif key == "Down":
253+
moved = self.move_down()
254+
255+
if moved:
256+
self.add_new_tile()
257+
258+
if self.score > self.high_score:
259+
self.high_score = self.score
260+
self.save_high_score()
261+
262+
self.update_grid()
263+
264+
if self.check_game_over():
265+
self.game_over()
266+
267+
def game_over(self):
268+
game_over_label = tk.Label(
269+
self.root,
270+
text="GAME OVER",
271+
font=("Arial", 24, "bold"),
272+
fg="red"
273+
)
274+
275+
game_over_label.grid(pady=10)
276+
277+
def restart_game(self):
278+
self.board = [[0] * GRID_SIZE for _ in range(GRID_SIZE)]
279+
self.score = 0
280+
281+
self.add_new_tile()
282+
self.add_new_tile()
283+
284+
self.update_grid()
285+
286+
287+
if __name__ == "__main__":
288+
root = tk.Tk()
289+
game = Game2048(root)
290+
root.mainloop()

games/2048-Game/highscore.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
516

web-app/index.html

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -238,6 +238,18 @@ <h3>Typing Speed Tester</h3>
238238
<p>Test your typing skills!</p>
239239
<button class="btn-play">Try It</button>
240240
</div>
241+
242+
<div class="project-card" data-category="games" data-project="game2048"
243+
data-tags="game,puzzle,2048,logic,tiles">
244+
245+
<div class="card-icon">🟦</div>
246+
247+
<h3>2048 Game</h3>
248+
249+
<p>Combine tiles and reach 2048!</p>
250+
251+
<button class="btn-play">Try It</button>
252+
</div>
241253
</div>
242254
</div>
243255
</section>

0 commit comments

Comments
 (0)