Python开发五子棋小游戏


Posted in Python onApril 28, 2022

了解游戏的规则是我们首先需要做的事情,如果不知晓规则,那么我们肯定寸步难行。

五子棋游戏规则:

1.对局双方各执一色棋子。
2.空棋盘开局。
3.黑先、白后,交替下子,每次只能下一子。
4.棋子下在棋盘的空白点上,棋子下定后,不得向其它点移动,不得从棋盘上拿掉或拿起另落别处。
5.黑方的第一枚棋子可下在棋盘任意交叉点上。
6.轮流下子是双方的权利,但允许任何一方放弃下子权(即:PASS权)。

五子棋对局,执行黑方指定开局、三手可交换、五手两打的规定。整个对局过程中黑方有禁手,白方无禁手。黑方禁手有三三禁手、四四禁手和长连禁手三种。

在这篇博客中我们只实现了较为简单的规则,不考虑规则6以及禁手的相关规定(个人能力有限,如果有愿意研究的朋友,我们可以一起研究研究 /抱拳)。

设计思路:

1、首先我们需要使用到界面,我们先分析界面上需要实现什么画面,也就是我们要进行这个五子棋游戏要看到什么。要看到:棋盘,棋子(棋子要分颜色,黑色和白色),这些是进行游戏的必需看到的。

2、外表做好以后我们需要去思考内部代码的填充,思考:

①棋子如何落到指定的位置,
②如何实现交替落子,实现颜色交替变换,并且做好记录方便计算棋子排布情况。
③如何计算四个方位上的同色棋子达到获胜的数量。

首先把窗口调出来,实现代码:

from tkinter import *#导入窗口第三方库
root = Tk()       #创建窗口
root.title("憨憨制作的五子棋")  #窗口名字
w1 = Canvas(root, width=600,height=600,background='lightcyan')#在窗口中央创建一个画布,root是窗口,宽度600,高度600,背景色为lightcyan
w1.pack()    #布局方式,全局需要统一。
mainloop()

Python开发五子棋小游戏

五子棋棋盘是由15条横线15条竖线组成的。

画出棋盘:

for i in range(0, 15):
    w1.create_line(i * 40 + 20, 20, i * 40 + 20, 580)
    w1.create_line(20, i * 40 + 20, 580, i * 40 + 20)
w1.create_oval(135, 135, 145, 145,fill='black')
w1.create_oval(135, 455, 145, 465,fill='black')
w1.create_oval(465, 135, 455, 145,fill='black')
w1.create_oval(455, 455, 465, 465,fill='black')
w1.create_oval(295, 295, 305, 305,fill='black')

窗口的左上角坐标为(0,0),通过调试,我们得出起始位置为(20,20)较为合适,多次调试进行对比,我选择线间距为40比较不错。当然线宽,圆的大小,棋盘线的间距这些都是可以进行调整的,大家可以慢慢试探(h_h)。棋盘中的五个黑点需要我们通过计算得出位置。
create_line(起点,终点):画直线
create_oval(x1,y1,x2,y2,fill=‘颜色’)这个是画一个内切圆,矩形左上角(x1,y1),右下角(x2,y2)fill为填充色,我们可以从网上找到turtle颜色库,顺便帮大家找了一个,自行选择自己喜欢的颜色。

Python开发五子棋小游戏

效果图:

Python开发五子棋小游戏

棋盘做好了,我们开始设计落子,这里需要交替进行颜色的改变,那我们就需要去通过一个判断方法来进行改变棋子的颜色。我想了两种:①一种是用字符标记当前鼠标上棋子的颜色,改变为另一种。②另一种是用计数的方式来进行改变。除此之外我们要规定已经放了棋子的位置不能再放棋子,也就是在落子前先判断当前位置是否有棋子。

num=0        #计算棋盘上有几个棋子,用来判断下一颗棋子颜色
A=np.full((15,15),0    )        #储存位置已有棋子的矩阵
B=np.full((15,15),'')        #用来记录每个位置棋子的颜色
def callback(event):        #输入的是点击事件,event.x和event.y是鼠标点击事件的位置
    global num ,A            #全局变量可以全局使用
    for j in range (0,15):    #双重循环定位点击位置最近的网格线交点(i,j),保证棋子落在线的交点处。
        for i in range (0,15):
            if (event.x - 20 - 40 * i) ** 2 + (event.y - 20 - 40 * j) ** 2 <= 2 * 20 ** 2:
                break
        if (event.x - 20 - 40 * i) ** 2 + (event.y - 20 - 40 * j) ** 2 <= 2*20 ** 2:
            break
    if num % 2 == 0 and A[i][j] != 1:#判断现在这颗棋子的颜色。
        w1.create_oval(40*i+5, 40*j+5, 40*i+35, 40*j+35,fill='black')
        A[i][j] = 1
        B[i][j] = 'b'
        num += 1
    if num % 2 != 0 and A[i][j] != 1 :
        w1.create_oval(40*i+5, 40*j+5, 40*i+35, 40*j+35,fill='white')
        A[i][j] = 1
        B[i][j] = 'w'
        num += 1

落子以后需要计算是否五子连珠,每个棋子的计算方向有八个形成四条线,那么就是从落子处算先向一端算,直到遇到另一种颜色的棋子,反向查询遇到另一个颜色棋处出停止,当达到五颗棋子时即代表一方获胜,否则循环下一条线。当四条线结束未达到胜利条件,即可继续落子。

f = [[-1, 0], [-1, 1], [0, 1], [1, 1]] #四条线其中一个方向的坐标变化规律
    for z in range(0, 4):                 #循环方向
        a, b = f[z][0], f[z][1]
        count1, count2 = 0, 0
        x, y = i, j
        while B[x][y] == B[i][j]:#当颜色相同即可进行计算
            count1 += 1
            if x + a > 0 and y + b > 0 and x + a < 15 and y + b < 15 and B[x + a][y + b] == B[i][j]:#保证不超出矩阵的边界,否则会报错
                [x, y] = np.array([x, y]) + np.array([a, b])
            else:
                x, y = i, j     
                break
        while B[x][y] == B[i][j]:#从落子处反向计算同色棋子个数。
            count2 += 1
            if x - a < 15 and y - b < 15 and x - a > 0 and y - b > 0 and B[x - a][y - b] == B[i][j]:
                [x, y] = np.array([x, y]) - np.array([a, b])
            else:
                break
        if count1 + count2 == 6:            #计算了两次落子处
            if B[i][j] == 'b':
                tkinter.messagebox.showinfo('提示', '黑棋获胜')
            else:
                tkinter.messagebox.showinfo('提示', '白棋获胜')

点击事件,每次点击以后都需要进行一次落子和游戏结束判断。调用函数进行落子,判断是否结束游戏。

w1.bind("<Button -1>",callback)
w1.pack()

设置退出按钮:

u=Button(root,text="退出",width=10,height=1,command=quit,font=('楷体',15))
u.pack()

完整代码:

from tkinter import *
import tkinter.messagebox  # 弹窗库
import numpy as np

root = Tk()                                 #创建窗口
root.title("憨憨制作的五子棋")                  #窗口名字
w1 = Canvas(root, width=600,height=600,background='lightcyan')
w1.pack()

for i in range(0, 15):
    w1.create_line(i * 40 + 20, 20, i * 40 + 20, 580)
    w1.create_line(20, i * 40 + 20, 580, i * 40 + 20)
w1.create_oval(135, 135, 145, 145,fill='black')
w1.create_oval(135, 455, 145, 465,fill='black')
w1.create_oval(465, 135, 455, 145,fill='black')
w1.create_oval(455, 455, 465, 465,fill='black')
w1.create_oval(295, 295, 305, 305,fill='black')

num=0
A=np.full((15,15),0)
B=np.full((15,15),'')
def callback(event):
    global num ,A
    for j in range (0,15):
        for i in range (0,15):
            if (event.x - 20 - 40 * i) ** 2 + (event.y - 20 - 40 * j) ** 2 <= 2 * 20 ** 2:
                break
        if (event.x - 20 - 40 * i) ** 2 + (event.y - 20 - 40 * j) ** 2 <= 2*20 ** 2:
            break
    if num % 2 == 0 and A[i][j] != 1:
        w1.create_oval(40*i+5, 40*j+5, 40*i+35, 40*j+35,fill='black')
        A[i][j] = 1
        B[i][j] = 'b'
        num += 1
    if num % 2 != 0 and A[i][j] != 1 :
        w1.create_oval(40*i+5, 40*j+5, 40*i+35, 40*j+35,fill='white')
        A[i][j] = 1.
        B[i][j] = 'w'
        num += 1

    f = [[-1, 0], [-1, 1], [0, 1], [1, 1]]
    for z in range(0, 4):
        a, b = f[z][0], f[z][1]
        count1, count2 = 0, 0
        x, y = i, j
        while B[x][y] == B[i][j]:
            count1 += 1
            if x + a > 0 and y + b > 0 and x + a < 15 and y + b < 15 and B[x + a][y + b] == B[i][j]:
                [x, y] = np.array([x, y]) + np.array([a, b])
            else:
                x, y = i, j
                break
        while B[x][y] == B[i][j]:
            count2 += 1
            if x - a < 15 and y - b < 15 and x - a > 0 and y - b > 0 and B[x - a][y - b] == B[i][j]:
                [x, y] = np.array([x, y]) - np.array([a, b])
            else:
                break
        if count1 + count2 == 6:
            if B[i][j] == 'b':
                tkinter.messagebox.showinfo('提示', '黑棋获胜')
            else:
                tkinter.messagebox.showinfo('提示', '白棋获胜')

w1.bind("<Button -1>",callback)
w1.pack()
def quit():
    root.quit()

u=Button(root,text="退出",width=10,height=1,command=quit,font=('楷体',15))
u.pack()

mainloop()

技术不精,但是喜欢做点小研究,从学习中找到玩耍的快乐,愿意和大家一起学习玩耍。


Tags in this post...

Python 相关文章推荐
Python时间戳与时间字符串互相转换实例代码
Nov 28 Python
python常用web框架简单性能测试结果分享(包含django、flask、bottle、tornado)
Aug 25 Python
Python中输出ASCII大文字、艺术字、字符字小技巧
Apr 28 Python
python实现从字典中删除元素的方法
May 04 Python
一文带你了解Python中的字符串是什么
Nov 20 Python
Python button选取本地图片并显示的实例
Jun 13 Python
如何使用Python自动控制windows桌面
Jul 11 Python
Django框架组成结构、基本概念与文件功能分析
Jul 30 Python
django删除表重建的实现方法
Aug 28 Python
Python分割训练集和测试集的方法示例
Sep 19 Python
Python测试Kafka集群(pykafka)实例
Dec 23 Python
PyQt5 closeEvent关闭事件退出提示框原理解析
Jan 08 Python
Python简易开发之制作计算器
Apr 28 #Python
Python实现对齐打印 format函数的用法
Apr 28 #Python
python实现简单的三子棋游戏
Apr 28 #Python
Python内置类型集合set和frozenset的使用详解
使用Python获取字典键对应值的方法
Apr 26 #Python
PyTorch中permute的使用方法
Apr 26 #Python
Python matplotlib 利用随机函数生成变化图形
You might like
实例讲解YII2中多表关联的使用方法
2017/07/21 PHP
PHP bin2hex()函数基础实例讲解
2019/02/11 PHP
学习YUI.Ext 第四天--对话框Dialog的使用
2007/03/10 Javascript
jquery实现每个数字上都带进度条的幻灯片
2013/02/20 Javascript
JavaScript创建类/对象的几种方式概述及实例
2013/05/06 Javascript
jQuery.parseJSON(json)将JSON字符串转换成js对象
2014/07/27 Javascript
详解JavaScript基于面向对象之继承实例
2015/12/16 Javascript
JS禁用页面上所有控件的实现方法(附demo源码下载)
2015/12/17 Javascript
JavaScript性能优化之函数节流(throttle)与函数去抖(debounce)
2016/08/11 Javascript
快速入门Vue
2016/12/19 Javascript
angularjs 实现带查找筛选功能的select下拉框实例
2017/01/11 Javascript
three.js实现围绕某物体旋转
2017/01/25 Javascript
jQuery上传插件webupload使用方法
2017/08/01 jQuery
Javascript防止图片拉伸的自适应处理方法
2017/12/26 Javascript
JS实现的判断方法、变量是否存在功能示例
2020/03/28 Javascript
React学习笔记之高阶组件应用
2018/06/02 Javascript
jQuery - AJAX load() 实例用法详解
2019/08/27 jQuery
vue 实现用户登录方式的切换功能
2020/04/14 Javascript
修改Vue打包后的默认文件名操作
2020/08/12 Javascript
基于elementUI竖向表格、和并列的案例
2020/10/26 Javascript
Python文件操作类操作实例详解
2014/07/11 Python
python中随机函数random用法实例
2015/04/30 Python
python实现列表中由数值查到索引的方法
2018/06/27 Python
Flask框架WTForm表单用法示例
2018/07/20 Python
python循环定时中断执行某一段程序的实例
2019/06/29 Python
对Python生成器、装饰器、递归的使用详解
2019/07/19 Python
html5 兼容IE6结构的实现代码
2012/05/14 HTML / CSS
法国奢华女性时尚配饰网上商店:Monnier Frères
2016/08/27 全球购物
瑞典领先的汽车零部件网上零售商:bildelaronline24.se
2017/01/12 全球购物
英国最大的在线蜡烛商店:Candles Direct
2019/03/26 全球购物
M.M.LaFleur官网:美国职业女装品牌
2020/10/27 全球购物
与UNIX有关的几个名词
2015/09/17 面试题
党员批评与自我批评材料
2014/10/14 职场文书
村党建工作汇报材料
2014/11/02 职场文书
幼师辞职信范文大全
2015/05/12 职场文书
网吧管理制度范本
2015/08/05 职场文书