python快速实现数字华容道小游戏

华容道,中国历史地名。据《资治通鉴》注释中的说法,就是“从此道可至华容也”。这里所说的华容,当然是指华容县城。华容道也就是赤壁战争中曹军逃入华容县界后向华容县城逃跑的路线 。

小说故事

诸葛亮智算华容,关云长义释曹操”,是世人皆知的一个故事,《三国演义》中的重点篇章。小说写赤壁战前,诸葛亮算定曹操必败走华容,且夜观天象,曹操不当身亡,考虑到曹操与关羽有恩,于是派关云长把守华容道,留个人情与关羽做。小说又写曹操果然由乌林向华容道败退,并在途中三次大笑诸葛亮、周瑜智谋不足,未在险要处暗设伏兵。然而,一笑笑出赵子龙,多亏徐晃张郃二人双敌赵云,才使曹操得以逃脱;二笑笑出张翼德,又是张辽、徐晃二将抵挡张飞,使曹操再次脱险;三笑非同小可,笑出了关云长,且又在有一夫当关之险的华容狭路上,加之曹军几经打击,此时已无力再战,无奈,曹操只得亲自哀求关羽放行,关羽念旧日恩情,义释曹操,使曹操得以回到江陵。后关羽为孙权所杀,人头交由曹操,曹操为其塑木制身体。

史实

三国演义》的上述描写,并非全是凭空之笔。曹操从赤壁败退,走的确实是华容道,但并没有关羽;曹操在途中确曾大笑,但不是三次,而是一次;曹操笑的也不是诸葛亮与周瑜智谋不足,而是笑刘备虽有计谋却迟缓;曹操笑后确也出现了敌情,但已无惊无险。据《三国志》记载,曹操在赤壁中了周瑜的火攻之计,索性又一把火烧掉所剩战船,率军经华容向江陵一路败退。孙刘联军则水陆并进,尾随曹军,紧追不舍。

其实,当时曹操虽然战败,但面临的形势并不十分严峻。因为在赤壁交锋之前,是曹操强大,孙刘弱小,孙权和刘备首先考虑的是如何挫败曹操的强大攻势,使曹操不得渡过长江,以保全自己的势力范围,或保证自己不被曹操消灭掉,在胜负未卜的情况下,他们没有也无力抽出部分兵力去在曹操可能败退的路线上去设伏。所以,曹操在败退的路上,虽后有追兵,却前无伏军。可是,在通向华容的道路上,却遇到了难以想象的困难。

三国志·武帝纪》裴松之注引《山阳公载记》说:曹操战船被烧,率军从华容道步行而归。华容道上一片泥泞,根本无法通行,加之那天又刮大风,行走更加艰难。于是曹操下令,命羸弱之兵割草垫路,大军才得以通过,而羸兵被人马践踏,深陷泥中,死亡无数。眼看大军就要全部通过华容道,曹操不由哈哈大笑。诸将本已狼狈不堪,见曹操大笑,十分不解,问曹操为何发笑。曹操说道:“刘备的才智与我不相上下,但他的计谋总要晚我一步;假使他早派快马至华容道放火,我等必全军覆没了。”曹操话音刚落,接探马报刘备追兵在后面开始顺风点火。但曹操大军已通过华容道,奔江陵而去。

华容道小游戏实现,主要依赖库:PyQt5,完整代码如下:

import sys
import random
from enum import IntEnum
from PyQt5.QtWidgets import QLabel, QWidget, QApplication, QGridLayout, QMessageBox
from PyQt5.QtGui import QFont, QPalette
from PyQt5.QtCore import Qt
 
# 方向类
class Direction(IntEnum):
    UP = 0
    DOWN = 1
    LEFT = 2
    RIGHT = 3
 
# 数字华容道
class NumberHuaRong(QWidget):
 
    def __init__(self):
        super().__init__()
        self.blocks = []
        self.zero_row = 0
        self.zero_column = 0
        self.gltMain = QGridLayout()
 
        self.initUI()
 
    def initUI(self):      
        # 方块间隔
        self.gltMain.setSpacing(10)
 
        self.onInit()
 
        # 布局
        self.setLayout(self.gltMain)
        # 宽高
        self.setFixedSize(400, 400)
        # 标题
        self.setWindowTitle('数字华容道')
        # 背景颜色
        self.setStyleSheet("background-color:white;")
        self.show()
 
    # 初始化
    def onInit(self):
        # 顺序数组1-16
        self.numbers = list(range(1, 16))
        self.numbers.append(0)
 
        # 将数字添加到二维数组
        for row in range(4):
            self.blocks.append([])
            for column in range(4):
                temp = self.numbers[row * 4 + column]
 
                if temp == 0:
                    self.zero_row = row
                    self.zero_column = column
                self.blocks[row].append(temp)
 
        # 打乱数组
        for i in range(1000):
            random_num = random.randint(0, 3)
            self.move(Direction(random_num))
 
        self.updatePanel()
 
    # 检测按键
    def keyPressEvent(self, event):
        key = event.key()
        if(key == Qt.Key_Up):
            self.move(Direction.UP)
        if(key == Qt.Key_Down):
            self.move(Direction.DOWN)
        if(key == Qt.Key_Left):
            self.move(Direction.LEFT)
        if(key == Qt.Key_Right):
            self.move(Direction.RIGHT)
        self.updatePanel()
        if self.checkResult():
            if QMessageBox.Ok == QMessageBox.information(self, '挑战结果', '恭喜完成本次挑战!'):
                self.onInit()
 
    # 方块移动
    def move(self, direction):
        if(direction == Direction.UP): # 上
            if self.zero_row != 3:
                self.blocks[self.zero_row][self.zero_column] = self.blocks[self.zero_row + 1][self.zero_column]
                self.blocks[self.zero_row + 1][self.zero_column] = 0
                self.zero_row += 1
        if(direction == Direction.DOWN): # 下
            if self.zero_row != 0:
                self.blocks[self.zero_row][self.zero_column] = self.blocks[self.zero_row - 1][self.zero_column]
                self.blocks[self.zero_row - 1][self.zero_column] = 0
                self.zero_row -= 1
        if(direction == Direction.LEFT): # 左
            if self.zero_column != 3:
                self.blocks[self.zero_row][self.zero_column] = self.blocks[self.zero_row][self.zero_column + 1]
                self.blocks[self.zero_row][self.zero_column + 1] = 0
                self.zero_column += 1
        if(direction == Direction.RIGHT): # 右
            if self.zero_column != 0:
                self.blocks[self.zero_row][self.zero_column] = self.blocks[self.zero_row][self.zero_column - 1]
                self.blocks[self.zero_row][self.zero_column - 1] = 0
                self.zero_column -= 1
 
    def updatePanel(self):
        for row in range(4):
            for column in range(4):
                self.gltMain.addWidget(Block(self.blocks[row][column]), row, column)
 
        self.setLayout(self.gltMain)
 
    # 检测完成
    def checkResult(self):
        # 右下角是否为0
        if self.blocks[3][3] != 0:
            return False
 
        for row in range(4):
            for column in range(4):
                # 右下角已经为0,pass
                if row == 3 and column == 3:
                    pass
                #值是否对应
                elif self.blocks[row][column] != row * 4 + column + 1:
                    return False
 
        return True
 
# 数字方块 
class Block(QLabel):
 
    def __init__(self, number):
        super().__init__()
 
        self.number = number
        self.setFixedSize(80, 80)
 
        # 字体
        font = QFont()
        font.setFamily("Arial")
        font.setPointSize(30)
        font.setBold(True)
        self.setFont(font)
 
        # 颜色
        pa = QPalette()
        pa.setColor(QPalette.WindowText, Qt.white)
        self.setPalette(pa)
 
        # 文字位置
        self.setAlignment(Qt.AlignCenter)
 
        # 样式
        if self.number == 0:
            self.setStyleSheet("background-color:grey;border-radius:10px;")
        else:
            self.setStyleSheet("background-color:cyan;border-radius:10px;")
            self.setText(str(self.number))
 
 
if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = NumberHuaRong()
    sys.exit(app.exec_())

运行结构如下:

 关于操作方式:使用方向键操作即可;由于灰色方块是空缺块,所以移动时不能被灰色方块视线诱导,将它误当作了移动中心点;如上图所示,此时上下左右方向键所移动的方块依次是4上移,7下移,12左移,6右移,则灰色空缺块朝相反方向移动

关于数字华容道的相关解法可参考以下文章

数字华容道怎么解?几个关键点处理好,你就能成为挑战高手

 主要详细来源:

Python程序设计之数字华容道_LeeYotta的博客-CSDN博客_数字华容道程序

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值