用python制作2048游戏

import tkinter as tk
from tkinter import messagebox
import random
import math

class Game2048:
    def __init__(self):
        self.window = tk.Tk()
        self.window.title("2048 游戏")
        self.window.geometry("500x600")
        self.window.resizable(False, False)
        self.window.configure(bg='#FAF8EF')
        
        # 游戏状态
        self.grid_size = 4
        self.cell_size = 100
        self.padding = 10
        self.grid = [[0 for _ in range(self.grid_size)] for _ in range(self.grid_size)]
        self.score = 0
        self.high_score = 0
        self.game_over = False
        self.won = False
        
        # 颜色配置
        self.colors = {
            0: ("#CDC1B4", "#776E65", ""),
            2: ("#EEE4DA", "#776E65", "2"),
            4: ("#EDE0C8", "#776E65", "4"),
            8: ("#F2B179", "#F9F6F2", "8"),
            16: ("#F59563", "#F9F6F2", "16"),
            32: ("#F67C5F", "#F9F6F2", "32"),
            64: ("#F65E3B", "#F9F6F2", "64"),
            128: ("#EDCF72", "#F9F6F2", "128"),
            256: ("#EDCC61", "#F9F6F2", "256"),
            512: ("#EDC850", "#F9F6F2", "512"),
            1024: ("#EDC53F", "#F9F6F2", "1024"),
            2048: ("#EDC22E", "#F9F6F2", "2048"),
            4096: ("#3C3A32", "#F9F6F2", "4096"),
            8192: ("#3C3A32", "#F9F6F2", "8192")
        }
        
        self.setup_ui()
        self.start_game()
        
    def setup_ui(self):
        """设置游戏界面"""
        # 标题
        title_frame = tk.Frame(self.window, bg='#FAF8EF')
        title_frame.pack(pady=10)
        
        title_label = tk.Label(
            title_frame, 
            text="2048", 
            font=("Arial", 40, "bold"),
            fg="#776E65",
            bg='#FAF8EF'
        )
        title_label.pack(side=tk.LEFT, padx=20)
        
        # 分数显示
        score_frame = tk.Frame(title_frame, bg='#FAF8EF')
        score_frame.pack(side=tk.RIGHT, padx=20)
        
        self.score_label = tk.Label(
            score_frame,
            text=f"分数: {self.score}",
            font=("Arial", 14, "bold"),
            fg="white",
            bg="#BBADA0",
            padx=10,
            pady=5
        )
        self.score_label.pack(pady=2)
        
        self.high_score_label = tk.Label(
            score_frame,
            text=f"最高分: {self.high_score}",
            font=("Arial", 14, "bold"),
            fg="white",
            bg="#BBADA0",
            padx=10,
            pady=5
        )
        self.high_score_label.pack(pady=2)
        
        # 游戏说明
        instruction_label = tk.Label(
            self.window,
            text="使用方向键移动方块,相同数字合并加倍!",
            font=("Arial", 12),
            fg="#776E65",
            bg='#FAF8EF'
        )
        instruction_label.pack(pady=5)
        
        # 游戏画布
        self.canvas = tk.Canvas(
            self.window,
            width=self.grid_size * self.cell_size + (self.grid_size + 1) * self.padding,
            height=self.grid_size * self.cell_size + (self.grid_size + 1) * self.padding,
            bg='#FAF8EF',
            highlightthickness=0
        )
        self.canvas.pack(pady=20)
        
        # 控制按钮框架
        button_frame = tk.Frame(self.window, bg='#FAF8EF')
        button_frame.pack(pady=10)
        
        restart_btn = tk.Button(
            button_frame,
            text="重新开始",
            font=("Arial", 12, "bold"),
            command=self.restart_game,
            bg="#8F7A66",
            fg="white",
            padx=20,
            pady=10
        )
        restart_btn.pack(side=tk.LEFT, padx=10)
        
        exit_btn = tk.Button(
            button_frame,
            text="退出游戏",
            font=("Arial", 12, "bold"),
            command=self.window.quit,
            bg="#8F7A66",
            fg="white",
            padx=20,
            pady=10
        )
        exit_btn.pack(side=tk.LEFT, padx=10)
        
        # 绑定键盘事件
        self.window.bind('<Key>', self.handle_keypress)
        self.window.focus_set()
        
    def start_game(self):
        """开始新游戏"""
        self.grid = [[0 for _ in range(self.grid_size)] for _ in range(self.grid_size)]
        self.score = 0
        self.game_over = False
        self.won = False
        self.add_random_tile()
        self.add_random_tile()
        self.draw_grid()
        
    def add_random_tile(self):
        """在随机空白位置添加新方块"""
        empty_cells = [
            (i, j) 
            for i in range(self.grid_size) 
            for j in range(self.grid_size) 
            if self.grid[i][j] == 0
        ]
        
        if empty_cells:
            i, j = random.choice(empty_cells)
            # 90% 概率生成 2,10% 概率生成 4
            self.grid[i][j] = 2 if random.random() < 0.9 else 4
            
    def draw_grid(self):
        """绘制游戏网格"""
        self.canvas.delete("all")
        
        # 绘制背景网格
        for i in range(self.grid_size):
            for j in range(self.grid_size):
                x = j * (self.cell_size + self.padding) + self.padding
                y = i * (self.cell_size + self.padding) + self.padding
                
                # 获取颜色
                value = self.grid[i][j]
                bg_color, text_color, text = self.colors.get(
                    value, 
                    ("#3C3A32", "#F9F6F2", str(value))
                )
                
                # 绘制方块
                self.canvas.create_rectangle(
                    x, y, x + self.cell_size, y + self.cell_size,
                    fill=bg_color, outline="", width=0,
                    tags=f"cell_{i}_{j}"
                )
                
                # 绘制数字
                if value != 0:
                    font_size = 40 if value < 100 else 36 if value < 1000 else 30
                    self.canvas.create_text(
                        x + self.cell_size // 2, 
                        y + self.cell_size // 2,
                        text=text,
                        font=("Arial", font_size, "bold"),
                        fill=text_color,
                        tags=f"text_{i}_{j}"
                    )
        
        # 更新分数显示
        self.score_label.config(text=f"分数: {self.score}")
        self.high_score_label.config(text=f"最高分: {max(self.score, self.high_score)}")
        
    def handle_keypress(self, event):
        """处理键盘输入"""
        if self.game_over:
            return
            
        moved = False
        
        if event.keysym in ['Up', 'w', 'W']:
            moved = self.move_up()
        elif event.keysym in ['Down', 's', 'S']:
            moved = self.move_down()
        elif event.keysym in ['Left', 'a', 'A']:
            moved = self.move_left()
        elif event.keysym in ['Right', 'd', 'D']:
            moved = self.move_right()
            
        if moved:
            self.add_random_tile()
            self.draw_grid()
            self.check_game_state()
            
    def move_left(self):
        """向左移动"""
        moved = False
        for i in range(self.grid_size):
            # 压缩行
            row = [num for num in self.grid[i] if num != 0]
            # 合并相同数字
            for j in range(len(row) - 1):
                if row[j] == row[j + 1]:
                    row[j] *= 2
                    self.score += row[j]
                    row[j + 1] = 0
                    moved = True
            # 再次压缩
            row = [num for num in row if num != 0]
            # 填充0
            row.extend([0] * (self.grid_size - len(row)))
            
            if self.grid[i] != row:
                moved = True
            self.grid[i] = row
            
        return moved
    
    def move_right(self):
        """向右移动"""
        moved = False
        for i in range(self.grid_size):
            # 压缩行
            row = [num for num in self.grid[i] if num != 0]
            # 合并相同数字
            for j in range(len(row) - 1, 0, -1):
                if row[j] == row[j - 1]:
                    row[j] *= 2
                    self.score += row[j]
                    row[j - 1] = 0
                    moved = True
            # 再次压缩
            row = [num for num in row if num != 0]
            # 填充0
            row = [0] * (self.grid_size - len(row)) + row
            
            if self.grid[i] != row:
                moved = True
            self.grid[i] = row
            
        return moved
    
    def move_up(self):
        """向上移动"""
        moved = False
        for j in range(self.grid_size):
            # 获取列
            column = [self.grid[i][j] for i in range(self.grid_size)]
            # 压缩列
            column = [num for num in column if num != 0]
            # 合并相同数字
            for i in range(len(column) - 1):
                if column[i] == column[i + 1]:
                    column[i] *= 2
                    self.score += column[i]
                    column[i + 1] = 0
                    moved = True
            # 再次压缩
            column = [num for num in column if num != 0]
            # 填充0
            column.extend([0] * (self.grid_size - len(column)))
            
            # 更新列
            for i in range(self.grid_size):
                if self.grid[i][j] != column[i]:
                    moved = True
                self.grid[i][j] = column[i]
                
        return moved
    
    def move_down(self):
        """向下移动"""
        moved = False
        for j in range(self.grid_size):
            # 获取列
            column = [self.grid[i][j] for i in range(self.grid_size)]
            # 压缩列
            column = [num for num in column if num != 0]
            # 合并相同数字
            for i in range(len(column) - 1, 0, -1):
                if column[i] == column[i - 1]:
                    column[i] *= 2
                    self.score += column[i]
                    column[i - 1] = 0
                    moved = True
            # 再次压缩
            column = [num for num in column if num != 0]
            # 填充0
            column = [0] * (self.grid_size - len(column)) + column
            
            # 更新列
            for i in range(self.grid_size):
                if self.grid[i][j] != column[i]:
                    moved = True
                self.grid[i][j] = column[i]
                
        return moved
    
    def check_game_state(self):
        """检查游戏状态"""
        # 检查是否获胜
        if any(2048 in row for row in self.grid) and not self.won:
            self.won = True
            if messagebox.askyesno("恭喜!", "你达到了2048!是否继续游戏?"):
                return
            else:
                self.restart_game()
                return
                
        # 检查游戏是否结束
        if not any(0 in row for row in self.grid):
            # 检查是否还能移动
            can_move = False
            for i in range(self.grid_size):
                for j in range(self.grid_size):
                    if j < self.grid_size - 1 and self.grid[i][j] == self.grid[i][j + 1]:
                        can_move = True
                    if i < self.grid_size - 1 and self.grid[i][j] == self.grid[i + 1][j]:
                        can_move = True
                        
            if not can_move:
                self.game_over = True
                if messagebox.askyesno("游戏结束", f"游戏结束!最终分数: {self.score}\n是否重新开始?"):
                    self.restart_game()
                else:
                    self.window.quit()
    
    def restart_game(self):
        """重新开始游戏"""
        self.high_score = max(self.score, self.high_score)
        self.start_game()
        
    def run(self):
        """运行游戏"""
        self.window.mainloop()

if __name__ == "__main__":
    game = Game2048()
    game.run()

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值