利用Python基于PySide2实现2048小游戏

本文章适合喜欢经典游戏和对pyside2感兴趣的同学阅读

2048是一款比较流行的数字游戏,最早于2014年3月20日发行。原版2048首先在GitHub上发布,原作者是Gabriele Cirulli,后被移植到各个平台。


一、准备工作

本代码需要第三方库PySide2,尽量选择最新版本。

二、创建游戏

1.创建目录

目录如下:

game2048
    2048.py
    rul.py
    ui_gameui.py -> 游戏界面
    ui_ruleui.py -> 游戏规则显示

2.界面设置

代码如下

ui_gameui:

# -*- coding: utf-8 -*-

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *


class Ui_Window(object):
    def setupUi(self, Window):
        if not Window.objectName():
            Window.setObjectName(u"Window")
        Window.resize(800, 800)
        self.centralwidget = QWidget(Window)
        self.centralwidget.setObjectName(u"centralwidget")
        self.g1 = QPushButton(self.centralwidget)
        self.g1.setObjectName(u"g1")
        self.g1.setGeometry(QRect(70, 130, 150, 150))
        font = QFont()
        font.setFamily(u"Ink Free")
        font.setPointSize(26)
        self.g1.setFont(font)
        self.g2 = QPushButton(self.centralwidget)
        self.g2.setObjectName(u"g2")
        self.g2.setGeometry(QRect(240, 130, 150, 150))
        self.g2.setFont(font)
        self.g3 = QPushButton(self.centralwidget)
        self.g3.setObjectName(u"g3")
        self.g3.setGeometry(QRect(410, 130, 150, 150))
        self.g3.setFont(font)
        self.g4 = QPushButton(self.centralwidget)
        self.g4.setObjectName(u"g4")
        self.g4.setGeometry(QRect(580, 130, 150, 150))
        self.g4.setFont(font)
        self.g8 = QPushButton(self.centralwidget)
        self.g8.setObjectName(u"g8")
        self.g8.setGeometry(QRect(580, 300, 150, 150))
        self.g8.setFont(font)
        self.g7 = QPushButton(self.centralwidget)
        self.g7.setObjectName(u"g7")
        self.g7.setGeometry(QRect(410, 300, 150, 150))
        self.g7.setFont(font)
        self.g6 = QPushButton(self.centralwidget)
        self.g6.setObjectName(u"g6")
        self.g6.setGeometry(QRect(240, 300, 150, 150))
        self.g6.setFont(font)
        self.g5 = QPushButton(self.centralwidget)
        self.g5.setObjectName(u"g5")
        self.g5.setGeometry(QRect(70, 300, 150, 150))
        self.g5.setFont(font)
        self.g13 = QPushButton(self.centralwidget)
        self.g13.setObjectName(u"g13")
        self.g13.setGeometry(QRect(70, 640, 150, 150))
        self.g13.setFont(font)
        self.g14 = QPushButton(self.centralwidget)
        self.g14.setObjectName(u"g14")
        self.g14.setGeometry(QRect(240, 640, 150, 150))
        self.g14.setFont(font)
        self.g11 = QPushButton(self.centralwidget)
        self.g11.setObjectName(u"g11")
        self.g11.setGeometry(QRect(410, 470, 150, 150))
        self.g11.setFont(font)
        self.g12 = QPushButton(self.centralwidget)
        self.g12.setObjectName(u"g12")
        self.g12.setGeometry(QRect(580, 470, 150, 150))
        self.g12.setFont(font)
        self.g10 = QPushButton(self.centralwidget)
        self.g10.setObjectName(u"g10")
        self.g10.setGeometry(QRect(240, 470, 150, 150))
        self.g10.setFont(font)
        self.g9 = QPushButton(self.centralwidget)
        self.g9.setObjectName(u"g9")
        self.g9.setGeometry(QRect(70, 470, 150, 150))
        self.g9.setFont(font)
        self.g15 = QPushButton(self.centralwidget)
        self.g15.setObjectName(u"g15")
        self.g15.setGeometry(QRect(410, 640, 150, 150))
        self.g15.setFont(font)
        self.g16 = QPushButton(self.centralwidget)
        self.g16.setObjectName(u"g16")
        self.g16.setGeometry(QRect(580, 640, 150, 150))
        self.g16.setFont(font)
        self.label = QLabel(self.centralwidget)
        self.label.setObjectName(u"label")
        self.label.setGeometry(QRect(330, 0, 141, 50))
        font1 = QFont()
        font1.setPointSize(18)
        self.label.setFont(font1)
        self.label.setAlignment(Qt.AlignCenter)
        self.sccaler = QLCDNumber(self.centralwidget)
        self.sccaler.setObjectName(u"sccaler")
        self.sccaler.setGeometry(QRect(500, 50, 261, 70))
        font2 = QFont()
        font2.setPointSize(9)
        self.sccaler.setFont(font2)
        self.sccaler.setDigitCount(7)
        self.sccaler.setMode(QLCDNumber.Dec)
        self.sccaler.setProperty("value", 0.000000000000000)
        self.sccaler.setProperty("intValue", 0)
        self.gamerule = QPushButton(self.centralwidget)
        self.gamerule.setObjectName(u"gamerule")
        self.gamerule.setGeometry(QRect(180, 60, 120, 60))
        font3 = QFont()
        font3.setPointSize(14)
        self.gamerule.setFont(font3)
        self.stgame = QPushButton(self.centralwidget)
        self.stgame.setObjectName(u"stgame")
        self.stgame.setGeometry(QRect(310, 60, 120, 60))
        self.stgame.setFont(font3)
        self.label_2 = QLabel(self.centralwidget)
        self.label_2.setObjectName(u"label_2")
        self.label_2.setGeometry(QRect(430, 50, 71, 70))
        self.label_2.setFont(font3)
        self.label_3 = QLabel(self.centralwidget)
        self.label_3.setObjectName(u"label_3")
        self.label_3.setGeometry(QRect(740, 680, 71, 16))
        self.ctrlz = QPushButton(self.centralwidget)
        self.ctrlz.setObjectName(u"ctrlz")
        self.ctrlz.setGeometry(QRect(50, 60, 120, 60))
        self.ctrlz.setFont(font3)
        Window.setCentralWidget(self.centralwidget)

        self.retranslateUi(Window)

        QMetaObject.connectSlotsByName(Window)
    # setupUi

    def retranslateUi(self, Window):
        Window.setWindowTitle(QCoreApplication.translate("Window", u"2048", None))
        self.g1.setText("")
        self.g2.setText("")
        self.g3.setText("")
        self.g4.setText("")
        self.g8.setText("")
        self.g7.setText("")
        self.g6.setText("")
        self.g5.setText("")
        self.g13.setText("")
        self.g14.setText("")
        self.g11.setText("")
        self.g12.setText("")
        self.g10.setText("")
        self.g9.setText("")
        self.g15.setText("")
        self.g16.setText("")
        self.label.setText(QCoreApplication.translate("Window", u"2048", None))
        self.gamerule.setText(QCoreApplication.translate("Window", u"\u6e38\u620f\u89c4\u5219", None))
        self.stgame.setText(QCoreApplication.translate("Window", u"\u5f00\u59cb\u6e38\u620f", None))
        self.label_2.setText(QCoreApplication.translate("Window", u"\u5206\u6570\uff1a", None))
        self.label_3.setText(QCoreApplication.translate("Window", u"@by Tong", None))
        self.ctrlz.setText(QCoreApplication.translate("Window", u"\u64a4\u56de", None))
    # retranslateUi

ui_ruleui.py:

# -*- coding: utf-8 -*-

from PySide2.QtCore import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *


class Ui_Ruleui(object):
    def setupUi(self, Ruleui):
        if not Ruleui.objectName():
            Ruleui.setObjectName(u"Ruleui")
        Ruleui.resize(400, 300)
        self.centralwidget = QWidget(Ruleui)
        self.centralwidget.setObjectName(u"centralwidget")
        self.textEdit = QTextEdit(self.centralwidget)
        self.textEdit.setObjectName(u"textEdit")
        self.textEdit.setGeometry(QRect(0, -1, 400, 301))
        font = QFont()
        font.setPointSize(12)
        self.textEdit.setFont(font)
        self.textEdit.setReadOnly(True)
        Ruleui.setCentralWidget(self.centralwidget)

        self.retranslateUi(Ruleui)

        QMetaObject.connectSlotsByName(Ruleui)
    # setupUi

    def retranslateUi(self, Ruleui):
        Ruleui.setWindowTitle(QCoreApplication.translate("Ruleui", u"\u6e38\u620f\u89c4\u5219", None))
        self.textEdit.setHtml(QCoreApplication.translate("Ruleui", u"<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">\n"
"<html><head><meta name=\"qrichtext\" content=\"1\" /><style type=\"text/css\">\n"
"p, li { white-space: pre-wrap; }\n"
"</style></head><body style=\" font-family:'SimSun'; font-size:12pt; font-weight:400; font-style:normal;\">\n"
"<p style=\" margin-top:0px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">\u6e38\u620f\u89c4\u5219\uff1a</span></p>\n"
"<p style=\" margin-top:0px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; backg"
                        "round-color:#ffffff;\">2048\u6e38\u620f\u5171\u670916\u4e2a\u683c\u5b50\uff0c\u521d\u59cb\u65f6\u521d\u59cb\u6570\u5b57\u75312\u6216\u80054\u6784\u6210\u3002</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">1\u3001\u5229\u7528WASD\u5411\u4e00\u4e2a\u65b9\u5411\u6ed1\u52a8\uff0c\u6240\u6709\u683c\u5b50\u4f1a\u5411\u90a3\u4e2a\u65b9\u5411\u8fd0\u52a8\u3002</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">2\u3001\u76f8\u540c"
                        "\u6570\u5b57\u7684\u4e24\u4e2a\u683c\u5b50\uff0c\u76f8\u649e\u65f6\u6570\u5b57\u4f1a\u76f8\u52a0\u3002</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">3\u3001\u6bcf\u6b21\u6ed1\u52a8\u65f6\uff0c\u7a7a\u767d\u5904\u4f1a\u968f\u673a\u5237\u65b0\u51fa\u4e00\u4e2a\u6570\u5b57\u7684\u683c\u5b50\u3002</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">4\u3001\u5f53\u754c\u9762\u4e0d\u53ef\u8fd0\u52a8\u65f6\uff08\u754c\u9762\u5168"
                        "\u90e8\u88ab\u6570\u5b57\u586b\u6ee1\u4e14\u6ca1\u6709\u76f8\u90bb\u76f8\u540c\u6570\u5b57\u65f6\uff09\uff0c\u6e38\u620f\u7ed3\u675f\u3002</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">\u6e38\u620f\u8ba1\u5206\u65b9\u5f0f\uff1a</span></p>\n"
"<p style=\" margin-top:17px; margin-bottom:17px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; line-height:28px; background-color:#ffffff;\"><span style=\" font-family:'PingFang SC,Lantinghei SC,Microsoft YaHei,arial,\u5b8b\u4f53,sans-serif,tahoma'; font-size:16px; color:#333333; background-color:#ffffff;\">2 2 0 0 \u5411\u5de6\u79fb\u5f97\u5230 4 0 0 0 \uff0c\u5219\u5206\u6570\u589e\u52a02\u5206\u3002</span></p></body></html>", None))
    # retranslateUi

这里建议直接复制,因为用的是html格式。

3.游戏主程序

rul.py:

from PySide2.QtWidgets import *

from ui_ruleui import Ui_Ruleui

class R(QMainWindow,Ui_Ruleui):
    def __init__(self):
        super().__init__()
        self.setupUi(self)

2048.py:

import sys
from random import choice
from copy import deepcopy
from PySide2.QtCore import *
from PySide2.QtWidgets import *
from ui_gameui import Ui_Window
from rul import R
# 导入库及文件

class MainPro(QMainWindow, Ui_Window):
    def __init__(self):
        super().__init__()
        self.setupUi(self)
        self.w2 = R()
        self.show()
        self.setup()
        self.hisl = []
        self.hiscl = []
        self.sc = 0
        self.isst = False
        self.dic = {0: '#ffffff', 2: '#eee6db', 4: '#efe0cd',
                    8: '#f5af7b', 16: '#fb9660', 32: '#f57d5a',
                    64: '#f95c3d', 128: '#eccc75', 256: '#eece61',
                    512: '#efc853', 1024: '#ebc53c', 2048: '#eec430',
                    4096: '#bbcf59', 8192: '#b0c254', 16384: '#a6b74f',
                    32768: '#aab767', 65536: '#aeb879', 131072: '#dd28e8'} # 合成数字颜色

    def setup(self):
        # 初始化
        self.gamerule.clicked.connect(self.showrule)
        self.stgame.clicked.connect(self.start)
        self.ctrlz.clicked.connect(self.cz)

    def cz(self):
        # 撤回
        self.lst = deepcopy(self.hisl[-1])
        self.setw()
        self.hisl.pop(-1)
        self.sccaler.display(self.hiscl[-1])
        self.hiscl.pop(-1)

    def showrule(self):
        # 展示游戏规则
        self.w2.show()

    def setw(self):
        # 写入数字
        for i in range(4):
            for j in range(4):
                exec(f'self.g{i * 4 + j + 1}.setText(str(self.lst[i][j] if self.lst[i][j]!=0 else ""))')
                if self.lst[i][j] != 0:
                    exec(f'self.g{i * 4 + j + 1}.setStyleSheet(f"background-color:{self.dic[self.lst[i][j]]}")')
                else:
                    exec(f'self.g{i * 4 + j + 1}.setStyleSheet(f"background-color:#FFFFFF")')

    def start(self):
        # 开始游戏
        self.sc = 0
        self.sccaler.display(self.sc)
        self.isst = True
        self.putnum(st=True)

    def putnum(self, st=False):
        # 随机放入数字
        if st:
            self.lst = [[0] * 4,
                        [0] * 4,
                        [0] * 4,
                        [0] * 4
                        ]

        l = []
        for i in range(4):
            for j in range(4):
                if not self.lst[i][j]:
                    l.append([i, j])
        t = choice(l)
        self.lst[t[0]][t[1]] = choice([2, 2, 2, 4])
        self.setw()

    def change(self, way):
        # 上下左右操作
        self.olist = deepcopy(self.lst)
        self.hisl.append(deepcopy(self.lst))
        self.hiscl.append(self.sc)
        self.olist = deepcopy(self.lst)
        self.olist = deepcopy(self.lst)
        if way == 'u':
            for k in range(3):
                for i in range(3, 0, -1):
                    for j in range(4):
                        if self.lst[i - 1][j] == 0:
                            self.lst[i][j], self.lst[i - 1][j] = self.lst[i - 1][j], self.lst[i][j]
            for i in range(1,4):
                for j in range(4):
                    if self.lst[i - 1][j] == self.lst[i][j]:
                        self.lst[i][j], self.lst[i - 1][j] = 0, self.lst[i][j] * 2
                        self.sc += self.lst[i - 1][j] / 2
            for k in range(3):
                for i in range(3, 0, -1):
                    for j in range(4):
                        if self.lst[i - 1][j] == 0:
                            self.lst[i][j], self.lst[i - 1][j] = self.lst[i - 1][j], self.lst[i][j]
        elif way == 'l':
            for k in range(3):
                for i in range(4):
                    for j in range(3, 0, -1):
                        if self.lst[i][j - 1] == 0:
                            self.lst[i][j], self.lst[i][j - 1] = self.lst[i][j - 1], self.lst[i][j]
            for i in range(4):
                for j in range(1,4):
                    if self.lst[i][j - 1] == self.lst[i][j]:
                        self.lst[i][j], self.lst[i][j - 1] = 0, self.lst[i][j] * 2
                        self.sc += self.lst[i][j - 1] / 2
            for k in range(3):
                for i in range(4):
                    for j in range(3, 0, -1):
                        if self.lst[i][j - 1] == 0:
                            self.lst[i][j], self.lst[i][j - 1] = self.lst[i][j - 1], self.lst[i][j]
        elif way == 'd':
            for k in range(3):
                for i in range(3):
                    for j in range(4):
                        if self.lst[i + 1][j] == 0:
                            self.lst[i][j], self.lst[i + 1][j] = self.lst[i + 1][j], self.lst[i][j]
            for i in range(2,-1,-1):
                for j in range(4):
                    if self.lst[i + 1][j] == self.lst[i][j]:
                        self.lst[i][j], self.lst[i + 1][j] = 0, self.lst[i][j] * 2
                        self.sc += self.lst[i + 1][j] / 2
            for k in range(3):
                for i in range(3):
                    for j in range(4):
                        if self.lst[i + 1][j] == 0:
                            self.lst[i][j], self.lst[i + 1][j] = self.lst[i + 1][j], self.lst[i][j]
        elif way == 'r':
            for k in range(3):
                for i in range(4):
                    for j in range(3):
                        if self.lst[i][j + 1] == 0:
                            self.lst[i][j], self.lst[i][j + 1] = self.lst[i][j + 1], self.lst[i][j]
            for i in range(4):
                for j in range(2,-1,-1):
                    if self.lst[i][j + 1] == self.lst[i][j]:
                        self.lst[i][j], self.lst[i][j + 1] = 0, self.lst[i][j] * 2
                        self.sc += self.lst[i][j + 1] / 2
            for k in range(3):
                for i in range(4):
                    for j in range(3):
                        if self.lst[i][j + 1] == 0:
                            self.lst[i][j], self.lst[i][j + 1] = self.lst[i][j + 1], self.lst[i][j]
        if self.olist == self.lst:
            return
        self.sccaler.display(self.sc)
        self.putnum()
        self.setw()
        self.judge()

    def judge(self):
        # 判断是否游戏结束
        for i in range(3):
            for j in range(4):
                if self.lst[i][j] == 0 or self.lst[i][j] == self.lst[i + 1][j]:
                    return
        for i in range(4):
            for j in range(3):
                if self.lst[i][j] == 0 or self.lst[i][j] == self.lst[i][j + 1]:
                    return
        QMessageBox.information(self, '游戏结束',
                                f'游戏结束,得分{int(self.sc)}分,最高{max(self.lst[i][j] for i in range(4) for j in range(4))}。')

    def keyPressEvent(self, event):
        if self.isst:
            if event.key() == Qt.Key_W:
                self.change(way='u')
            elif event.key() == Qt.Key_A:
                self.change(way='l')
            elif event.key() == Qt.Key_S:
                self.change(way='d')
            elif event.key() == Qt.Key_D:
                self.change(way='r')


if __name__ == '__main__':
    app = QApplication(sys.argv)
    window = MainPro()
    sys.exit(app.exec_())

三、效果展示


 总结

以上就是本文的内容,这里只用了PySide2的冰山一角,同学们可以深钻。当然本文的逻辑也有一定欠缺,若有更好建议欢迎投稿!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值