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

news2024/11/24 18:58:28

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.coloradmin.cn/o/1626219.html

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

相关文章

C# 生成图形验证码

目录 应用场景 开发运行环境 设计 生成内容 生成图片 实现 核心代码 调用示例 小结 应用场景 我们当用户登录系统时经常会用到图形验证码技术&#xff0c;要求用户识别图片中的内容&#xff0c;并正确输入&#xff0c;方可尝试登录。类似的场景还有用户注册或者涉及…

探秘MySQL主从复制的多种实现方式

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 探秘MySQL主从复制的多种实现方式 前言基于语句的复制原理实现方法应用场景及优缺点应用场景优点缺点 基于行的复制原理实现方法优势和适用性优势适用性 基于混合模式的复制混合模式复制的工作原理混合…

【stomp 实战】Spring websocket使用详解和基本原理

spring框架对websocket有很好的支持&#xff0c;stomp协议作为websocket的子协议&#xff0c;Spring也做了很多封装&#xff0c;让我们在开发中易于使用。 学习使用Spring的Websocket模块&#xff0c;当然最好的办法就是看官网说明了。本篇文章对官网做一些简述和个人的理解。 …

链游:未来游戏发展的新风向

链游&#xff0c;即区块链游戏的一种&#xff0c;是一种将区块链技术与游戏玩法相结合的创新型游戏。它利用区块链技术的特性&#xff0c;如去中心化、可追溯性和安全性&#xff0c;为玩家提供了一种全新的游戏体验。链游通常采用智能合约来实现游戏的规则和交易系统&#xff0…

按现价和不变价计算与公布的统计指标主要有哪些

在经济统计和分析工作中 , 有些指标可以直接用实物量表示 , 如粮食和工业品产量等&#xff1b;而有些指标则是用价值量表示的 , 如全国居民人均可支配收入、社会消费品零售总额、商品房销售额等。在计算价值量指标时&#xff0c;一般均要考虑采用什么价格来计算。统计上常用的价…

新媒体运营-----短视频运营-----PR视频剪辑----PR特效

新媒体运营-----短视频运营-----PR视频剪辑-----持续更新(进不去说明我没写完)&#xff1a;https://blog.csdn.net/grd_java/article/details/138079659 文章目录 1. 混合和对比度1. 滤色2. 对比度 2. 3d和属性粘贴3. 参考线和锚点 1. 混合和对比度 1. 滤色 混合是PS&#xff…

【数据结构(邓俊辉)学习笔记】绪论04——算法分析

文章目录 0. 前言1. 算法分析2.级数2.1基本形式2.2 收敛级数 3.循环 vs 级数4.示例 0. 前言 通过以基本计算模型作为参照&#xff0c;并且以大O记号的形式在上面添加适当刻度&#xff0c;已经建立一套对DSA进行分析的完整工具和体系。不清楚的可以看看复杂度度量 、复杂度分析…

Kafka 生产者应用解析

目录 1、生产者消息发送流程 1.1、发送原理 2、异步发送 API 2.1、普通异步发送 2.2、带回调函数的异步发送 3、同步发送 API 4、生产者分区 4.1、分区的优势 4.2、生产者发送消息的分区策略 示例1&#xff1a;将数据发往指定 partition 示例2&#xff1a;有 key 的…

Python浅谈清朝秋海棠叶版图

1、清朝疆域概述&#xff1a; 清朝是我国最后一个封建王朝&#xff0c;其始于1616年建州女真部努尔哈赤建立后金&#xff0c;此后统一女真各部、东北地区。后又降服漠南蒙古&#xff0c;1644年入关打败农民起义军、灭南明&#xff0c;削三藩&#xff0c;复台湾。后又收外蒙&am…

【后端】python与django的开发环境搭建指南

安装Git 双击Git 客户端安装文件&#xff0c;在安装页面&#xff0c;单击“Next” 在安装路径选择页面&#xff0c;保持默认&#xff0c;单击“Next” 在功能组件选择页面&#xff0c;保持默认&#xff0c;单击“Next” 在开始菜单文件夹设置页面&#xff0c;保持默认&am…

分享Python7个爬虫小案例(附源码)_爬虫实例

在这篇文章中&#xff0c;我们将分享7个Python爬虫的小案例&#xff0c;帮助大家更好地学习和了解Python爬虫的基础知识。以下是每个案例的简介和源代码&#xff1a; 1. 爬取豆瓣电影Top250 这个案例使用BeautifulSoup库爬取豆瓣电影Top250的电影名称、评分和评价人数等信息&…

Redisson - tryLock 函数参数分析

这里有三个参数&#xff1a; waitTime&#xff1a;等待时间leaseTime&#xff1a;超时施放时间TimeUnit&#xff1a;时间单位 等待时间 如果 ABC… 多个线程去抢夺一把锁&#xff0c;A 成功了&#xff0c;如果设置的是 -1&#xff0c;那么 BCD... 就不等待&#xff0c;直接返…

MYSQL45道练习题---持续更新中

来源&#xff1a; Mysql_45道练习题 - 简书 共四张表&#xff1a; ①、course表&#xff1a; CId&#xff1a;课程id Cname&#xff1a;课程名称 TId&#xff1a;老师id ②、student学生表&#xff1a; SId&#xff1a;学生id Sname&#xff1a;…

淘宝店铺商品信息抓取

一、背景 为了更好了解同行或竞争对手的情况&#xff0c;基于对行业数据分析、市场研究、竞争情报收集等方面的需求。一些公司或个人可能希望获取淘宝店铺的商品数据&#xff0c;以便进行以下操作&#xff1a; 市场研究和竞争分析&#xff1a;通过分析淘宝店铺的商品数据&…

Qt [获取Dump] 使用WindowsAPI实现生成MiniDump文件

说明 客户现场的软件偶发崩溃是程序开发者&#xff0c;比较头疼的事情。如何更快速的定位到问题点和解决掉&#xff0c;是开发应该具备的基本能力。 Windows提供了一系列的API&#xff0c;可以记录软件崩溃前的堆栈信息。下面就实现一个生成Dump文件的程序实例。 主要代码 回…

Linux之线程管理

目录 第1关&#xff1a;创建线程 任务描述 相关知识 使用pthread_create函数创建线程 编程要求 答案&#xff1a; 第2关&#xff1a;线程挂起 任务描述 相关知识 使用pthread_join挂起线程 编程要求 答案&#xff1a; 第3关&#xff1a;线程终止 任务描述 相关知识 使用pthread…

意法半导体STM32F407VET6TR单片机优缺点、参数、应用和引脚封装

ST(意法半导体)的型号STM32F407VET6TR属于32位MCU微控制器&#xff0c;基于高性能的ArmCortex-M4 32位RISC核心&#xff0c;工作频率高达168MHz。单精度浮点单元(FPU)用于Cortex-M4核心&#xff0c;支持所有Arm单精度数据处理指令和数据类型。它还实现了一套完整的DSP指令和一个…

走进中财:创邻科技图技术赋能金融高质量发展路演圆满完成!

4月20日下午&#xff0c;由中财MBA金融科技研究会主办的“走进中财”主题活动在中央财经大学商学院的A28教室如期举行。中央财经大学商学院党委副书记杨中英、中财MBA金融科技研究会发起人代表贾晓强、中央财经大学商学院教授王毅等受邀参与本次大会。 创邻科技CEO兼创始人张晨…

python 实现用户登录

1. JWT Token 参考&#xff1a;https://www.zhihu.com/question/364616467 jwt官网&#xff1a;https://jwt.io/#debugger-io 1.1. Token Token 是一个宽泛的术语&#xff0c;它可以指代任何一种用于身份验证的机制。Token 常常被用在验证和授权流程中。Token 可以有不同的形…

标准版/开源版 移动端新增页面使用文档

在标准版开发的实际使用中&#xff0c;随着用户移动端的产品和信息内容不断增多&#xff0c;新增页面来展示对应的产品详情、模块等内容。针对一些概念或者步骤较多的内容&#xff0c;可以新增子页面构建多级模块结构&#xff0c;帮助用户快速定位。 下面就如何新增页面做一讲…