python小游戏(华容道)

python基础运用
1、定义块
定义相应的块,每个方块实际就是一个按钮,所以继承Button类。每个方块的基本数据,除了方块的类型以外还有左上角的坐标,一旦确定方块的类型和坐标后,就可以确定方块对应的角色和位置了。方块左上角坐标用Point类的对象来表示,并在Block类中定义一个属性Location来表示

from tkinter import *
One=1;TowH=2;TowV=1;Four=4
class Point:
    def __init__(self,x,y): #定义坐标X,Y
        self.X=x
        self.Y=y
class Block(Button):   #块类 

    def __init__(self,p,blockType,master,r,bm):
        Button.__init__(self,master)

        self.Location=p

        self.BType=blockType

        self["text"]=r

        self["image"]=bm

        self.bind("",btn_MouseDown);

        self.bind("",btn_Release);

        self.place(x=self.Location.X*80,y=self.Location.Y*80)

2、定义初始坐标位置,判断条件
坐标图如下:
python小游戏(华容道)_第1张图片 python小游戏(华容道)_第2张图片
每个块都相应完成具体的操作,每个块功能如下:
(1) Block类中定义一个函数GetPoints来
获取该方块所占据的所有坐标位置的列表,
通过方块类型和左上角的坐标就可以得到
占据的所有坐标位置。
(2) 再定义函数 IsValid 来判断这个方块是
否在游戏区域内,如果有任何部分出界就
返回False,可以通过方块类型和左上角坐
标来判断。
(3) 函数Intersects(Block b) 用来判断一个
角色是否和另一个角色有重叠部分,如果
有则返回True,通过获取两个角色各自占
据的点来判断是否有重叠。

#定义得到游戏图片的初始位置
    def getPoints(self):
        pList=[]
        if self.BType==One:
            pList.append(self.Location)
        elif self.BType==TowH:
            pList.append(self.Location)
            pList.append(Point(self.Location.X+1,self.Location.Y))
        elif self.BType==TowV:
            pList.append(self.Location)
            pList.append(Point(self.Location.X,self.Location.Y+1))
        elif self.BType==Four:
            pList.append(self.Location)
            pList.append(Point(self.Location.X,self.Location.Y+1))
            pList.append(Point(self.Location.X+1,self.Location.Y))
            pList.append(Point(self.Location.X+1,self.Location.Y+1))
        return  pList
    def isValid(self,width,height): #判断移动边界条件
        points=self.getPoints()
        for i in points:
             if i.X<0 or i.X>=width or i.Y<0 or i.Y>=height:
                 return False
        return True
    def Intersects(self,block): #判断角色是否重叠
        mypoints=self.getPoints()
        otherpoints=block.getPoints()
        for i in mypoints:
            for j in otherpoints:
                if i.X==j.X and i.Y==j.Y:
                    return True
        return False

3定义Game控制游戏
(1). 定义Game类并定义一些变量
首先包含场地的宽度和高度,
在华容道中宽度为4格,高度为5
格,在类中定义变量 Width=4;
Height=5类中定义一个列表保存
游戏中的所有方块,开始为空:
Blocks = [ ],类中再定义一个
变量保存结束位置坐标,变量名
和代码:finishPoint = Point(1,3)
(2). 在类中定义函数GetBlockByPos(self, p )获取指定位置方块
(3). AddBlock(self, block) 用于向列表Blocks中添加方块,
可用来编辑游戏。需要判断添加的方块是否已经在列表内,是否在有效范围内,以及是否和任何已在列表中的方块有重叠,都符合条件才允许添加,代码如有图。
(4). 定义函数MoveBlock用来移动角色的方块
MoveBlock所做的是将移动的方块先朝指
定方向移动,然后判断该方块是否出界,是否
与其他方块有重叠,如果是则保留在原来的位
置,否则进行移动更新位置。
(5). 定义函数GameWin判断游戏是否胜利
根据类的全局变量WinFlag的值来判断
游戏是否胜利。在函数MoveBlock中会判断
曹操是否移动到位置(1,3)这个坐标,如果是
则把WinFlag的值置为True。

   class Game(): #控制游戏模块,
    Width=4
    Height=5
    WinFlag=False
    Blocks=[]
    finishPoint=Point(1,3)
    def GetBlockByPos(self,p):
        for i in self.Blocks:
            if i.Location.X==p.X and i.Location.Y==p.Y:
                return i
        return False
    def AddBlock(self,block):
        if block in self.Blocks:
            return False
        if not block.isValid(self.Width,self.Height):
            return False
        for i in self.Blocks:
            if i.Intersects(block):
                return False
        self.Blocks.append(block)
        return True
    def MoveBlock(self,block,direction):
        if block not in self.Blocks:
            return
        oldx=block.Location.X
        oldy=block.Location.Y
        if direction=="Up":
            block.Location.Y-=1
        elif direction=="Down":
            block.Location.Y+=1
        elif direction=="Left":
            block.Location.X-=1
        elif direction=="Right":
            block.Location.X+=1
        moveOK=True
        if not block.isValid(self.Width,self.Height):
            moveOK=False
        else:
            for i in self.Blocks:
                if (block is not i) and block.Intersects(i):
                    moveOK=False
                    break
        if moveOK==False:
            block.Location=Point(oldx,oldy)
        else:
            if block["text"]=="曹操" and block.Location.X==1 and block.Location.Y==3:
                self.WinFlag=True
        return moveOK
    def GameWin(self):
        return self.WinFlag

oldx=0    #保存方块移动之前的x轴坐标

oldy=0    #保存方块移动之前的y轴坐标

BlockSize = 80   #方块的显示范围

mouseDownPoint=Point(0,0)#鼠标按下位置

mouseDown=False    #标记鼠标是否按下

4、游戏结果处理
(1). 控制游戏的全局变量
oldx=0 #保存方块移动之前的x轴坐标
oldy=0 #保存方块移动之前的y轴坐标
BlockSize = 80 #方块的显示范围
mouseDownPoint=Point(0,0)#鼠标按下位置
mouseDown=False #标记鼠标是否按下
(2). 函数btn_MouseDown(event)
处理鼠标按下的事件,
把按下坐标值保存到各个变量。
(3). 函数btn_Realse(event)
处理鼠标松开的事件,根据鼠标拖动的水平和
垂直方向偏移量超过方格大小1/3,
则向此方向移动。

def btn_MouseDown(event):
    global oldx,oldy,mouseDownPoint,mouseDown
    mouseDownPoint=Point(event.x,event.y)
    mouseDown=True
    oldx=event.x
    oldy=event.y
    print(event.x,event.y)
def btn_Release(event):
    global oldx,oldy,mouseDownPoint,mouseDown
    if not mouseDown:
        return
    moveH=event.x-mouseDownPoint.X
    moveV=event.y-mouseDownPoint.Y
    x=int(event.widget.place_info()["x"])//80
    y=int(event.widget.place_info()["y"])//80
    block=game.GetBlockByPos(Point(x,y))

    if moveH>=BlockSize//3:
        game.MoveBlock(block,"Right")
    elif moveH<=-BlockSize//3:
        game.MoveBlock(block,"Left")
    elif moveV>=BlockSize//3:
        game.MoveBlock(block,"Down")
    elif moveV<=-BlockSize//3:
        game.MoveBlock(block,"Up")
    else:
        return

    event.widget.place(x=block.Location.X*80,y=block.Location.Y*80)
    if game.GameWin():
        print("游戏胜利")
    mouseDown=False


#win=Tk()
win=Toplevel()
win.title("华容道游戏")
win.geometry("320x400")

game=Game()

role=["曹操","关羽","黄忠","张飞","马超","赵云","兵","兵","兵","兵"]
bm=[PhotoImage(file="bmp\\%s.png"%(i)) for i in role]
block_para=[(Point(1,0),Four),(Point(1,2),TowH),(Point(3,2),TowV),(Point(0,0),TowV),
            (Point(0,2),TowV),(Point(3,0),TowV),(Point(1,3),One),(Point(2,3),One),
            (Point(0,4),One),(Point(3,4),One)]
for i in range(10):
    b=Block(block_para[i][0],block_para[i][1],win,role[i],bm[i])
    game.AddBlock(b)

win.mainloop()

参考资料链接: https://pan.baidu.com/s/1sGQFOyJpsDDCmnj68c4FFw 密码: rzqa

你可能感兴趣的:(兴趣作品)