Python百日百行代码挑战-day8,day9,day10,游戏实战系列-五子棋

写在前面

这次写游戏的时候感觉自己明显比之前写贪吃蛇的时候思路拓宽了很多,上一次基本上都是看着我买的教程一点点敲出来了,这次基本上可以说就是我自己写出来的(所以bug变得越来越多了),不过参考了一点教程中部分函数的用法等等。之前感觉这个五子棋的游戏会比贪吃蛇简单很多,实际写下来,发现语法上好像是简单了一些,但是逻辑上变难了,尤其是五子判定花了很长的时间,所以用了三天时间才写出来,接下来记录一下这三天我做的事情。想要代码可以私聊我,但是请别用于商业活动。

需要用到的工具包和参考

  • tkinter
  • time
  • numpy(其实可有可无)
  • 取色器
  • 感谢某个大佬,部分想法来源于大佬,她csdn博客是:白曦(Bessie)

游戏设定

初始化

首先需要初始化一些参数,我介绍其中的一部分吧

		self.step = 1     # 记录一下步数,在后面判定是哪一方走的棋子用的
        self.overr = 0     # 判断游戏是否结束的参数
        self.currentcolor = '#000000'     # 当前颜色,在取色器网址里面随便挑你喜欢的
        self.trancolor = 1   # 判断是否切换颜色参数(就是该不该下一个人下棋了)
        self.show = '0'    # 步数展示
        self.awin = 0      # 黑方赢
        self.bwin = 0      # 绿方赢
        self.board = np.zeros((15,15))    # 棋盘的初始化
        self.line = (100, 130, 160, 190, 220, 250, 280, 310, 340, 370, 400, 430, 460, 490, 520)  # 从这往下都是棋盘界面的初始化
        for i in self.line:
            self.canvas.create_line(100, i, 520, i)
            self.canvas.create_line(i, 100, i, 520)

切换下棋方

    def colorex(self):
        if self.trancolor == 1:
            self.currentcolor = '#000000'
            self.trancolor = 0
        else:
            self.currentcolor = '#BCE7A0'
            self.trancolor = 1

这个函数太简单了,看一下就懂了,一开始是黑棋走,而我的初试值为1,所以就让当前颜色为黑色就行了,然后把trancolor参数的值改变一下。一个需要注意的点就是,我这里是在类里面写的,所以前面加一个self就行,如果不写类直接写函数的话,这些参数前面要加global来表示是全局变量。

判断五子连珠(核心)

这个地方卡了我好久,写的时候总是会有奇奇怪怪的东西出现,这里我将记录一下我的踩坑记录和最后正确判定的方法(其实也不能说完全正确,有的时候还是很随缘会出现一些bug导致下棋出问题的,真就是一模一样的代码,重启前好好地,重启了不行了,淦!)

踩坑记录
一开始我的想法是这样:
1 创建两个列表,一个列表记录黑子落子坐标,另一个列表记录绿字落子坐标
2 从第五个子开始(step当中记录的第9步)开始遍历下棋者的坐标列表
3 判断横向五子方法:从第一个坐标开始,向后遍历4个棋子,如果横坐标都相等,则五子连珠,如果不相等,就从第二个棋子重新开始遍历
4 判断竖向五子方法:从第一个坐标开始,向后遍历4个棋子,如果纵坐标都相等,则五子连珠,如果不相等,就从第二个棋子开始重新遍历
5 判断斜向五子方法:从第一个坐标开始,向后遍历4个棋子,如果两两坐标相差为1,则五子连珠,如果不相等,就从第二个棋子开始遍历
6 如上述条件均不成立,则棋局继续,返回至第2步。

后来我发现吧,这个方法真的是太勾八了,比如人家万一这么走呢:
在这里插入图片描述
反正就是一个简略的棋谱,凑活看吧。
也就是说,他走的棋子和之前的棋子意外成了5个,那我这个方法就完全没有作用了。还有一些很细节的问题,但是并不是逻辑本身的问题,就不写了,一些代码的小问题。

暴力解法
这个解法是一个大佬提供给我的,她真的超级优秀,不过我最后没用这个方法就是了哈哈哈哈哈。

她的方法是:
1 从第9步开始,对整个棋盘进行遍历(我的棋盘是15*15)
2 横向遍历棋盘,如果遇到颜色连起来一致的5个,就达成五子连珠
3 竖向遍历棋盘,同上
4 斜向遍历棋盘,同上
5 如果没有就再遍历一次,回到1

这个办法可以说成功率100%,不过感觉太浪费计算机空间和时间了,主要是我真的懒得写这玩意的代码,感觉听起来就很麻烦啊哈哈哈哈

最终算法
最终选择了“米”字型判定算法,计算方法如下:
1 从下棋点开始遍历
2 采用5中心算法(没错我自己想的),对横向纵向和斜向进行遍历,结果大于15即为胜利
3 如果没结束,再次进行循环。

5中心算法
黑方落子,该点在board矩阵中的值记录为1,绿方落子,记录为2。同时设置一个权重值,落子点的权重为5。以横向为例:从最左边开始遍历,如果该点存在且值和落子点一致,则权重+1,以此类推,直到落子点左边的一个,则+4。再从右边开始,从最靠近右边开始,权重+1,直到最右边,权重+4。(这里的最左最右是米字的左右,也就是左遍历4个,右遍历4个。)

在这里插入图片描述
就是这样的,你品,你细品,是不是随便5个子加和起来都是15,如果不连续加和起来就不是15,我直接判断一个大的整体,剩下的交给python,关键是这个方法代码很好写啊!比如在边界处,有一个值不存在,我直接让这个东西等于某个变量,就会报错超出边界。这么写代码的话,只要不存在那个sum就不加就行了,很方便的,上代码。(仅展示横向,其他的都一样)

    def raw(self,a,b):
        ori = self.board[a][b]
        sum = 5
        if (a-4) >= 0:
            if self.board[a-4][b] == ori:
                sum+=1
        if (a-3) >= 0:
            if self.board[a-3][b] == ori:
                sum+=2
        if (a-2) >= 0:
            if self.board[a-2][b] == ori:
                sum+=3
        if (a-1) >= 0:
            if self.board[a-1][b] == ori:
                sum+=4
        if (a+1) <= 14:
            if self.board[a+1][b] == ori:
                sum+=1
        if (a+2) <= 14:
            if self.board[a+2][b] == ori:
                sum+=2
        if (a+3) <= 14:
            if self.board[a+3][b] == ori:
                sum+=3
        if (a+4) <= 14:
            if self.board[a+4][b] == ori:
                sum+=4

        if sum>=15 and ori == 1:
            self.awin = 1

        if sum>=15 and ori == 2:
            self.bwin = 1

鼠标点击流程事件

就是一些超级简单的逻辑,不写解释了,直接上代码吧

    def action(self,event):
        time.sleep(0.05)
        if event.x < 100 or event.x > 520 or event.y < 100 or event.y > 520:  # 鼠标不能点击界外
            pass
        else:
            self.colorex()
            self.x1 = round((event.x - 100) / 30)   # 鼠标点击对应的矩阵坐标
            self.y1 = round((event.y - 100) / 30)

            self.x11 = self.x1*30+100   # 矩阵坐标对应的画布坐标
            self.y11 = self.y1*30+100

            if self.board[self.x1][self.y1] == 0:
                self.board[self.x1][self.y1] = 1
                self.canvas.create_oval(self.x11-15,self.y11-15,self.x11+15,self.y11+15,fill=self.currentcolor)  # 画棋子
                self.show = str(self.step)
                self.step+=1
                self.canvas.delete(self.a)
                self.a = self.canvas.create_text(700,180,text=self.show,fill=self.currentcolor,font=('Times',20))  # 步数提示语句
                if self.step%2 == 0:
                    self.board[self.x1][self.y1] = 2
                else:
                    self.board[self.x1][self.y1] = 1
                self.raw(self.x1,self.y1)   # 判断是否五子连珠
                self.col(self.x1,self.y1)
                self.tilt1(self.x1,self.y1)
                self.tilt2(self.x1,self.y1)
                if self.awin == 1:
                    self.canvas.create_text(400,300,text="绿方赢",fill='#663333',font=('Times',50))
                    self.overr = 1
                if self.bwin == 1:
                    self.canvas.create_text(400,300,text="黑方赢",fill='#663333',font=('Times',50))
                    self.overr = 1

            if self.overr == 1:
                self.canvas.create_text(400,400,text='Game Over',fill='#663333',font=('Times',30))

成品展示

在这里插入图片描述

打包成exe文件

最后是怎么把py文件打包成exe的方法
首先你得有一个pyinstaller的包,在阿里云等等镜像网址都可以下载
我这里是在虚拟环境中安装的pyinstaller的,所以首先我激活了一下虚拟环境,然后用这个命令

pyinstaller -F F:\1.py

这个就是我的路径,然后就能打包了。会自动保存到这个路径
在这里插入图片描述
命令提示出现一堆东西的时候就是好了。

真的是麻了,py文件运行正常,exe就不行,懒得改了,太浪费时间了。

总结

真难写啊
防火防盗防诈骗

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值