当前位置:   article > 正文

用python的tkinter做游戏(四)—— 推箱子重制版_tkinter推箱子游戏

tkinter推箱子游戏

今天继续:用python自带的tkinter做游戏系列的第四弹,推箱子重制版 篇

之前的三篇博文介绍的分别是贪食蛇和俄罗斯方块,还有推箱子的简易版。
用python自带的tkinter做游戏(一)—— 贪吃蛇 篇
用python自带的tkinter做游戏(二)—— 俄罗斯方块 篇
用python自带的tkinter做游戏(三)—— 推箱子简易版 篇

上回发布的推箱子游戏中,我后来发现一个BUG,就是在大地图的关卡中(第六关),如果人物远离初始地后,按J键复位的话画面不会返回到人物所在的坐标处。今天要讲的重制版里已经修复好了。

先来谈谈重制版的思路吧。我最初的想法是做成像素版的,就是用更多的像素来构成游戏画面。打个比方,本来黄色单元格代表的人,等于只有一个像素来表达,如果把这个单元格再分成16x16,或者甚至更多,就可以展现出更精致的画面。像素升级法优点就是不需要用到图片,全部用代码就能搞定,缺点么也很明显,比较费力,等于是在画像素图。
  
  不过像素图的问题也好解决,我可以用tkinter来做一个像素图编辑器,这个还是比较容易实现的,而且有了这个编辑器,制作关卡也会变的方便许多。

可惜,虽然后来我是完成了像素上的升级,但我发现即使是只有8x8的像素升级,游戏过程中还是能肉眼所见的卡顿。如果像素再高的话就成了幻灯片了。
  
  当然我也想过用一些方案来优化,比如多线程,或者只刷新局部区域,效果都不是很明显,只能说自身水平有限吧,只好作罢。不过在这次的重制版中,我还是保留了像素模式,用的是8x8的像素图,各位可以感受一下~

# 人物在空地上的动画效果(用于像素动画模式)
pe2 = [[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 2, 2, 1, 0, 0],
 [0, 0, 1, 2, 2, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ],[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 5, 5, 1, 1, 0],
 [0, 1, 1, 5, 5, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

这就是人物的像素图,在游戏画面中就如下图:
在这里插入图片描述
在这里插入图片描述
  因为只有8x8的像素,所以也只能画画这种简单的画面。这两张反复切换所形成的动图就成了这个推箱小人。
  
  既然像素模式行不通,那我只能用图片模式了,这也是游戏制作最常用的方法,直接用图片,简单明了。
  
  也懒得网上去找图片,我就直接用做好的像素图截图下来当图片用。当然为了区分,箱子的颜色略有区别,还有就是人物造型也略有修改。
  在这里插入图片描述
嗯,比之前的简易版来的确是有点游戏的样子了。按数字键0可以切换模式,原始的简易模式,图片模式和像素模式,三种模式逐一切换。

图片模式比较好理解,就根据原本单元格的值,插入相应的图片即可。

    def create_pic_cells(self,a,b):
        """ 创建图片模式的单元格 """ 
        global man_gif
        
        man_2 = ["2.png","22.png"] # 两张空地上人的图片
        man_6 = ["6.png","66.png"] # 两张终点上人的图片
            
        man_gif = man_gif + 1
        if man_gif > 1:
            man_gif = 0
            
        man_2[0] = man_2[man_gif]
        man_6[0] = man_6[man_gif]
            
        pic= ["0.png","1.png",man_2[0],"3.png","4.png","5.png",man_6[0]]
        bm = []  
            
        for i in range(len(pic)):
            bm.append(('bm' + str(i)))
            exec('bm'+str(i)+' = tk.PhotoImage(file='+str(pic)+'['+str(i)+'])',globals())
            #bm = ['bm0','bm1','bm2','bm3','bm4','bm5','bm6']
            
        for y in range(0,len(game_map[self.game_stage-1])-b):
            for x in range(0,len(game_map[self.game_stage-1][0])-a): 
                n = game_map[self.game_stage-1][y+b][x+a] # 单元格的值
                canvas.create_image(self.frame_x*2 + self.cell_size*x + x*self.cell_gap, 
                                    self.frame_y*2 + self.cell_size*y + y*self.cell_gap,
                                    image = eval(bm[n])) 
        canvas.place(x=0,y=0)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

像素模式也是差不多的思路,就有一点不同,网格线的显示。像素模式下,网格线是每8个单元格出现一次,所以解决的方案就是看像素格的坐标值能否整除8,能整除的就加一条网格线,有余数的就略过。
  
  好了,推箱子的重制版算是完成了,掌握了这些技巧后,就能制作出更多类似的游戏来,比如经典的魔塔。从制作的角度上来说,魔塔和推箱子是属于同一类的游戏,都是以单元格为单位移动的。本来是想做一个魔塔,图片资源都找好了,后来想想工程有点浩大,而且技术上也没什么大的难点,也就作罢了。有需要图片资源的朋友可以联系我(wx:znix1116),欢迎来交流。
  
  至于音效,其实python自带的winsound就可以播放音乐,有兴趣的朋友可以自行试一试。
  
  最后我来谈谈其它类型的游戏吧。其实大多数的游戏,动作类的也好,射击类的也好,就算是RPG类的,对象的移动基本上都是以像素为单位的。不像推箱子或是魔塔,是以单元格为单位的。有什么区别呢?就拿坦克大战来说吧,玩坦克大战的时候,玩家可以躲在砖墙后面,一点一点的移动出来。而推箱工只能是要么在墙后面,要么就整个人都出来,没法做到人一半在墙后,一半在外的情况。
  
  那么tkinter能否做到以像素为单位来移动呢?答案当然是可以的,下一期我就会来谈谈如何实现以像素为单位的移动。
  
  好了,今天就到此结束,最后附上推箱子重制版的完整版代码,别忘了还要下载9张图片,想要更完美的画面可自行替换,图片像素是48x48

66.png
在这里插入图片描述
22.png
在这里插入图片描述
6.png
在这里插入图片描述
3.png
在这里插入图片描述
5.png
在这里插入图片描述
4.png
在这里插入图片描述
1.png
在这里插入图片描述
0.png
在这里插入图片描述
2.png
在这里插入图片描述
图片一共有九张(第八张是个白底),名字别忘了修改一下,不然不认。

2022.06.08 更新:修复BUG

完整版代码:

# -*- coding: utf-8 -*-
"""
# -*- coding: utf-8 -*-
"""
Created on Tue Mar 16 13:31:29 2021

@author: Juni Zhu (wechat:znix1116)
"""


import tkinter as tk
import copy
from tkinter.messagebox import showinfo

remake = 1 # 版本切换 0为原始模式,1为图片模式,2为像素动画模式(像素动画模式有点卡)

try:  # 同目录下搜寻m.txt地图扩充文件,若没有此文件就用内置地图
  with open("m.txt", "r") as f:
     game_map = f.read()
     game_map = eval(game_map)
except:
     game_map = [[
 [0, 0, 1, 1, 1, 0, 0, 0],
 [0, 0, 1, 4, 1, 0, 0, 0],
 [0, 0, 1, 0, 1, 1, 1, 1],
 [1, 1, 1, 3, 0, 3, 4, 1],
 [1, 4, 0, 3, 2, 1, 1, 1],
 [1, 1, 1, 1, 3, 1, 0, 0],
 [0, 0, 0, 1, 4, 1, 0, 0],
 [0, 0, 0, 1, 1, 1, 0, 0]
 ],[
 [0, 0, 0, 1, 1, 1, 1, 1, 1, 0],
 [0, 1, 1, 1, 0, 0, 0, 0, 1, 0],
 [1, 1, 4, 0, 3, 1, 1, 0, 1, 1],
 [1, 4, 4, 3, 0, 3, 0, 0, 2, 1],
 [1, 4, 4, 0, 3, 0, 3, 0, 1, 1],
 [1, 1, 1, 1, 1, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 0]
 ],[
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 4, 4, 1, 0, 0],
 [0, 1, 1, 0, 4, 1, 1, 0],
 [0, 1, 0, 0, 3, 4, 1, 0],
 [1, 1, 0, 3, 0, 0, 1, 1],
 [1, 0, 0, 1, 3, 3, 0, 1],
 [1, 0, 0, 2, 0, 0, 0, 1],
 [1, 1, 1, 1, 1, 1, 1, 1]
 ],[
 [1, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 1, 0, 0, 0, 1],
 [1, 0, 3, 4, 4, 3, 0, 1],
 [1, 2, 3, 4, 5, 0, 1, 1],
 [1, 0, 3, 4, 4, 3, 0, 1],
 [1, 0, 0, 1, 0, 0, 0, 1],
 [1, 1, 1, 1, 1, 1, 1, 1]
 ],[
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 0, 3, 3, 0, 1, 0],
 [1, 1, 1, 1, 1, 1, 0, 3, 1, 0, 0, 1, 0],
 [1, 4, 4, 4, 1, 1, 1, 0, 1, 0, 0, 1, 1],
 [1, 4, 0, 0, 1, 0, 0, 3, 0, 1, 0, 0, 1],
 [1, 4, 0, 0, 0, 0, 3, 0, 3, 0, 3, 0, 1],
 [1, 4, 0, 0, 1, 0, 0, 3, 0, 1, 0, 0, 1],
 [1, 4, 4, 4, 1, 1, 1, 0, 1, 0, 0, 1, 1],
 [1, 1, 1, 1, 1, 1, 0, 3, 0, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 0, 2, 1, 0, 0, 1, 0],
 [0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 0], 
 ],[
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1],
 [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 1, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
 [1, 0, 4, 4, 4, 0, 3, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 4, 4, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 5, 0, 0, 3, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0, 1, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1],
 [1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
 [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1]
 ]]

    
# 8*8单元格的像素图(用于像素动画模式)
cell = [[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ],[
 [1, 1, 1, 1, 7, 1, 1, 1],
 [1, 1, 1, 1, 7, 1, 1, 1],
 [7, 7, 7, 7, 7, 7, 7, 7],
 [1, 1, 7, 1, 1, 1, 1, 1],
 [1, 1, 7, 1, 1, 1, 1, 1],
 [7, 7, 7, 7, 7, 7, 7, 7],
 [1, 1, 1, 1, 7, 1, 1, 1],
 [1, 1, 1, 1, 7, 1, 1, 1]
 ],[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 2, 2, 1, 0, 0],
 [0, 0, 1, 2, 2, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ],[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 3, 3, 3, 3, 3, 3, 0],
 [0, 3, 3, 0, 0, 3, 3, 0],
 [0, 3, 0, 3, 3, 0, 3, 0],
 [0, 3, 0, 3, 3, 0, 3, 0],
 [0, 3, 3, 0, 0, 3, 3, 0],
 [0, 3, 3, 3, 3, 3, 3, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ],[
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4]
 ],[    
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 5, 5, 5, 5, 5, 5, 4],
 [4, 5, 5, 4, 4, 5, 5, 4],
 [4, 5, 4, 5, 5, 4, 5, 4],
 [4, 5, 4, 5, 5, 4, 5, 4],
 [4, 5, 5, 4, 4, 5, 5, 4],
 [4, 5, 5, 5, 5, 5, 5, 4],
 [4, 4, 4, 4, 4, 4, 4, 4]
 ],[
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 1, 1, 2, 2, 1, 4, 4],
 [4, 4, 1, 2, 2, 1, 1, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 4, 4, 1, 1, 4, 4, 4],
 [4, 1, 1, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4]
 ]]
    
# 人物在空地上的动画效果(用于像素动画模式)
pe2 = [[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 1, 1, 2, 2, 1, 0, 0],
 [0, 0, 1, 2, 2, 1, 1, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0],
 [0, 1, 1, 0, 0, 0, 0, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ],[
 [0, 0, 0, 0, 0, 0, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 1, 5, 5, 1, 1, 0],
 [0, 1, 1, 5, 5, 1, 0, 0],
 [0, 0, 1, 1, 1, 1, 0, 0],
 [0, 0, 0, 1, 1, 0, 0, 0],
 [0, 0, 0, 0, 0, 1, 1, 0],
 [0, 0, 0, 0, 0, 0, 0, 0]
 ]]

# 人物在终点上的动画效果(用于像素动画模式)
pe6 = [[
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 1, 1, 2, 2, 1, 4, 4],
 [4, 4, 1, 2, 2, 1, 1, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 4, 4, 1, 1, 4, 4, 4],
 [4, 1, 1, 4, 4, 4, 4, 4],
 [4, 4, 4, 4, 4, 4, 4, 4]
 ],[
 [4, 4, 4, 4, 4, 4, 4, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 4, 1, 5, 5, 1, 1, 4],
 [4, 1, 1, 5, 5, 1, 4, 4],
 [4, 4, 1, 1, 1, 1, 4, 4],
 [4, 4, 4, 1, 1, 4, 4, 4],
 [4, 4, 4, 4, 4, 1, 1, 4],
 [4, 4, 4, 4, 4, 4, 4, 4]
 ]]

            
class Boxman():
    """ 推箱子游戏 """
    def __init__(self, game_stage):
        """ 游戏参数设置 """       
        self.p          = 8                 # 小方格内一行像素的数量(用于像素动画模式)
        self.s          = 6                 # 单像素的宽度(用于像素动画模式)
        self.game_stage = game_stage        # 游戏关卡
        self.canvas_bg  = '#d7d7d7'         # 游戏背景色
        self.cell_size  = self.p * self.s   # 方格单元格大小
        self.cell_gap   = 1                 # 方格间距
        self.frame_x    = 25                # 左右边距
        self.frame_y    = 25                # 上下边距
        self.max_cells  = 10                # 游戏画面长宽最大单元格数
        self.win_w_plus = 220               # 窗口右边额外多出的宽度 
        self.big_map    = 0                 # 判断当前地图是否是超出窗口大小。1为是,0为不是
        
        # 根据地图自动调整窗口大小
        self.canvas_w   = len(game_map[self.game_stage-1][0]) * self.cell_size + self.frame_x*2
        self.canvas_h   = len(game_map[self.game_stage-1]   ) * self.cell_size + self.frame_y*2
        
        self.color_dict = {0:  'white',     # 0表示空白
                           1:'#808080',     # 1表示墙
                           2: 'yellow',     # 2表示空地上的人
                           3:  'green',     # 3表示空地上的箱子
                           4:   'pink',     # 4表示终点
                           5:    'red',     # 5表示终点上的的箱子
                           6:'#ffa579',     # 6表示在终点上的人
                           7:'#d7d7d7'      # 额外的颜色(用于像素动画模式)
                           }
        
        # 若地图过大,窗口则根据max_cells值来设定大小
        if len(game_map[self.game_stage-1][0]) > self.max_cells:
            self.big_map  = 1
            self.canvas_w = self.cell_size*self.max_cells + self.frame_x*2
        if len(game_map[self.game_stage-1]) > self.max_cells:
            self.big_map  = 1
            self.canvas_h = self.cell_size*self.max_cells + self.frame_y*2 
                              
        self.win_w_size = self.canvas_w + self.win_w_plus
        self.win_h_size = self.canvas_h


    def create_pixel_map(self):
        """ 创建像素版的地图 """
        global pixel_map
        
        p = self.p  # 小方格内一行像素的数量
        gy = len(game_map[self.game_stage-1])
        gx = len(game_map[self.game_stage-1][0])
        
        pixel_map = []
        for i in range(0,gy*p):
            pixel_map.append([])
        for i in range(0,gy*p):
           for j in range(0,gx*p):
              pixel_map[i].append(j)   
              pixel_map[i][j] = 0   # 生成一个全是0的空数列
        
        
    def load_pixel_map(self):
        """ 加载像素版地图 """
        global pixel_map
        p = self.p
        gy = len(game_map[self.game_stage-1])
        gx = len(game_map[self.game_stage-1][0])
        
        for a in range(0,gy):
            for b in range(0,gx):
                for y in range(0,p):
                    for x in range(0,p):
                        pixel_map[y + p*a][x + p*b] = cell[game_map[self.game_stage-1][a][b]][y][x]
        
        
    def create_canvas(self): 
        """ 创建canvas """
        global canvas
        canvas = tk.Canvas(window, 
                           bg=self.canvas_bg, 
                           height=self.canvas_h,
                           width=self.canvas_w,
                           highlightthickness = 0)
                           
                            
    def create_pixel_cells(self,a,b): # a,b值为偏差值,若地图大于窗口的话,用于调节起始坐标
            """ 创建像素版的单元格 """
            p = self.p  # 小方格内一行像素的数量
            s = self.s  # 单像素的宽度
            gy = len(game_map[self.game_stage-1])
            gx = len(game_map[self.game_stage-1][0])
            
            for y in range(0,gy*p-b):
              for x in range(0,gx*p-a):
                
                if x % p != 0:
                    xp = 0
                else:
                    xp = self.cell_gap
                # 每8个单元格间隔一个gap(p = 8)
                if y % p != 0:
                    yp = 0
                else:
                    yp = self.cell_gap
                
                x1 = self.frame_x + s * x + xp
                y1 = self.frame_y + s * y + yp
                x2 = self.frame_x + s * (x+1)
                y2 = self.frame_y + s * (y+1)
                
                canvas.itemconfig(canvas.create_rectangle(x1,y1,x2,y2,
                                        fill    = self.color_dict[pixel_map[y+b][x+a]],
                                        outline = self.canvas_bg,
                                        width   = 0),
                                        fill    = self.color_dict[pixel_map[y+b][x+a]])
                                        
            canvas.place(x=0,y=0)
            
            
    def load_pixel_boxman(self,boxman_y,boxman_x):
        """ 加载像素版人物 """
        p = self.p
        for y in range(0,p):
            for x in range(0,p):
                pixel_map[y + p*(boxman_y)][x + p*boxman_x] = cell[game_map[self.game_stage-1][boxman_y][boxman_x]][y][x]
        

    def pixel_gif(self):
        """ 像素动画效果 """ # 2张像素图反复切换做出动画效果
        global p_gif
        p_gif = p_gif + 1
        if p_gif > 1:
            p_gif = 0
        cell[2] = pe2[p_gif]
        cell[6] = pe6[p_gif]
        Boxman(self.game_stage).load_pixel_boxman(boxman_y + 0,boxman_x + 0)
        
        
    def game_loop(self):
        """ 刷新游戏画面 """
        global loop
        if   remake == 0: # 简易模式
            pass # 静止画面不需要自动刷新
        elif remake == 1: # 图片模式
            canvas.delete('all') # 清除canvas,不清除的话时间久了有BUG
            Boxman(self.game_stage).create_pic_cells(px,py)
        else: # 像素模式
            canvas.delete('all') # 清除canvas
            Boxman(self.game_stage).pixel_gif()
            Boxman(self.game_stage).create_pixel_cells(px*self.p,py*self.p)
        
        loop = window.after(100, Boxman(self.game_stage).game_loop)


    def window_center(self,window,w_size,h_size):
        """ 窗口居中 """
        screenWidth  =  window.winfo_screenwidth()  # 获取显示区域的宽度
        screenHeight = window.winfo_screenheight()  # 获取显示区域的高度
        left =  (screenWidth - w_size) // 2
        top  = (screenHeight - h_size) // 2
        window.geometry("%dx%d+%d+%d" % (w_size, h_size, left, top))

        
    def create_game_cells(self,a,b): # a,b值为偏差值,若地图大于窗口的话,用于调节起始坐标
        """ 创建初始版的游戏单元格 """  # 通过game_map列表,对应字典color_dict里的颜色画出地图
        for y in range(0,len(game_map[self.game_stage-1])-b):
              for x in range(0,len(game_map[self.game_stage-1][0])-a):            
                canvas.itemconfig(canvas.create_rectangle(
                                        self.frame_x + self.cell_size * x + self.cell_gap,
                                        self.frame_y + self.cell_size * y + self.cell_gap,
                                        self.frame_x + self.cell_size * (x+1),
                                        self.frame_y + self.cell_size * (y+1),
                                        fill    = self.color_dict[game_map[self.game_stage-1][y+b][x+a]],
                                        outline = self.canvas_bg,
                                        width   = 0),
                                        fill    = self.color_dict[game_map[self.game_stage-1][y+b][x+a]])
                                        
        canvas.place(x=0,y=0)
        

    def create_pic_cells(self,a,b):
        """ 创建图片模式的单元格 """ 
        global man_gif,pic_dict
        
        man_2 = ["2.png","22.png"] # 两张空地上人的图片
        man_6 = ["6.png","66.png"] # 两张终点上人的图片
            
        man_gif = man_gif + 1
        if man_gif > 1:
            man_gif = 0
            
        man_2[0] = man_2[man_gif]
        man_6[0] = man_6[man_gif]
        
        pic_dict = {0: tk.PhotoImage(file =  '0.png'),
                    1: tk.PhotoImage(file =  '1.png'),
                    2: tk.PhotoImage(file = man_2[0]),
                    3: tk.PhotoImage(file =  '3.png'),
                    4: tk.PhotoImage(file =  '4.png'),
                    5: tk.PhotoImage(file =  '5.png'),
                    6: tk.PhotoImage(file = man_6[0])
                    }
        
        for y in range(0,len(game_map[self.game_stage-1])-b):
            for x in range(0,len(game_map[self.game_stage-1][0])-a): 
                n = game_map[self.game_stage-1][y+b][x+a] # 单元格的值
                canvas.create_image(self.frame_x*2 + self.cell_size*x + x*self.cell_gap, 
                                    self.frame_y*2 + self.cell_size*y + y*self.cell_gap,
                                    image = pic_dict[n]) 
        canvas.place(x=0,y=0)
        
        
    def boxman_xy(self):
        """ 获取人物坐标 """
        global boxman_x, boxman_y
        xy = []
        for i in range(0,len(game_map[self.game_stage-1])):
            try: # 查找数值为2的坐标,没有就返回0。为防止人物出现在0列,先加上1,最后再减去。
                x = game_map[self.game_stage-1][i].index(2) + 1
            except:
                x = 0
            xy.append(x)
        boxman_x = max(xy)
        boxman_y = xy.index(boxman_x)
        boxman_x = boxman_x - 1 # 之前加1,现在减回

        if boxman_x == -1: # 没有数值为2,说明人物在终点,即数值等于6
            xy = []
            for i in range(0,len(game_map[self.game_stage-1])):
                try:
                    x  = game_map[self.game_stage-1][i].index(6) + 1
                except:
                    x = 0
                xy.append(x)
            boxman_x = max(xy)
            boxman_y = xy.index(boxman_x)
            boxman_x = boxman_x - 1


    def move_action(self,event): 
        """ 按键控制 """
        def Boxman_move(event,key,x,y):
                """ 操控人物 """
                # 0表示空白,  1表示墙,  2表示人,  3表示箱子,  4表示终点,  5表示已完成的箱子,  6表示在终点上的人
                def operation_forward_none(f1,f2,f3,f4,f5):
                    """ 前方是空地或是终点 """
                    if             game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1] == f1: ### 前方是空地或是终点
                        if         game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0] == 2:  #   人站在空地上
                                   game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0]  = f2  ### 人离开后是空地
                                   game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1]  = f3  ### 前方是空地或是终点
                        else:                                                                         #   人站在终点上
                                   game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0]  = f4  ### 身后是终点
                                   game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1]  = f5  ### 前方是空地或是终点

                def operation_forward_box(f1,f2,f3,f4,f5,f6,f7):
                    """ 前方是空地上的箱子或是已完成的箱子 """
                    if             game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1] == f1: ### 前方是空地上的箱子或是已完成的箱子
                        if         game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0] == 2:  #   人站在空地
                            if     game_map[self.game_stage-1][boxman_y + y*2][boxman_x + x*2] == f2: ### 箱子的前方是空地或终点
                                   game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0]  = 0   #   人离开后是空地
                                   game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1]  = f3  ### 前方是空地或是终点
                                   game_map[self.game_stage-1][boxman_y + y*2][boxman_x + x*2]  = f4  ### 前方是空地上的箱子或是已完成的箱子
                        else:                                                                         ### 人站在终点上
                            if     game_map[self.game_stage-1][boxman_y + y*2][boxman_x + x*2] == f5: ### 箱子的前方是空地或是终点
                                   game_map[self.game_stage-1][boxman_y + y*0][boxman_x + x*0]  = 4   #   身后是终点
                                   game_map[self.game_stage-1][boxman_y + y*1][boxman_x + x*1]  = f6  ### 前方是空地或是终点
                                   game_map[self.game_stage-1][boxman_y + y*2][boxman_x + x*2]  = f7  ### 箱子的前方是空地或是终点

                
                
                if remake == 2:
                    Boxman(self.game_stage).load_pixel_boxman(boxman_y + y,boxman_x + x)
                
                
                direction = event.keysym
                if(direction == key):
                    operation_forward_none(0,0,2,4,2)
                    operation_forward_none(4,0,6,4,6)
                    operation_forward_box(3,0,2,3,0,2,3)
                    operation_forward_box(3,4,2,5,4,2,5)
                    operation_forward_box(5,0,6,3,0,6,3)
                    operation_forward_box(5,4,6,5,4,6,5)
                    
                    Boxman(self.game_stage).boxman_xy()   # 刷新坐标
                    
                    temp = [] # 记录每步的操作,供撤消使用。
                    temp.append(boxman_y) # 保存XY轴坐标值,即人物所在单元格的坐标
                    temp.append(boxman_x) # 后面6个分别是中,上,下,左,右和前方单元格的值
                    temp.append(game_map[self.game_stage-1][boxman_y + 0][boxman_x + 0])
                    temp.append(game_map[self.game_stage-1][boxman_y - 1][boxman_x + 0])
                    temp.append(game_map[self.game_stage-1][boxman_y + 1][boxman_x + 0])
                    temp.append(game_map[self.game_stage-1][boxman_y + 0][boxman_x - 1])
                    temp.append(game_map[self.game_stage-1][boxman_y + 0][boxman_x + 1])
                    temp.append(game_map[self.game_stage-1][boxman_y + y][boxman_x + x])
                    
                    record_list.append(temp)
                    
                    if len(record_list) > 1:
                        if record_list[-1] == record_list[-2]:
                          del record_list[-1]   # 删除连续相同的数据


        def game_select_stage(event,key):
            """ 返回游戏主页面 """
            global game_map
            direction = event.keysym
            if(direction == key): 
                game_map = copy.deepcopy(backup_map)
                window.after_cancel(loop)
                window.destroy()  # 窗口关闭并启动起始窗口
                Boxman(self.game_stage).index_game()


        def reset_stage(event,key):
            """ 重置关卡 """
            global game_map
            direction = event.keysym
            if(direction == key): 
                del record_list[:]
                game_map = copy.deepcopy(backup_map)
                Boxman(self.game_stage).boxman_xy() # 重置大地图时需要重新定位人物坐标
                Boxman(self.game_stage).big_map_check()
                if remake == 2:
                    Boxman(self.game_stage).load_pixel_map() # 像素模式下重新装载下地图
                

        def to_stage(event,key,stage): # 直接按数字键选关
            """ 选择游戏关卡 """
            global game_map
            direction = event.keysym
            if(direction == key): 
                del record_list[:]
                game_map = copy.deepcopy(backup_map)
                window.after_cancel(loop)
                window.destroy()
                Boxman(stage).window_open()


        def restore_stage(event,key):
            """ 撤销功能 """
            direction = event.keysym
            if(direction == key): 
                def restore(): 
                    """ 撤销步骤的函数 """
                    m = game_map[self.game_stage-1]
                    
                    before_forward = 0                   # 之前所面对的(0是临时值)
                    
                    before_stand   = record_list[-2][2]  # 之前所站的单元格的值
                    now_stand      = record_list[-1][2]  # 当前所站的单元格的值
                    now_forward    = record_list[-1][7]  # 当前所面对的单元格的值

                    before_x       = record_list[-2][1]  # 之前所站的X轴坐标
                    before_y       = record_list[-2][0]  # 之前所站的Y轴坐标
                    now_x          = record_list[-1][1]  # 当前所站的X轴坐标
                    now_y          = record_list[-1][0]  # 当前所站的Y轴坐标
                    
                    b_up           = record_list[-2][3]  # 之前上方单元格的值
                    b_dw           = record_list[-2][4]  # 之前下方单元格的值
                    b_lf           = record_list[-2][5]  # 之前左方单元格的值
                    b_rg           = record_list[-2][6]  # 之前右方单元格的值

                    #  推断出之前所面对的单元格的值

                    if     before_x         > now_x:
                           next_x           = now_x - 1
                           before_forward   = b_lf
                    elif   before_x         < now_x:
                           next_x           = now_x + 1
                           before_forward   = b_rg
                    else:
                           next_x           = now_x
                             
                    if     before_y         > now_y:
                           next_y           = now_y - 1
                           before_forward   = b_up
                    elif   before_y         < now_y:
                           next_y           = now_y + 1
                           before_forward   = b_dw
                    else:
                           next_y           = now_y
                    
                    # 0表示空白,  1表示墙,  2表示人,  3表示箱子,  4表示终点,  5表示已完成的箱子,  6表示在终点上的人
                    
                    m[before_y][before_x] = before_stand # 人退回之前的状态,2或者6
                    m[   now_y][   now_x] = before_forward
                    # 推断出当前面对的单元格的值
                    if                      before_forward == 3:
                        if                     now_forward == 3:
                            if                   now_stand == 2:
                                         m[next_y][next_x]  = 0
                            elif                 now_stand == 6:
                                         m[next_y][next_x]  = 0
                        elif                   now_forward == 5:
                            if                   now_stand == 2:
                                         m[next_y][next_x]  = 4
                            elif                 now_stand == 6:
                                         m[next_y][next_x]  = 0 
                                         
                    elif                    before_forward == 5:
                        if                     now_forward == 3:
                            if                   now_stand == 2:
                                         m[next_y][next_x]  = 0
                            elif                 now_stand == 6:
                                         m[next_y][next_x]  = 0
                        elif                   now_forward == 5:
                            if                   now_stand == 2:
                                         m[next_y][next_x]  = 0
                            elif                 now_stand == 6:
                                         m[next_y][next_x]  = 4
                restore()
                
                del record_list[-1]  # 每撤消一步就删除最后一组列表
                
                if remake == 2:
                    Boxman(self.game_stage).load_pixel_map() # 像素模式下重新装载下地图
                

        def game_pass(): # 通关条件为箱子数为0
            """ 获取箱子数量,等于0的话过关 """
            xy = []
            for i in range(0,len(game_map[self.game_stage-1])):
                x = game_map[self.game_stage-1][i].count(3)
                xy.append(x)
            box_number = sum(xy)
            if box_number == 0:
                pass_win()
        
        
        def pass_win():
            """ 箱子为零时,显示过关窗口 """
            global game_map
            showinfo('恭喜过关','返回首页')
            window.destroy()
            game_map = copy.deepcopy(backup_map)
            Boxman(0).index_game()
            

        def move_map_ws(event,key,a,b):
            """ 若是大地图,则上下移动地图 """
            global py
            direction = event.keysym
            if(direction == key):             
              my = len(game_map[self.game_stage-1])
              if    self.big_map == 1:  
                if      boxman_y  >= int(self.max_cells//2) + a:
                  if    boxman_y  < my - int(self.max_cells//2):
                      if game_map[self.game_stage-1][boxman_y + b*1][boxman_x] not in [1] and \
                         game_map[self.game_stage-1][boxman_y + b*2][boxman_x] not in [1,3,5]:
                          py  = boxman_y - int(self.max_cells//2) + b
                  elif  boxman_y >= my - int(self.max_cells//2):
                              py  = my - self.max_cells 
                else:
                              py  = 0
              else:
                              py  = 0


        def move_map_ad(event,key,a,b): 
            """ 若是大地图,则左右移动地图 """
            global px
            direction = event.keysym
            if(direction == key): 
              mx = len(game_map[self.game_stage-1][0])
              if      self.big_map == 1:
                if      boxman_x >= int(self.max_cells/2) + a:
                  if    boxman_x  < mx - int(self.max_cells//2):
                      if game_map[self.game_stage-1][boxman_y][boxman_x + b*1] not in [1] and \
                         game_map[self.game_stage-1][boxman_y][boxman_x + b*2] not in [1,3,5] :
                          px  = boxman_x - int(self.max_cells//2) + b
                  elif  boxman_x >= mx - int(self.max_cells//2):
                              px  = mx - self.max_cells
                else:
                              px  = 0
              else:
                              px  = 0


        def change_map(event,key): 
            """ 三个游戏版本的切换 """ # 版本切换 0为原始模式,1为图片模式,2为像素动画模式
            global remake
            direction = event.keysym
            if(direction == key):
                window.after_cancel(loop)
                window.destroy()
                remake = remake + 1
                if remake > 2:
                    remake = 0
                Boxman(self.game_stage).window_open()
                                            

        change_map(event, '0')

        move_map_ws(event,    'w',  1, -1)
        move_map_ws(event,    's',  0,  1)
        move_map_ad(event,    'a',  1, -1)
        move_map_ad(event,    'd',  0,  1)
        
        move_map_ws(event,    'W',  1, -1)
        move_map_ws(event,    'S',  0,  1)
        move_map_ad(event,    'A',  1, -1)
        move_map_ad(event,    'D',  0,  1)
        
        move_map_ws(event,   'Up',  1, -1)
        move_map_ws(event, 'Down',  0,  1)
        move_map_ad(event, 'Left',  1, -1)
        move_map_ad(event,'Right',  0,  1)
        
        
        Boxman_move(event,    'w',  0, -1)
        Boxman_move(event,    's',  0,  1)
        Boxman_move(event,    'a', -1,  0)
        Boxman_move(event,    'd',  1,  0)
        
        Boxman_move(event,    'W',  0, -1)
        Boxman_move(event,    'S',  0,  1)
        Boxman_move(event,    'A', -1,  0)
        Boxman_move(event,    'D',  1,  0)
        
        Boxman_move(event,   'Up',  0, -1)
        Boxman_move(event, 'Down',  0,  1)
        Boxman_move(event, 'Left', -1,  0)
        Boxman_move(event,'Right',  1,  0)
        
        game_select_stage(event, 'p')     # 返回主页面
        game_select_stage(event, 'P')
        reset_stage(event, 'j')           # 重置该关卡
        reset_stage(event, 'J')
        
        to_stage(event, '1', 1)
        to_stage(event, '2', 2)
        to_stage(event, '3', 3)
        to_stage(event, '4', 4)
        to_stage(event, '5', 5)
        to_stage(event, '6', 6)
        
        
        if  len(record_list) <= 1:
            reset_stage(event, 'r')
            reset_stage(event, 'R')
        else:
            restore_stage(event, 'r')
            restore_stage(event, 'R')
        
        move_map_ws(event,   'r', 0, 0)
        move_map_ad(event,   'r', 0, 0)
        move_map_ws(event,   'R', 0, 0)
        move_map_ad(event,   'R', 0, 0)
        
        
        if  remake == 0:
            Boxman(self.game_stage).create_canvas() # 不刷新的话在大地图中有小BUG
            canvas.delete('all')
            Boxman(self.game_stage).create_game_cells(px,py)
            
        Boxman(self.game_stage).boxman_xy() # 重新刷新人物坐标,不然会有BUG
        game_pass()
        
        
    def big_map_check(self):
        """ 大地图判断 """
        global px,py
        # 如果是大地图,更换起始坐标,以人物为中心建立地图
        mx = len(game_map[self.game_stage-1][0])
        my = len(game_map[self.game_stage-1])
        if      self.big_map == 1:
                if      boxman_x  > int(self.max_cells//2):
                  if    boxman_x  < mx - int(self.max_cells//2):
                              px  = boxman_x - int(self.max_cells//2)
                  elif  boxman_x >= mx - int(self.max_cells//2):
                              px  = mx - self.max_cells
                else:
                              px  = 0
        else:
                              px  = 0
        if      self.big_map == 1:                            
                if      boxman_y  > int(self.max_cells//2):
                  if    boxman_y  < my - int(self.max_cells//2):
                              py  = boxman_y - int(self.max_cells//2)
                  elif  boxman_y >= my - int(self.max_cells//2):
                              py  = my - self.max_cells
                else:
                              py  = 0
        else:
                              py  = 0

        
    def window_open(self):
        """ 开启游戏窗口 """
        global window,txt_lable,px,py,p_gif,man_gif
        window = tk.Tk()
        window.focus_force()
        window.title('Boxman')
        Boxman(self.game_stage).window_center(window,self.win_w_size,self.win_h_size)
        p_gif = 0
        man_gif = 0
        if self.game_stage == 0:  # 若等于0,代表是最后一关
            n = len(game_map)
        else:
            n = self.game_stage
        
        mode = { 0:'简易模式', 1:'图片模式', 2:'像素模式'}
        
        txt_lable = tk.Label(window, text=
                             mode[remake]
                             +"\n"
                             +"\n当前为第" + str(n) + "关"
                             +"\n白色单元格为空地"
                             +"\n灰色单元格为墙" 
                             +"\n黄色单元格为打工人"
                             +"\n绿色单元格为箱子"
                             +"\n粉色单元格为终点"
                             +"\n红色单元格为已完成的箱子"
                             +"\n橘色单元格为站在终点上的人"
                             +"\n"
                             +"\n字母ADSW或方向键移动"
                             +"\n字母键P返回主页面"
                             +"\n字母键J重置本关"
                             +"\n字母键R为撤消"
                             +"\n数字键0为切换游戏界面模式"
                             +"\n数字键1~6直接选择关卡"
                             +"\n(第六关为测试关)"
                             +"\n"
                             +"\n"
                             +"\nBy Juni Zhu"
                             +"\n微信: znix1116"
                             +"\n2022.06.08"
                             ,
                             font=('Arial', 11),anchor="ne", justify="left")
        txt_lable.pack(side='right')
        
        Boxman(self.game_stage).boxman_xy()
        Boxman(self.game_stage).big_map_check()
        Boxman(self.game_stage).create_canvas()
        
        if  remake == 0:
            Boxman(self.game_stage).create_game_cells(px,py)
        elif  remake == 1:
            Boxman(self.game_stage).create_pic_cells(px,py)      
        else:            
            Boxman(self.game_stage).create_pixel_map()
            Boxman(self.game_stage).load_pixel_map()
            Boxman(self.game_stage).create_pixel_cells(px*self.p,py*self.p)
            
        window.bind('<Key>', Boxman(self.game_stage).move_action)
        Boxman(self.game_stage).game_loop()
        
        def close_w():
            window.after_cancel(loop)
            window.destroy()
            
        window.protocol('WM_DELETE_WINDOW', close_w)
        window.mainloop()
        
        
    def run_game(self):
        """ Run Game """
        global backup_map,record_list
        
        record_list = [] # 记录每步的操作,供撤消用
        backup_map = []  # 备份地图,供恢复用
        backup_map = copy.deepcopy(game_map)  # 备份地图,需要用深度复制
        Boxman(self.game_stage).window_open()   
        

    def index_game(self):
        """ 起始界面 """  # 窗口大小会根据按键的数量自动调整
        for i in range(1,len(game_map)+1):  # 批量生成函数,to_game_1,2,3,4,5...
            exec("def to_game_" + str(i) + "():\n\
                 index_win.destroy()\n\
                 Boxman(" + str(i) + ").run_game()")
            
        global index_win
        index_win = tk.Tk()
        index_win.focus_force()
        index_win.title('Welcome')
        Boxman(self.game_stage).window_center(index_win,200,(len(game_map)+1)*30)
        
        for i in range(1,len(game_map)+1): # 批量添加按键
            exec("b" + str(i) + " = tk.Button(index_win, text='" + str(i) 
                 + "', font=('Arial', 12), width=10, height=1, command=to_game_" + str(i) + ")")
            exec("b" + str(i) + ".pack()")
        
        index_win.mainloop()
        
    
if __name__ == '__main__':

 Boxman(0).index_game()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304
  • 305
  • 306
  • 307
  • 308
  • 309
  • 310
  • 311
  • 312
  • 313
  • 314
  • 315
  • 316
  • 317
  • 318
  • 319
  • 320
  • 321
  • 322
  • 323
  • 324
  • 325
  • 326
  • 327
  • 328
  • 329
  • 330
  • 331
  • 332
  • 333
  • 334
  • 335
  • 336
  • 337
  • 338
  • 339
  • 340
  • 341
  • 342
  • 343
  • 344
  • 345
  • 346
  • 347
  • 348
  • 349
  • 350
  • 351
  • 352
  • 353
  • 354
  • 355
  • 356
  • 357
  • 358
  • 359
  • 360
  • 361
  • 362
  • 363
  • 364
  • 365
  • 366
  • 367
  • 368
  • 369
  • 370
  • 371
  • 372
  • 373
  • 374
  • 375
  • 376
  • 377
  • 378
  • 379
  • 380
  • 381
  • 382
  • 383
  • 384
  • 385
  • 386
  • 387
  • 388
  • 389
  • 390
  • 391
  • 392
  • 393
  • 394
  • 395
  • 396
  • 397
  • 398
  • 399
  • 400
  • 401
  • 402
  • 403
  • 404
  • 405
  • 406
  • 407
  • 408
  • 409
  • 410
  • 411
  • 412
  • 413
  • 414
  • 415
  • 416
  • 417
  • 418
  • 419
  • 420
  • 421
  • 422
  • 423
  • 424
  • 425
  • 426
  • 427
  • 428
  • 429
  • 430
  • 431
  • 432
  • 433
  • 434
  • 435
  • 436
  • 437
  • 438
  • 439
  • 440
  • 441
  • 442
  • 443
  • 444
  • 445
  • 446
  • 447
  • 448
  • 449
  • 450
  • 451
  • 452
  • 453
  • 454
  • 455
  • 456
  • 457
  • 458
  • 459
  • 460
  • 461
  • 462
  • 463
  • 464
  • 465
  • 466
  • 467
  • 468
  • 469
  • 470
  • 471
  • 472
  • 473
  • 474
  • 475
  • 476
  • 477
  • 478
  • 479
  • 480
  • 481
  • 482
  • 483
  • 484
  • 485
  • 486
  • 487
  • 488
  • 489
  • 490
  • 491
  • 492
  • 493
  • 494
  • 495
  • 496
  • 497
  • 498
  • 499
  • 500
  • 501
  • 502
  • 503
  • 504
  • 505
  • 506
  • 507
  • 508
  • 509
  • 510
  • 511
  • 512
  • 513
  • 514
  • 515
  • 516
  • 517
  • 518
  • 519
  • 520
  • 521
  • 522
  • 523
  • 524
  • 525
  • 526
  • 527
  • 528
  • 529
  • 530
  • 531
  • 532
  • 533
  • 534
  • 535
  • 536
  • 537
  • 538
  • 539
  • 540
  • 541
  • 542
  • 543
  • 544
  • 545
  • 546
  • 547
  • 548
  • 549
  • 550
  • 551
  • 552
  • 553
  • 554
  • 555
  • 556
  • 557
  • 558
  • 559
  • 560
  • 561
  • 562
  • 563
  • 564
  • 565
  • 566
  • 567
  • 568
  • 569
  • 570
  • 571
  • 572
  • 573
  • 574
  • 575
  • 576
  • 577
  • 578
  • 579
  • 580
  • 581
  • 582
  • 583
  • 584
  • 585
  • 586
  • 587
  • 588
  • 589
  • 590
  • 591
  • 592
  • 593
  • 594
  • 595
  • 596
  • 597
  • 598
  • 599
  • 600
  • 601
  • 602
  • 603
  • 604
  • 605
  • 606
  • 607
  • 608
  • 609
  • 610
  • 611
  • 612
  • 613
  • 614
  • 615
  • 616
  • 617
  • 618
  • 619
  • 620
  • 621
  • 622
  • 623
  • 624
  • 625
  • 626
  • 627
  • 628
  • 629
  • 630
  • 631
  • 632
  • 633
  • 634
  • 635
  • 636
  • 637
  • 638
  • 639
  • 640
  • 641
  • 642
  • 643
  • 644
  • 645
  • 646
  • 647
  • 648
  • 649
  • 650
  • 651
  • 652
  • 653
  • 654
  • 655
  • 656
  • 657
  • 658
  • 659
  • 660
  • 661
  • 662
  • 663
  • 664
  • 665
  • 666
  • 667
  • 668
  • 669
  • 670
  • 671
  • 672
  • 673
  • 674
  • 675
  • 676
  • 677
  • 678
  • 679
  • 680
  • 681
  • 682
  • 683
  • 684
  • 685
  • 686
  • 687
  • 688
  • 689
  • 690
  • 691
  • 692
  • 693
  • 694
  • 695
  • 696
  • 697
  • 698
  • 699
  • 700
  • 701
  • 702
  • 703
  • 704
  • 705
  • 706
  • 707
  • 708
  • 709
  • 710
  • 711
  • 712
  • 713
  • 714
  • 715
  • 716
  • 717
  • 718
  • 719
  • 720
  • 721
  • 722
  • 723
  • 724
  • 725
  • 726
  • 727
  • 728
  • 729
  • 730
  • 731
  • 732
  • 733
  • 734
  • 735
  • 736
  • 737
  • 738
  • 739
  • 740
  • 741
  • 742
  • 743
  • 744
  • 745
  • 746
  • 747
  • 748
  • 749
  • 750
  • 751
  • 752
  • 753
  • 754
  • 755
  • 756
  • 757
  • 758
  • 759
  • 760
  • 761
  • 762
  • 763
  • 764
  • 765
  • 766
  • 767
  • 768
  • 769
  • 770
  • 771
  • 772
  • 773
  • 774
  • 775
  • 776
  • 777
  • 778
  • 779
  • 780
  • 781
  • 782
  • 783
  • 784
  • 785
  • 786
  • 787
  • 788
  • 789
  • 790
  • 791
  • 792
  • 793
  • 794
  • 795
  • 796
  • 797
  • 798
  • 799
  • 800
  • 801
  • 802
  • 803
  • 804
  • 805
  • 806
  • 807
  • 808
  • 809
  • 810
  • 811
  • 812
  • 813
  • 814
  • 815
  • 816
  • 817
  • 818
  • 819
  • 820
  • 821
  • 822
  • 823
  • 824
  • 825
  • 826
  • 827
  • 828
  • 829
  • 830
  • 831
  • 832
  • 833
  • 834
  • 835
  • 836
  • 837
  • 838
  • 839
  • 840
  • 841
  • 842
  • 843
  • 844
  • 845
  • 846
  • 847
  • 848
  • 849
  • 850
  • 851
  • 852
  • 853
  • 854
  • 855
  • 856
  • 857
  • 858
  • 859
  • 860
  • 861
  • 862
  • 863
  • 864
  • 865
  • 866
  • 867
  • 868
  • 869
  • 870
  • 871
  • 872
  • 873
  • 874
  • 875
  • 876
  • 877
  • 878
  • 879
  • 880
  • 881
  • 882
  • 883
  • 884
  • 885
  • 886
  • 887
  • 888
  • 889
  • 890
  • 891
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/花生_TL007/article/detail/230033?site
推荐阅读
相关标签
  

闽ICP备14008679号