基于Python实现的推箱子小游戏

Python贪吃蛇小游戏实现:

     推箱子曾经在我们的童年给我们带来了很多乐趣。推箱子这款游戏现在基本上没人玩了,甚至在新一代人的印象中都已毫无记忆了。。。但是,这款游戏可以在一定程度上锻炼自己的编程能力。

运行效果如图所示:

    游戏关卡有点难哦,码友们一起来挑战一下吧。

代码如下:

import pygame, sys, os
from pygame.locals import *
from collections import deque


def to_box(level, index):
   if level[index] == '-' or level[index] == '@':
       level[index] = '$'
   else:
       level[index] = '*'


def to_man(level, i):
   if level[i] == '-' or level[i] == '$':
       level[i] = '@'
   else:
       level[i] = '+'


def to_floor(level, i):
   if level[i] == '@' or level[i] == '$':
       level[i] = '-'
   else:
       level[i] = '.'


def to_offset(d, width):
   d4 = [-1, -width, 1, width]
   m4 = ['l', 'u', 'r', 'd']
   return d4[m4.index(d.lower())]

def b_manto(level, width, b, m, t):
   maze = list(level)
   maze[b] = '#'
   if m == t:
       return 1
   queue = deque([])
   queue.append(m)
   d4 = [-1, -width, 1, width]
   m4 = ['l', 'u', 'r', 'd']
   while len(queue) > 0:
       pos = queue.popleft()
       for i in range(4):
           newpos = pos + d4[i]
           if maze[newpos] in ['-', '.']:
               if newpos == t:
                   return 1
               maze[newpos] = i
               queue.append(newpos)
   return 0

def b_manto_2(level, width, b, m, t):
   maze = list(level)
   maze[b] = '#'
   maze[m] = '@'
   if m == t:
       return []
   queue = deque([])
   queue.append(m)
   d4 = [-1, -width, 1, width]
   m4 = ['l', 'u', 'r', 'd']
   while len(queue) > 0:
       pos = queue.popleft()
       for i in range(4):
           newpos = pos + d4[i]
           if maze[newpos] in ['-', '.']:
               maze[newpos] = i
               queue.append(newpos)
               if newpos == t:
                   path = []
                   while maze[t] != '@':
                       path.append(m4[maze[t]])
                       t = t - d4[maze[t]]
                   return path

   return []

class Sokoban:
   def __init__(self):
       self.level = list(
           '----#####--------------#---#--------------#$--#------------###--$##-----------#--$-$-#---------###-#-##-#---#######---#-##-#####--..##-$--$----------..######-###-#@##--..#----#-----#########----#######--------')
       self.w = 19
       self.h = 11
       self.man = 163
       self.hint = list(self.level)
       self.solution = []
       self.push = 0
       self.todo = []
       self.auto = 0
       self.sbox = 0
       self.queue = []

   def draw(self, screen, skin):
       w = skin.get_width() / 4
       offset = (w - 4) / 2
       for i in range(0, self.w):
           for j in range(0, self.h):
               if self.level[j * self.w + i] == '#':
                   screen.blit(skin, (i * w, j * w), (0, 2 * w, w, w))
               elif self.level[j * self.w + i] == '-':
                   screen.blit(skin, (i * w, j * w), (0, 0, w, w))
               elif self.level[j * self.w + i] == '@':
                   screen.blit(skin, (i * w, j * w), (w, 0, w, w))
               elif self.level[j * self.w + i] == '$':
                   screen.blit(skin, (i * w, j * w), (2 * w, 0, w, w))
               elif self.level[j * self.w + i] == '.':
                   screen.blit(skin, (i * w, j * w), (0, w, w, w))
               elif self.level[j * self.w + i] == '+':
                   screen.blit(skin, (i * w, j * w), (w, w, w, w))
               elif self.level[j * self.w + i] == '*':
                   screen.blit(skin, (i * w, j * w), (2 * w, w, w, w))
               if self.sbox != 0 and self.hint[j * self.w + i] == '1':
                   screen.blit(skin, (i * w + offset, j * w + offset), (3 * w, 3 * w, 4, 4))

   def move(self, d):
       self._move(d)
       self.todo = []

   def _move(self, d):
       self.sbox = 0
       h = to_offset(d, self.w)
       h2 = 2 * h
       if self.level[self.man + h] == '-' or self.level[self.man + h] == '.':
           # move
           to_man(self.level, self.man + h)
           to_floor(self.level, self.man)
           self.man += h
           self.solution += d
       elif self.level[self.man + h] == '*' or self.level[self.man + h] == '$':
           if self.level[self.man + h2] == '-' or self.level[self.man + h2] == '.':
               # push
               to_box(self.level, self.man + h2)
               to_man(self.level, self.man + h)
               to_floor(self.level, self.man)
               self.man += h
               self.solution += d.upper()
               self.push += 1

   def undo(self):
       if self.solution.__len__() > 0:
           self.todo.append(self.solution[-1])
           self.solution.pop()

           h = to_offset(self.todo[-1], self.w) * -1
           if self.todo[-1].islower():
               # undo a move
               to_man(self.level, self.man + h)
               to_floor(self.level, self.man)
               self.man += h
           else:
               # undo a push
               to_floor(self.level, self.man - h)
               to_box(self.level, self.man)
               to_man(self.level, self.man + h)
               self.man += h
               self.push -= 1

   def redo(self):
       if self.todo.__len__() > 0:
           self._move(self.todo[-1].lower())
           self.todo.pop()

   def manto(self, x, y):
       maze = list(self.level)
       maze[self.man] = '@'
       queue = deque([])
       queue.append(self.man)
       d4 = [-1, -self.w, 1, self.w]
       m4 = ['l', 'u', 'r', 'd']
       while len(queue) > 0:
           pos = queue.popleft()
           for i in range(4):
               newpos = pos + d4[i]
               if maze[newpos] in ['-', '.']:
                   maze[newpos] = i
                   queue.append(newpos)
       # print str(maze)
       t = y * self.w + x
       if maze[t] in range(4):
           self.todo = []
           while maze[t] != '@':
               self.todo.append(m4[maze[t]])
               t = t - d4[maze[t]]
       # print self.todo
       self.auto = 1

   def automove(self):
       if self.auto == 1 and self.todo.__len__() > 0:
           self._move(self.todo[-1].lower())
           self.todo.pop()
       else:
           self.auto = 0

   def boxhint(self, x, y):
       d4 = [-1, -self.w, 1, self.w]
       m4 = ['l', 'u', 'r', 'd']
       b = y * self.w + x
       maze = list(self.level)
       to_floor(maze, b)
       to_floor(maze, self.man)
       mark = maze * 4
       size = self.w * self.h
       self.queue = []
       head = 0
       for i in range(4):
           if b_manto(maze, self.w, b, self.man, b + d4[i]):
               if len(self.queue) == 0:
                   self.queue.append((b, i, -1))
               mark[i * size + b] = '1'
       # print self.queue
       while head < len(self.queue):
           pos = self.queue[head]
           head += 1
           # print pos
           for i in range(4):
               if mark[pos[0] + i * size] == '1' and maze[pos[0] - d4[i]] in ['-', '.']:
                   # print i
                   if mark[pos[0] - d4[i] + i * size] != '1':
                       self.queue.append((pos[0] - d4[i], i, head - 1))
                       for j in range(4):
                           if b_manto(maze, self.w, pos[0] - d4[i], pos[0], pos[0] - d4[i] + d4[j]):
                               mark[j * size + pos[0] - d4[i]] = '1'
       for i in range(size):
           self.hint[i] = '0'
           for j in range(4):
               if mark[j * size + i] == '1':
                   self.hint[i] = '1'
       # print self.hint

   def boxto(self, x, y):
       d4 = [-1, -self.w, 1, self.w]
       m4 = ['l', 'u', 'r', 'd']
       om4 = ['r', 'd', 'l', 'u']
       b = y * self.w + x
       maze = list(self.level)
       to_floor(maze, self.sbox)
       to_floor(maze, self.man)  # make a copy of working maze by removing the selected box and the man
       for i in range(len(self.queue)):
           if self.queue[i][0] == b:
               self.todo = []
               j = i
               while self.queue[j][2] != -1:
                   self.todo.append(om4[self.queue[j][1]].upper())
                   k = self.queue[j][2]
                   if self.queue[k][2] != -1:
                       self.todo += b_manto_2(maze, self.w, self.queue[k][0], self.queue[k][0] + d4[self.queue[k][1]],
                                              self.queue[k][0] + d4[self.queue[j][1]])
                   else:
                       self.todo += b_manto_2(maze, self.w, self.queue[k][0], self.man,
                                              self.queue[k][0] + d4[self.queue[j][1]])
                   j = k
               # print self.todo
               self.auto = 1
               return
       print('not found!')

   def mouse(self, x, y):
       if x >= self.w or y >= self.h:
           return
       m = y * self.w + x
       if self.level[m] in ['-', '.']:
           if self.sbox == 0:
               self.manto(x, y)
           else:
               self.boxto(x, y)
       elif self.level[m] in ['$', '*']:
           if self.sbox == m:
               self.sbox = 0
           else:
               self.sbox = m
               self.boxhint(x, y)
       elif self.level[m] in ['-', '.', '@', '+']:
           self.boxto(x, y)


def main():
   # start pygame
   pygame.init()
   screen = pygame.display.set_mode((400, 300))

   # load skin
   skinfilename = os.path.join('borgar.png')
   try:
       skin = pygame.image.load(skinfilename)
   except pygame.error as msg:
       print('cannot load skin')
       raise SystemExit(msg)
   skin = skin.convert()

   # print skin.get_at((0,0))
   # screen.fill((255,255,255))
   screen.fill(skin.get_at((0, 0)))
   pygame.display.set_caption('推箱子')

   # create Sokoban object
   skb = Sokoban()
   skb.draw(screen, skin)

   #
   clock = pygame.time.Clock()
   pygame.key.set_repeat(200, 50)

   # main game loop
   while True:
       clock.tick(60)

       if skb.auto == 0:
           for event in pygame.event.get():
               if event.type == QUIT:
                   # print skb.solution
                   pygame.quit()
                   sys.exit()
               elif event.type == KEYDOWN:
                   if event.key == K_LEFT:
                       skb.move('l')
                       skb.draw(screen, skin)
                   elif event.key == K_UP:
                       skb.move('u')
                       skb.draw(screen, skin)
                   elif event.key == K_RIGHT:
                       skb.move('r')
                       skb.draw(screen, skin)
                   elif event.key == K_DOWN:
                       skb.move('d')
                       skb.draw(screen, skin)
                   elif event.key == K_BACKSPACE:
                       skb.undo()
                       skb.draw(screen, skin)
                   elif event.key == K_SPACE:
                       skb.redo()
                       skb.draw(screen, skin)
               elif event.type == MOUSEBUTTONUP and event.button == 1:
                   mousex, mousey = event.pos
                   mousex /= (skin.get_width() / 4)
                   mousey /= (skin.get_width() / 4)
                   skb.mouse(mousex, mousey)
                   skb.draw(screen, skin)
       else:
           skb.automove()
           skb.draw(screen, skin)

       pygame.display.update()
       pygame.display.set_caption(skb.solution.__len__().__str__() + '/' + skb.push.__str__() + ' - 推箱子')


if __name__ == '__main__':
   main()

图片素材:

完整素材及全部代码

代码已上传csdn,0积分下载,觉得这片博文有用请留下你的点赞。

基于Python实现的推箱子小游戏
 

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

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

相关文章

一文读懂海外站建设平台选择,HubSpot为何独占鳌头?

说起海外站建设平台&#xff0c;就像咱们挑餐馆一样&#xff0c;得看菜色合不合胃口&#xff0c;环境舒不舒服&#xff0c;还有价格能不能接受。市面上那些平台&#xff0c;各有各的招牌菜&#xff0c;但哪道最适合你&#xff0c;还真得好好琢磨琢磨。如果你想要的是那种既实用…

【产品经理修炼之道】- 从需求到功能的转化过程

产品经理的最大作用是将需求转化为产品或者功能&#xff0c;从需求到功能&#xff0c;会经历哪些过程&#xff1f;本文总结了从需求到功能的转化过程&#xff0c;希望对你进一步了解有所帮助。 “大部分的产品经理特别是数字化产品经理其核心价值就是如何去解决如何把需求转化为…

bash: ../configure: /bin/sh^M: bad interpreter: No such file or directory

bash: ../configure: /bin/sh^M: bad interpreter: No such file or directory 这个错误通常是由于Windows平台下的文本格式导致的&#xff0c;而在Linux下则会被解释为错误。解决这个问题的方法之一是使用dos2unix命令将脚本转换为Unix格式。 dos2unix ../configure 然后重…

leetcode2418.按身高排序

题目描述&#xff1a; 给你一个字符串数组 names &#xff0c;和一个由 互不相同 的正整数组成的数组 heights 。两个数组的长度均为 n 。 对于每个下标 i&#xff0c;names[i] 和 heights[i] 表示第 i 个人的名字和身高。 请按身高 降序 顺序返回对应的名字数组 names 。 …

Azure AKS集群监控告警表达式配置

背景需求 Azure AKS集群中&#xff0c;需要对部署的服务进行监控和告警&#xff0c;需要创建并启用预警规则&#xff0c;而这里怎么去监控每个pod级别的CPU和内存&#xff0c;需要自己写搜索查询 解决方法 搜索和查询的语句如下&#xff0c;需要自己替换其中的部分信息,其中…

汽车驾驶3D模拟仿真展示系统更立体直观

随着新能源汽车的普及&#xff0c;它已成为现代生活中不可或缺的交通工具。并且国产车的崛起&#xff0c;其设计与零部件制造水平已能与合资车相媲美&#xff0c;因此汽车维修技能的学习变得尤为重要。汽车维修3D仿真教学软件应运而生&#xff0c;为广大学员提供了一个直观、高…

vLLM-prefix浅析(System Prompt,大模型推理加速)

原文&#xff1a;vLLM-prefix浅析&#xff08;System Prompt&#xff0c;大模型推理加速&#xff09; 简介 本文浅析了在大模型推理加速方面一个非常优秀的项目 vLLM 的一个新特性 Prefix。在 Prompt 中有相同前缀时可以提高吞吐量降低延迟&#xff0c;换句话说可以省去这部分…

M - 上帝造题的八分钟(数位dp,dfs—dp,****)

链接&#xff1a;登录—专业IT笔试面试备考平台_牛客网 来源&#xff1a;牛客网 我们称一个数为 fufu 数&#xff0c;当且仅当一个数满足下述性质&#xff1a;它的数位中有至少 3 个相邻的数字 3&#xff0c;且数字 0 的个数与数字 1 的个数相差至少为 1 的正整数。 给定一个…

Python拿取nmap扫描的结果并存在csv文件中

今天分享一个使用subprocess模块来执行nmap命令,并使用csv模块来将结果写入CSV文件的方法。 代码如下: import subprocess import csv# 定义扫描的参数 ip_address = 172.18.0.1/24 # 扫描的IP地址或CIDR port_range = -p 443 # 扫描的端口范围 output_filename = s…

睫毛膏上架亚马逊销售需要做什么准备 HRIPT / RIPT斑贴试验

睫毛膏上架需要办理&#xff1a;HRIPT / RIPT斑贴试验COA成分分析证书BCOP认证报告&#xff01; 什么是BCOP&#xff1a; 亚马逊美国站对接触眼睛的眼影&#xff0c;液体眼线笔&#xff0c;磁性睫毛&#xff0c;假睫毛等产品&#xff0c;需提供BCOP&#xff08;Bovine Corneal…

存在矛盾的题目

{ u t t − a 2 u x x 0 , t > 0 , x > 0 , u ( x , 0 ) sin ⁡ ( x ) 2 x , x ≥ 0 , u t ( x , 0 ) cos ⁡ ( x ) , x ≥ 0 , u x ( 0 , t ) 2 , t ≥ 0. \begin{cases} u_{tt} - a^2 u_{xx} 0, & t > 0, x > 0, \\ u(x, 0) \sin(x) 2x, & x \ge…

解线性方程组——上三角、下三角,回代算法 | 北太天元

1. 解上三角(回代) a i i ≠ 0 a_{ii\neq0} aii0​ , i 1 , 2 , … , n i1,2,\ldots,n i1,2,…,n a 11 x 1 a 12 x 2 ⋯ a 1 n x n b 1 a 22 x 2 ⋯ a 2 n x n b 2 ⋯ a n n x n b n \begin{aligned} a_{11}x_1a_{12}x_2\cdotsa_{1n}x_n&b_1 \\ a_{22}x_2\cdot…

解决idea不识别${pageContext.request.contextPath}的方法

文章目录 一、产生原因二、解决方法——直接修改web.xml文件三、修改模板——找到web.xml模板&#xff0c;修改替换 一、产生原因 由于web.xml 使用的web-app版本号过低。导致无法识别"{pageContext.request.contextPath}"。 IDEA在创建javaweb项目的时候&#xff0…

synchronized 之谜

序言 本文给大家介绍一下 synchronized 关键字的部分原理。 一、内存中的 Java 对象 class A {private String attr; }先引入一个问题&#xff1a;上面类 A 有一个属性 attr。当类 A 实例化之后的对象在内存中是如何表示的呢&#xff1f; 在内存中&#xff0c;Java 对象由三…

2024年03月CCF-GESP编程能力等级认证Python编程二级真题解析

本文收录于专栏《Python等级认证CCF-GESP真题解析》,专栏总目录:点这里,订阅后可阅读专栏内所有文章。 一、单选题(共15题,共30分) 第1题 小杨的父母最近刚刚给他买了一块华为手表,他说手表上跑的是鸿蒙,这个鸿蒙是? A.小程序 B.计时器 C.操作系统 D.神话人物 答案…

【Linux驱动层】iTOP-RK3568学习之路(三):字符设备驱动框架

一、总体框架图 二、字符设备相关函数 静态申请设备号 register_chrdev_region 函数原型&#xff1a;register_chrdev_region(dev_t from, unsigned count, const char *name) 函数作用&#xff1a;静态申请设备号&#xff0c;可以一次性申请多个连续的号&#xff0c;count指定…

电阻理论基础

电流的形成是电荷运动&#xff0c;电子方向相反&#xff0c;标量 电压&#xff1a;电势有参考点&#xff0c;是一个相对量 电阻的值不取决于电压和电流的&#xff0c; Ra表示标准电阻 R表示任意温度的电阻

Transformer step by step--Positional Embedding 和 Word Embedding

Transformer step by step往期文章&#xff1a; Transformer step by step--层归一化和批量归一化 要把Transformer中的Embedding说清楚&#xff0c;那就要说清楚Positional Embedding和Word Embedding。至于为什么有这两个Embedding&#xff0c;我们不妨看一眼Transformer的…

代码随想录算法训练营第三十八天| LeetCode509.斐波那契数、LeetCode70.爬楼梯、LeetCode746.使用最小花费爬楼梯

LeetCode 509 斐波那契数 题目链接&#xff1a;509. 斐波那契数 - 力扣&#xff08;LeetCode&#xff09; 【解题思路】 1.确定dp数组以及下标的含义 dp[i]的定义为&#xff1a;第i个数的斐波那契数值是dp[i] 2.确定递推公式 递推公式就是题目说的斐波那契值递推公式 3.确定…

【Java GUI】人机对弈五子棋

在学校的Java课程中&#xff0c;我们被分配了一项有趣的任务&#xff1a;开发一款能够实现人机对弈的五子棋游戏。为了更好地理解Java GUI的运用&#xff0c;并与大家分享学习心得&#xff0c;我将整个开发过程记录在这篇博客中。欢迎大家阅读并提供宝贵的意见和建议&#xff0…