用Python做一个2048小游戏

news2024/12/22 12:53:11

文章目录

    • 逻辑设计
    • 绘图逻辑
    • 主循环

逻辑设计

2048的逻辑无非是操作 4 × 4 4\times4 4×4的方格,每个方格中有一个数,这些数可以移动,如果两个相同的数字在移动时相撞了,就可以彼此合并。

而这个 4 × 4 4\times4 4×4的方格,无非是一个矩阵。只需设计好移动逻辑,再用PyGame将这个方格表现出来就算大功告成。

2048只有四个手势动作,即上下左右,这四个动作所引发的结果都可以归结为对单行或者单列的操作,进而归结为对一个列表的操作。

首先,对列表进行操作时,先排除0的影响,在排除0的影响之后,若相邻元素相等,即可合并。例如对于 [ 0 , 2 , 2 , 0 ] [0,2,2,0] [0,2,2,0],如果向左合并则输出为 [ 4 , 0 , 0 , 0 ] [4,0,0,0] [4,0,0,0]

def mergeLst(lst):
    lst = [x for x in lst if x] # 删除lst中的0
    newLst = []
    N, i = len(lst), 0
    while i < N:
        if i<N-1 and lst[i] == lst[i+1]:
            newLst.append(lst[i]*2)
            i += 2
        else:
            newLst.append(lst[i])
            i += 1
    return newLst + (4-len(newLst))*[0]

测试如下

mergeLst([0,2,2,0]) # [4, 0, 0, 0]
mergeLst([2,2,2,2]) # [4, 4, 0, 0]
mergeLst([2,2,8,4]) # [4, 8, 4, 0]

相应地,对一个矩阵进行合并,只需针对每一行进行操作即可

[mergeLst(x) for x in mat]

对于上下左右不同按键的操作,可以先将矩阵旋转,然后再进行合并操作,合并之后再逆转回来。

def rotate(mat):
    newMat = [[[] for _ in mat] for b in mat[0]]
    for i,row in enumerate(mat, 1):
        for j,r in enumerate(row, 0):
            newMat[j][-i] = r
    return newMat

在实际操作中,左、下、右、上分别对应旋转0,1,2,3次,即

KEY_DCT = {
    pygame.K_LEFT:0,   pygame.K_DOWN:1,
    pygame.K_RIGHT:2,  pygame.K_UP:3
}

从而游戏的总挪动逻辑如下

def updateMat(mat, key):
    N = KEY_DCT[key]
    for _ in range(N):
        mat = rotate(mat)
    mat = [mergeLst(x) for x in mat]
    for _ in range(4-N):
        mat = rotate(mat)   # 旋转回来
    return mat

2048游戏在开始之前,需要初始化一个4x4的矩阵,然后每次操作之前,需要在矩阵中为0的位置随机生成一个数。随机生成的数的取值范围决定了游戏的难度,所以生成方式也比较灵活,下面给出一种普通的生成方法

from itertools import product
from random import sample, randint
def addNew(mat):
    ijs = []
    for i,j in product(range(4), range(4)):
        if mat[i][j] == 0:
            ijs.appen((i,j))
    if len(ijs) == 0:
        return False
    i, j = sample(ijs, 1)[0]   # 挑选一个不为0的点
    x = randint(1,100)
    x = 7 - np.floor(np.log2(x))
    mat[i,j] = int(2**x)
    return True

绘图逻辑

这个游戏的绘图逻辑比较简单,只需为矩阵中每个元素赋予一个颜色即可。

GRAY = (205, 205, 205)
WHITE = (255, 255, 255)
GREEN = (0, 255, 0)
SIZE = 80

def setColor(N):
    if N == 0:
        return (233, 233, 233)
    n = int(math.log2(N))
    delta = int(255/15)
    return (255-n*delta, n*delta, (128+n*delta)%255)


def draw(win, font, mat):
    for i,j in product(range(4), range(4)):
        ch = str(mat[i][j])
        rect = (j*SIZE, i*SIZE, SIZE, SIZE)
        c = setColor(mat[i][j])
        pygame.draw.rect(win, c, rect)
        pygame.draw.rect(win, GRAY, rect, 5)

        txt = font.render(ch, True, GREEN)
        offset =  (0.5 - len(ch)/10)*SIZE
        xy = (j*SIZE+offset, (i+0.3)*SIZE)
        win.blit(txt, xy)

主循环

最后,实现游戏的主循环如下

def gui():
    pygame.init()
    win = pygame.display.set_mode(
        (4 * SIZE, 4 * SIZE))
    pygame.display.set_caption("迷宫游戏")
    font.init()
    f = font.Font('C:\\WINDOWS\\Fonts\\ARLRDBD.TTF', 32)
    running = True

    mat = [[0]*4 for _ in range(4)]
    addNew(mat)
    while running:
        win.fill(WHITE)
        for evt in pygame.event.get():
            if evt.type == pygame.QUIT:
                return
            if evt.type == pygame.KEYDOWN and evt.key in KEY_DCT:
                newMat = updateMat(mat, evt.key)
                if newMat!=mat:
                    mat = newMat
                    running = addNew(mat)
        draw(win, f, mat)
        # 判断玩家是否到达出口
        if max([max(x) for x in mat])==2048:
            print("恭喜通关")
            running = False
        if min([min(x) for x in mat])>0:
            print("游戏失败")
            running = False

        pygame.display.update()

游戏效果如下

在这里插入图片描述

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

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

相关文章

scratch考试“画图”相关考点一网打尽

最近2023年12月17日举行的第15届蓝桥STEMA测评Scratch编程初/中级组编程第3题—六花阵图 在讲解这个题目&#xff0c;可以延申scratch所有的基础图形&#xff0c;学会这篇&#xff0c;碰到关于“图形”类题目基本上都可以搞定 六花阵图 编程实现&#xff1a; 六花阵图。 注…

C#,入门教程(15)——类(class)的基础知识

上一篇&#xff1a; C#&#xff0c;入门教程(14)——字符串与其他数据类型的转换https://blog.csdn.net/beijinghorn/article/details/124004562 物以类聚&#xff0c;凡物必类。 类的使用&#xff0c;须遵循几个简单的原则&#xff1a; &#xff08;1&#xff09;能类则类&a…

selenium不自动关闭chrome,selenium hello world

selenium不自动关闭chrome 用visual studio的话&#xff0c;右键&#xff0c;在终端运行。 from selenium import webdriveroptions webdriver.ChromeOptions() options.add_experimental_option("detach", True) driver webdriver.Chrome(optionsoptions) url …

世微大功率 内置2.5A宽电压降压恒流 LED电源驱动车灯IC AP5193

AP5193是一款PWM工作模式,高效率、外围简单、 内置功率MOS管&#xff0c;适用于4.5-100V输入的高精度 降压LED恒流驱动芯片。电流2.5A。AP5193可实现线性调光和PWM调光&#xff0c;线性调光 脚有效电压范围0.55-2.6V. AP5193 工作频率可以通过RT 外部电阻编程来设定&#xff0c…

【Python】编程练习的解密与实战(三)

​&#x1f308;个人主页&#xff1a;Sarapines Programmer&#x1f525; 系列专栏&#xff1a;《Python | 编程解码》⏰诗赋清音&#xff1a;云生高巅梦远游&#xff0c; 星光点缀碧海愁。 山川深邃情难晤&#xff0c; 剑气凌云志自修。 目录 &#x1fa90;1. 初识Python &a…

机器人制作开源方案 | 六足灾后探测机器人

作者&#xff1a;毕钟诚 施钥 范江龙 张莉曼 陈金凤 单位&#xff1a;中国石油大学&#xff08;北京&#xff09; 指导老师&#xff1a;许亚岚 孙琳 世纪全球自然灾害频发&#xff0c;灾后探测重建工作十分重要&#xff0c;极端恶劣的现场探测环境&#xff0c;频发的余震甚至…

Unity获取系统语言

大家好&#xff0c;我是阿赵。   在使用Unity引擎做多语言的游戏时&#xff0c;很有可能需要根据用户的手机或者电脑的当前语言来设置游戏的默认语言。   Unity的API里面默认就有可以获取系统语言的方法&#xff1a; Application.systemLanguageUnity的API例子&#xff1a…

Redis 为什么要分16个库

目录 一. 前言 二. 16 个数据库的由来 三. 正解 Redis 数据库概念 四. 集群环境下的 Redis 实例 五. 总结 一. 前言 在实际的项目中&#xff0c;Redis 常被用作缓存、分布式锁、消息队列等的解决方案。但是在搭建好Redis 服务后&#xff0c;Redis 默认创建了16个数据库&am…

基于知识图谱的健康知识问答系统

基于知识图谱的健康知识问答系统 引言数据集与技术选型数据集技术选型 系统功能与实现数据导入与图数据库构建问答任务设计与实现1. 实体提取2. 用户意图识别 前端聊天界面与问答系统 结语 引言 随着互联网的发展&#xff0c;人们对健康知识的需求逐渐增加。为了更方便地获取健…

Windows安全基础:认证基础知识

目录 Windows凭据 Windows访问控制模型 访问令牌&#xff1a; 安全标识符&#xff08;SID&#xff09;&#xff1a; 安全描述符&#xff1a; 令牌安全防御 1、禁止域管理员异机登录 2、开启“审核进程创建”策略 Windows凭据 SSPI&#xff08;Security Support Provide…

【PHP】PHP实现与硬件串口交互,接收硬件发送的实时数据

一、前言 目的&#xff1a;借助虚拟串口软件&#xff08;VSPD&#xff09;模拟硬件串口发送数据&#xff0c;使用PHP语言实现接收硬件发送的数据。 我这里的需求是连接天平&#xff0c;把天平的称量数据实时的传送到PHP使用。 使用工具&#xff1a;vspd串口调试工具 使用语…

第十三章Filter

第十三章Filter 1.什么是Filter过滤器2.Filter过滤器的基本使用示例3.完整的用户登录和权限检查4.Filter的生命周期5.FilterConfig类6.FilterChain多个过滤器执行的细节7.Filter的拦截路径 1.什么是Filter过滤器 2.Filter过滤器的基本使用示例 现在下面三个都是可以访问的&…

PPT插件-大珩助手-《提取选中的幻灯片》-选中新建

选中新建 提取选中的幻灯片到新的幻灯文稿中。PDF编辑器可以提取指定的页面到新的PDF文档中&#xff0c;PPT没有这个功能&#xff0c;因此开发。 软件介绍 PPT大珩助手是一款全新设计的Office PPT插件&#xff0c;它是一款功能强大且实用的PPT辅助工具&#xff0c;支持Wps Wo…

Docker介绍安装及使用

目录 引言一、什么是Docker?二、Docker的优势三、Docker的架构四、Docker的安装五、Docker的基本使用六、Docker与传统虚拟化的比较七、Docker的应用场景八、总结 引言 在现代的软件开发和部署中&#xff0c;容器化技术已经成为了一种趋势。Docker作为容器化技术的领先者&…

im6ull学习总结(三-五)freetype显示正行字

知识补充 笛卡尔坐标系 这里笛卡尔坐标系就是初高中学的直角坐标系的第一象限 lcd坐标系则不同 这两个坐标系如何转换 观察两个坐标系 点&#xff08;x,y&#xff09;的x坐标在两个坐标系中相同&#xff0c;纵坐标&#xff08;y&#xff09;存在着yV-yV V是整个屏幕的行数的像…

基于RNN的模型

文本数据是一种典型的具有序列结构的数据&#xff0c;因为文本通常是由一系列的词语或字符组成的序列。每个词语或字符在文本中都有特定的位置和顺序&#xff0c;这种有序的结构对于理解和处理文本的含义至关重要。因此&#xff0c;多数情况下需要使用时间序列建模来完成相应的…

C/C++ 堆排序

个人主页&#xff1a;仍有未知等待探索-CSDN博客 专题分栏&#xff1a;数据结构_仍有未知等待探索的博客-CSDN博客 欢迎大家来指教&#xff01; 一、前言 今天要介绍的是堆排序。 首先什么是堆&#xff1f;简而言之&#xff0c;堆就是二叉树的数组形式&#xff0c;用数组来存…

【C++】类和对象之匿名对象友元内部类

目录 一、匿名对象 1、基础格式 2、使用场景 二、友元 1、友元函数 2、友元类 三、内部类 1、概念 2、特性 四、拷贝对象时的一些编译器优化 1、函数传参 2、对象返回 一、匿名对象 1、基础格式 【注意】 &#x1f7e2;匿名对象的声明周期只有当前行&#xff0c;进入…

推荐熊猫电竞赏金电竞系统源码

熊猫电竞赏金电竞系统源码&#xff0c;包含APP、H5和搭建视频教程&#xff0c;支持运营级搭建&#xff0c;这套源码是基于ThinkPHPUniaapp框架开发的。 系统是一套完整的电竞平台开发源码&#xff0c;包括赛事管理、用户系统、竞猜系统、支付系统等模块。源码结构清晰&#xff…

OpenGL排坑指南—贴图纹理绑定和使用

一、前言 在OpenGL学习 的纹理这一章中讲述了纹理贴图的使用方式&#xff0c;主要步骤是先创建一个纹理的对象&#xff0c;和创建顶点VAO类似&#xff0c;然后就开始绑定这个纹理&#xff0c;最后在循环中使用&#xff0c;有时候可能还要用到激活纹理单元的函数。然而&#xff…