import tkinter as tk
import color as c
import random
class Game(tk.Frame):
def __init__(self):
tk.Frame.__init__(self)
self.grid()
self.master.title("2048")
self.main_grid = tk.Frame(
self,bg=c.GRID_COLOR,bd=3,width=600,height=600
)
self.main_grid.grid(pady=(100,0))
self.make_GUI()
self.start_game()
self.master.bind("<Left>",self.left)
self.master.bind("<Right>",self.right)
self.master.bind("<Up>",self.up)
self.master.bind("<Down>",self.down)
self.mainloop()
def make_GUI(self):
#make grid
self.cells = []
for i in range(4):
row = []
for j in range(4):
cell_frame = tk.Frame(
self.main_grid,bg=c.EMPTY_CELL_COLOR,width=150,height=150
)
cell_frame.grid(row=i,column=j,padx=5,pady=5)
cell_number = tk.Label(self.main_grid,bg=c.EMPTY_CELL_COLOR,)
cell_number.grid(row=i,column=j)
cell_data = {"frame": cell_frame,"number":cell_number}
row.append(cell_data)
self.cells.append(row)
#make score header
score_frame = tk.Frame(self)
score_frame.place(relx=0.5,y=45,anchor="center")
tk.Label(
score_frame,
text= "Score",
font=c.SCORE_LABEL_FONT
).grid(row=0)
self.score_label = tk.Label(score_frame,text="0",font=c.SCORE_FONT)
self.score_label.grid(row=1)
def start_game(self):
#create matrix with all zeros
self.matrix = [[0]*4 for _ in range(4)]
#fill 2 random cells with 2s
row = random.randint(0,3)
col = random.randint(0,3)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg=c.CELL_COLORS[2])
self.cells[row][col]["number"].configure(
bg=c.CELL_COLORS[2],
fg=c.CELL_COLORS[2],
font=c.CELL_COLORS[2],
text="2"
)
while(self.matrix[row][col] != 0):
row = random.randint(0,3)
col = random.randint(0,3)
self.matrix[row][col] = 2
self.cells[row][col]["frame"].configure(bg=c.CELL_COLORS[2])
self.cells[row][col]["number"].configure(
bg=c.CELL_COLORS[2],
fg=c.CELL_COLORS[2],
font=c.CELL_COLORS[2],
text="2"
)
self.score = 0
def stack(self):
new_matrix = [[0]* 4 for _ in range(4)]
for i in range(4):
fill_position = 0
for j in range(4):
if self.matrix[i][j] != 0:
new_matrix[i][fill_position] = self.matrix[i][j]
fill_position += 1
self.matrix = new_matrix
def combine(self):
for i in range(4):
for j in range(3):
if self.matrix[i][j] != 0 and self.matrix[i][j] == self.matrix[i][j + 1]:
self.matrix[i][j] *= 2
self.matrix[i][j + 1] = 0
self.score += self.matrix[i][j]
def reverse(self):
new_matrix = []
for i in range(4):
new_matrix.append([])
for j in range(4):
new_matrix[i].append(self.matrix[i][3-j])
self.matrix = new_matrix
def transpose(self):
new_matrix = [[0] * 4 for _ in range(4)]
for i in range(4):
for j in range(4):
new_matrix[i][j] = self.matrix[j][i]
self.matrix = new_matrix
def add_new_tile(self):
row = random.randint(0,3)
col = random.randint(0,3)
while(self.matrix[row][col] != 0):
row = random.randint(0,3)
col = random.randint(0,3)
self.matrix[row][col] = random.choice([2,4])
def update_GUI(self):
for i in range(4):
for j in range(4):
cell_value = self.matrix[i][j]
if cell_value == 0:
self.cells[i][j]["frame"].configure(bg=c.EMPTY_CELL_COLOR)
self.cells[i][j]["number"].configure(bg=c.EMPTY_CELL_COLOR,text="")
else:
self.cells[i][j]["frame"].configure(bg=c.CELL_COLORS[cell_value])
self.cells[i][j]["number"].configure(
bg=c.CELL_COLORS[cell_value],
fg=c.CELL_NUMBER_COLORS[cell_value],
font=c.CELL_NUMBER_FONTS[cell_value],
text=str(cell_value)
)
self.score_label.configure(text=self.score)
self.update_idletasks()
def left(self,event):
self.stack()
self.combine()
self.stack()
self.add_new_tile()
self.update_GUI()
self.game_over()
def right(self,event):
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.add_new_tile()
self.update_GUI()
self.game_over()
def up(self,event):
self.transpose()
self.stack()
self.combine()
self.stack()
self.transpose()
self.add_new_tile()
self.update_GUI()
self.game_over()
def down(self,event):
self.transpose()
self.reverse()
self.stack()
self.combine()
self.stack()
self.reverse()
self.transpose()
self.add_new_tile()
self.update_GUI()
self.game_over()
def horizontal_move_exists(self):
for i in range(4):
for j in range(3):
if self.matrix[i][j] == self.matrix[i][j+1]:
return True
return False
def vertial_move_exists(self):
for i in range(3):
for j in range(4):
if self.matrix[i][j] == self.matrix[i+1][j]:
return True
return False
def game_over(self):
if any(2048 in row for row in self.matrix):
game_over_frame = tk.Frame(self.main_grid,borderwidth=2)
game_over_frame.place(relx=0.5,rely=0.5,anchor="center")
tk.Label(
game_over_frame,
text="YOU WIN!",
bg=c.WINNER_BG,
fg=c.GAME_OVER_FONT_COLOR,
font=c.GAME_OVER_FONT
).pack()
elif not any(0 in row for row in self.matrix) and not self.horizontal_move_exists() and not self.vertial_move_exists:
game_over_frame = tk.Frame(self.main_grid,borderwidth=2)
game_over_frame.place(relx=0.5,rely=0.5,anchor="center")
tk.Label(
game_over_frame,
text="GAME OVER!",
bg=c.LOSER_BG,
fg=c.GAME_OVER_FONT_COLOR,
font=c.GAME_OVER_FONT
).pack()
def main():
Game()
if __name__ == "__main__":
main()
color.py
GRID_COLOR = "#a39489"
EMPTY_CELL_COLOR = "#c2b3a9"
SCORE_LABEL_FONT = ("Verdana", 20)
SCORE_FONT = ("Helvetica", 32, "bold")
GAME_OVER_FONT = ("Helvetica", 48, "bold")
GAME_OVER_FONT_COLOR = "#ffffff"
WINNER_BG = "#ffcc00"
LOSER_BG = "#a39489"
CELL_COLORS = {
2: "#fcefe6",
4: "#f2e8cb",
8: "#f5b682",
16: "#f29446",
32: "#ff775c",
64: "#e64c2e",
128: "#ede291",
256: "#fce130",
512: "#ffdb4a",
1024: "#f0b922",
2048: "#fad74d"
}
CELL_NUMBER_COLORS = {
2: "#695c57",
4: "#695c57",
8: "#ffffff",
16: "#ffffff",
32: "#ffffff",
64: "#ffffff",
128: "#ffffff",
256: "#ffffff",
512: "#ffffff",
1024: "#ffffff",
2048: "#ffffff"
}
CELL_NUMBER_FONTS = {
2: ("Helvetica", 55, "bold"),
4: ("Helvetica", 55, "bold"),
8: ("Helvetica", 55, "bold"),
16: ("Helvetica", 50, "bold"),
32: ("Helvetica", 50, "bold"),
64: ("Helvetica", 50, "bold"),
128: ("Helvetica", 45, "bold"),
256: ("Helvetica", 45, "bold"),
512: ("Helvetica", 45, "bold"),
1024: ("Helvetica", 40, "bold"),
2048: ("Helvetica", 40, "bold")
}
我沒寫過 python 也不知道這遊戲在玩什麼
不過這程式的問題是在 add_new_tile()
當畫面上 16 個格子都有大於 0 的數字存在時,主程式 121 那個 while 迴圈就會無限巡迴
該處理的可能也不是 add_new_tile()
而是遊戲結束的判斷條件
也可能兩個都要處理
看看 game_over(self)
的邏輯對不對吧,如果格子填滿就要判斷遊戲是否結束,那 add_new_tile()
就不用修,要修的是判斷條件
因為是看著教程寫的,所以邏輯上應該不會有問題。我覺得可能是哪裡遺漏了什麼,我再看看把
在 121 行那個 while 迴圈前面加個判斷式就不會變成無窮迴圈
def add_new_tile(self):
row = random.randint(0,3)
col = random.randint(0,3)
if any(0 in row for row in self.matrix):
while(self.matrix[row][col] != 0):
row = random.randint(0,3)
col = random.randint(0,3)
self.matrix[row][col] = random.choice([2,4])
你如果是複製貼上,那表示教學本來的程式就有問題。
如果是自己看著打,就可能就是你打錯
例如 210 行
elif not any(0 in row for row in self.matrix) and not self.horizontal_move_exists() and not self.vertial_move_exists:
self.vertial_move_exists 就沒加括號
Hello! I'm glad to hear that you've resolved the issue with your 2048 game. If you enjoy this type of game, you might want to try Blokc Blast at blockblast-online.io. It's another fun puzzle game that you might like! Wishing you enjoyable moments of relaxation!