python快速实现2048小游戏

news2024/11/26 20:42:45

《2048》是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。这款游戏是基于《1024》和《小3传奇》的玩法开发而成的新型数字游戏。

操作指南:

每次可以选择上下左右其中一个方向去滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢外,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢、相撞时会相加。不断的叠加最终拼凑出2048这个数字就算成功。

游戏技巧:

  1. 最大数尽可能放在角落。

  2. 数字按顺序紧邻排列。

  3. 首先满足最大数和次大数在的那一列/行是满的。

  4. 时刻注意活动较大数(32以上)旁边要有相近的数。

  5. 以大数所在的一行为主要移动方向

  6. 不要急于“清理桌面”。

完整代码如下:

logic.py

import random
import constants as c



def new_game(n):
    matrix = []
    for i in range(n):
        matrix.append([0] * n)
    matrix = add_two(matrix)
    matrix = add_two(matrix)
    return matrix



def add_two(mat):
    a = random.randint(0, len(mat)-1)
    b = random.randint(0, len(mat)-1)
    while mat[a][b] != 0:
        a = random.randint(0, len(mat)-1)
        b = random.randint(0, len(mat)-1)
    mat[a][b] = 2
    return mat



def game_state(mat):
    # check for win cell
    for i in range(len(mat)):
        for j in range(len(mat[0])):
            if mat[i][j] == 2048:
                return 'win'
    # check for any zero entries
    for i in range(len(mat)):
        for j in range(len(mat[0])):
            if mat[i][j] == 0:
                return 'not over'
    # check for same cells that touch each other
    for i in range(len(mat)-1):
        # intentionally reduced to check the row on the right and below
        # more elegant to use exceptions but most likely this will be their solution
        for j in range(len(mat[0])-1):
            if mat[i][j] == mat[i+1][j] or mat[i][j+1] == mat[i][j]:
                return 'not over'
    for k in range(len(mat)-1):  # to check the left/right entries on the last row
        if mat[len(mat)-1][k] == mat[len(mat)-1][k+1]:
            return 'not over'
    for j in range(len(mat)-1):  # check up/down entries on last column
        if mat[j][len(mat)-1] == mat[j+1][len(mat)-1]:
            return 'not over'
    return 'lose'



def reverse(mat):
    new = []
    for i in range(len(mat)):
        new.append([])
        for j in range(len(mat[0])):
            new[i].append(mat[i][len(mat[0])-j-1])
    return new



def transpose(mat):
    new = []
    for i in range(len(mat[0])):
        new.append([])
        for j in range(len(mat)):
            new[i].append(mat[j][i])
    return new



def cover_up(mat):
    new = []
    for j in range(c.GRID_LEN):
        partial_new = []
        for i in range(c.GRID_LEN):
            partial_new.append(0)
        new.append(partial_new)
    done = False
    for i in range(c.GRID_LEN):
        count = 0
        for j in range(c.GRID_LEN):
            if mat[i][j] != 0:
                new[i][count] = mat[i][j]
                if j != count:
                    done = True
                count += 1
    return new, done

def merge(mat, done):
    for i in range(c.GRID_LEN):
        for j in range(c.GRID_LEN-1):
            if mat[i][j] == mat[i][j+1] and mat[i][j] != 0:
                mat[i][j] *= 2
                mat[i][j+1] = 0
                done = True
    return mat, done

def up(game):
    print("up")
    # return matrix after shifting up
    game = transpose(game)
    game, done = cover_up(game)
    game, done = merge(game, done)
    game = cover_up(game)[0]
    game = transpose(game)
    return game, done

def down(game):
    print("down")
    # return matrix after shifting down
    game = reverse(transpose(game))
    game, done = cover_up(game)
    game, done = merge(game, done)
    game = cover_up(game)[0]
    game = transpose(reverse(game))
    return game, done

def left(game):
    print("left")
    # return matrix after shifting left
    game, done = cover_up(game)
    game, done = merge(game, done)
    game = cover_up(game)[0]
    return game, done

def right(game):
    print("right")
    # return matrix after shifting right
    game = reverse(game)
    game, done = cover_up(game)
    game, done = merge(game, done)
    game = cover_up(game)[0]
    game = reverse(game)
    return game, done

constants.py

SIZE = 400
GRID_LEN = 4
GRID_PADDING = 10

BACKGROUND_COLOR_GAME = "#92877d"
BACKGROUND_COLOR_CELL_EMPTY = "#9e948a"

BACKGROUND_COLOR_DICT = {
2:      "#eee4da",
4:      "#ede0c8",
8:      "#f2b179",
16:     "#f59563",
32:     "#f67c5f",
64:     "#f65e3b",
128:    "#edcf72",
256:    "#edcc61",
512:    "#edc850",
1024:   "#edc53f",
2048:   "#edc22e",
4096:   "#eee4da",
8192:   "#edc22e",
16384:  "#f2b179",
32768:  "#f59563",
65536:  "#f67c5f",
}

CELL_COLOR_DICT = {
2:      "#776e65",
4:      "#776e65",
8:      "#f9f6f2",
16:     "#f9f6f2",
32:     "#f9f6f2",
64:     "#f9f6f2",
128:    "#f9f6f2",
256:    "#f9f6f2",
512:    "#f9f6f2",
1024:   "#f9f6f2",
2048:   "#f9f6f2",
4096:   "#776e65",
8192:   "#f9f6f2",
16384:  "#776e65",
32768:  "#776e65",
65536:  "#f9f6f2",
}

FONT = ("Verdana",40,"bold")

KEY_QUIT = "Escape"
KEY_BACK = "b"

KEY_UP = "Up"
KEY_DOWN = "Down"
KEY_LEFT = "Left"
KEY_RIGHT = "Right"

KEY_UP_ALT1 = "w"
KEY_DOWN_ALT1 = "s"
KEY_LEFT_ALT1 = "a"
KEY_RIGHT_ALT1 = "d"

KEY_UP_ALT2 = "i"
KEY_DOWN_ALT2 = "k"
KEY_LEFT_ALT2 = "j"
KEY_RIGHT_ALT2 = "l"

run.py

from tkinter import Frame, Label, CENTER
import random
import logic
import constants as c

def gen():
    return random.randint(0, c.GRID_LEN - 1)

class GameGrid(Frame):
    def __init__(self):
        Frame.__init__(self)

        self.grid()
        self.master.title('2048')
        self.master.bind("<Key>", self.key_down)

        self.commands = {
            c.KEY_UP: logic.up,
            c.KEY_DOWN: logic.down,
            c.KEY_LEFT: logic.left,
            c.KEY_RIGHT: logic.right,
            c.KEY_UP_ALT1: logic.up,
            c.KEY_DOWN_ALT1: logic.down,
            c.KEY_LEFT_ALT1: logic.left,
            c.KEY_RIGHT_ALT1: logic.right,
            c.KEY_UP_ALT2: logic.up,
            c.KEY_DOWN_ALT2: logic.down,
            c.KEY_LEFT_ALT2: logic.left,
            c.KEY_RIGHT_ALT2: logic.right,
        }

        self.grid_cells = []
        self.init_grid()
        self.matrix = logic.new_game(c.GRID_LEN)
        self.history_matrixs = []
        self.update_grid_cells()

        self.mainloop()

    def init_grid(self):
        background = Frame(self, bg=c.BACKGROUND_COLOR_GAME,width=c.SIZE, height=c.SIZE)
        background.grid()

        for i in range(c.GRID_LEN):
            grid_row = []
            for j in range(c.GRID_LEN):
                cell = Frame(
                    background,
                    bg=c.BACKGROUND_COLOR_CELL_EMPTY,
                    width=c.SIZE / c.GRID_LEN,
                    height=c.SIZE / c.GRID_LEN
                )
                cell.grid(
                    row=i,
                    column=j,
                    padx=c.GRID_PADDING,
                    pady=c.GRID_PADDING
                )
                t = Label(
                    master=cell,
                    text="",
                    bg=c.BACKGROUND_COLOR_CELL_EMPTY,
                    justify=CENTER,
                    font=c.FONT,
                    width=5,
                    height=2)
                t.grid()
                grid_row.append(t)
            self.grid_cells.append(grid_row)

    def update_grid_cells(self):
        for i in range(c.GRID_LEN):
            for j in range(c.GRID_LEN):
                new_number = self.matrix[i][j]
                if new_number == 0:
                    self.grid_cells[i][j].configure(text="",bg=c.BACKGROUND_COLOR_CELL_EMPTY)
                else:
                    self.grid_cells[i][j].configure(
                        text=str(new_number),
                        bg=c.BACKGROUND_COLOR_DICT[new_number],
                        fg=c.CELL_COLOR_DICT[new_number]
                    )
        self.update_idletasks()

    def key_down(self, event):
        key = event.keysym
        print(event)
        if key == c.KEY_QUIT: exit()
        if key == c.KEY_BACK and len(self.history_matrixs) > 1:
            self.matrix = self.history_matrixs.pop()
            self.update_grid_cells()
            print('back on step total step:', len(self.history_matrixs))
        elif key in self.commands:
            self.matrix, done = self.commands[key](self.matrix)
            if done:
                self.matrix = logic.add_two(self.matrix)
                # record last move
                self.history_matrixs.append(self.matrix)
                self.update_grid_cells()
                if logic.game_state(self.matrix) == 'win':
                    self.grid_cells[1][1].configure(text="You", bg=c.BACKGROUND_COLOR_CELL_EMPTY)
                    self.grid_cells[1][2].configure(text="Win!", bg=c.BACKGROUND_COLOR_CELL_EMPTY)
                if logic.game_state(self.matrix) == 'lose':
                    self.grid_cells[1][1].configure(text="You", bg=c.BACKGROUND_COLOR_CELL_EMPTY)
                    self.grid_cells[1][2].configure(text="Lose!", bg=c.BACKGROUND_COLOR_CELL_EMPTY)

    def generate_next(self):
        index = (gen(), gen())
        while self.matrix[index[0]][index[1]] != 0:
            index = (gen(), gen())
        self.matrix[index[0]][index[1]] = 2

game_grid = GameGrid()

操作方式:

方向键:上下左右

26键中的:WSAD

26键中的:IKJL

ESC键退出游戏,b键返回上一步

为增加游戏可玩性,此游戏最大叠加数为65536

运行结果如下所示:

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/68151.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

景区票务系统毕业设计,景区售票系统设计与实现,旅游售票系统毕业设计源码分析

项目背景和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于java的景区景点预约购票系统&#xff0c;整体使用javaMySql的B/S架构&#xff0c;技术上采用了springboot框架&#xff1b;通过后台添加景区资讯、景点介绍&#xff0c;管理用户订单&#xff1b;用户通过…

Vue怎么通过JSX动态渲染组件

一、明确需求 有一组数组结构如下&#xff1a; const arr [ { tag: van-field }, // 输入框{ tag: van-cell }, // 弹出层{ tag: van-stepper } // 步进器 ] 想通过循环arr&#xff0c;拿到tag渲染对应的组件。 下面我们分析如何写才是最优。 二、进行分析 2.1 v-if走天…

JavaScript期末大作业:基于HTML+CSS+JavaScript黑色的bootstrap响应式企业博客介绍模板

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

JTable详细介绍

目录 一、基本表格 二、修改列宽并显示列的名称 三、使用AbstractTableModel抽象类存储数据 一、基本表格 显示一个Table需要两组数据 1. 一维数组&#xff1a; String[]columnNames 表示表格的标题 2. 二维数组&#xff1a; String[][] heros 表格中的内容 默认情况下&…

使用openssl工具生成CSR文件

使用OpenSSL工具生成CSR文件 登录服务器。 安装OpenSSL工具。 执行以下命令&#xff0c;生成CSR文件。 openssl req -new -nodes -sha256 -newkey rsa:2048 -keyout [$Key_File] -out [$OpenSSL_CSR] 说明 -new&#xff1a;指定生成一个新的CSR文件。 -nodes&#xff1a;指定…

WindowsNT下的OpenGL

三、WindowsNT下的OpenGL 3.1、Windows NT下的OpenGL函数   如前面的章节所述&#xff0c;Windows NT下的OpenGL同样包含100多个库函数&#xff0c;这些函数都按一定的格式来命名&#xff0c;即每个函数都以gl开头。Windows NT下的OpenGL除了具有基本的OpenGL函数外&#xf…

威马汽车欲曲线上市:沈晖已提前持股并任职,销量垫底、员工降薪

12月5日&#xff0c;港交所上市公司Apollo出行&#xff08;HK:00860&#xff09;发布公告称&#xff0c;该公司拟收购一家从事智能电动车的公司&#xff0c;目标公司的业务涵盖一系列配备先进技术的智能电动车&#xff0c;目标客户为中国年轻且精通技术的用户&#xff08;特别是…

小迪-day14(注入类型之提交注入)

1、参数提交注入 1.1 明确参数类型 数字&#xff0c;字符&#xff0c;搜索&#xff0c;JSON等1.2 明确提交方式 GET, POST,COOKIE,REQUEST&#xff0c;HTTP头等可能有些网站是以Request的方式接受参数&#xff0c;所以GET和POST都行 注入的地方可能在User-Agent、cookie上&a…

辽宁熤星传媒文化:抖音原创特效怎么做?

现在很多小伙伴在家都基本上会去找一些副业来做&#xff0c;或者是一些赚钱的方法&#xff0c;要知道&#xff0c;抖音其实还是有很多赚钱的机遇在里面的&#xff0c;那么大家拍抖音都是需要去使用特效的&#xff0c;那么抖音特效应该怎么做呢&#xff1f;跟着辽宁熤星传媒小编…

探索可观测性:AIOps中的时序数据应用

01. 背景 随着科技的发展&#xff0c;时序数据在我们的认知中占据越来越多的位置&#xff0c;小到电子元件在每个时刻的状态&#xff0c;大到世界每天的新冠治愈人数&#xff0c;一切可观测&#xff0c;可度量&#xff0c;可统计的数据只要带上了时间这个重要的因素就会成为时…

Antlr4 快速入门 - 编写语法解析器

Antlr全称(ANother Tool for Language Recognition)&#xff0c;Antlr4是一款强大的语法分析器生成工具&#xff0c;推特&#xff0c;Haddop&#xff0c;Oracle等各大知名公司在用到了Antlr来构建自己的语言处理类项目。 一门语言的正式描述称为语法(grammar)&#xff0c;Antl…

计算机考研报名人数下降一半!211北京科技大学计算机报考人数公布!

北京科技大学是一所211大学&#xff0c;计算机学科评估B&#xff0c;计算机实力在211大学中还算不错。前段时间&#xff0c;北京科技大学公布了23考研的报考人数&#xff0c;而且详细到了各个专业的人数&#xff1a;北京科技大学2023年硕士研究生各招生专业准考人数统计表https…

PyQt5页面跳转问题及解决方式

问题1&#xff1a;如何实现页面间跳转 主要定义MainWindow类和Actions.py class MainWindow&#xff1a; Actions.py&#xff1a; 问题2&#xff1a;实现定义函数传参功能 大胆修改&#xff0c;将定义函数的参数值改为a&#xff1b;使用函数处将参数加上&#xff1a; 运行&…

腾讯云动态公网IP绑定域名实现内网服务器公网穿透

公众号推广: 目前CSDN进行VIP可见,文章可在微信公众号进行免费的阅读。 文章内容经过认证实践,比较的清晰易懂,适合初次接触的人员。 目录 公众号推广: 需求场景: 解决方案: 实现方案:

1.5.4 HDFS 客户端操作-hadoop-最全最完整的保姆级的java大数据学习资料

文章目录1.5.4 HDFS 客户端操作1.5.4.1 Shell 命令行操作HDFS1.5.4.2 JAVA客户端1.5.4.2.1 客户端环境准备1.5.4.2.2 HDFS的API操作1.5.4.2.2.1 上传文件1.5.4.2.2.2 下载文件1.5.4.2.2.3 删除文件/文件夹1.5.4.2.2.4 查看文件名称、权限、长度、块信息1.5.4.2.2.5 文件夹判断1…

Letbook Cookbook题单——数组2

Letbook Cookbook题单——数组2 39. 组合总和 难度中等 给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target &#xff0c;找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 &#xff0c;并以列表形式返回。你可以按 任意顺序 返回这些组合。…

Qgis加载arcgis的gdb格式数据

方式1&#xff1a;文件浏览器打开可直接看到图层&#xff0c;拖到可视区域即可。 方式2&#xff1a;gdb文件夹拖到可视区域即可。 方式3&#xff1a;图层-矢量-目录 该gdb可能没有坐标信息&#xff0c;需要跟甲方询问或者自己尝试

安卓APP源码和设计报告——快递查询录入系统

《多媒体通信技术》 题 目&#xff1a;快递 完 成 日 期 2022年05月 目 录 1 绪论1 2 设计方案2 2.1 设计思路和方案2 2.2 功能要求2 2.3 设计的流程图2 3 设计过程3 3.1 界面布局3 3.2 功能实现3 4 运行结果与分析4 4.1 设计的使用步骤4 4.2 运行结果与分析4 5 …

【数据结构】—带头双向循环链表的实现(完美链表)

目录前言链表的实现新节点的创建链表初始化尾插与尾删头插与头删查找数据在任意位置的插入与删除链表的销毁总结前言 链表结构一共有八种形式&#xff0c;在前面的文章里已经讲完了不带头单向非循环链表的实现&#xff0c;但是我们发现该链表实现尾插与尾删时比较麻烦&#xff…