Python五子棋程序实现详解

Python五子棋程序实现详解

    • 引言
    • 功能实现
      • 显示棋盘
      • 点击落子
      • 判断胜负
      • 游戏结束判断
      • 交替落子
    • 运行结果
    • 完整代码
    • 总结

引言

五子棋是一种广泛传播的策略棋类游戏,两人对弈,通过在棋盘上落子,以先形成连续的相同颜色的五子棋为胜利条件。本文将介绍如何使用Python编写一个简单的五子棋程序,实现了五子棋游戏的基本功能。

功能实现

显示棋盘

首先,我们需要在程序中显示一个19x19的五子棋棋盘。使用tkinter库可以快速实现可视化界面的搭建。

# 定义常量
ROWS = 19
COLS = 19
PADDING = 30
GRID_SIZE = 20

# 创建棋盘
board = [[0] * COLS for _ in range(ROWS)]

# 创建窗口
window = tk.Tk()
window.title("五子棋")
window.geometry(str(COLS * GRID_SIZE + PADDING * 2) + "x" + str(ROWS * GRID_SIZE + PADDING * 2 + 40))

# 创建画布
canvas = tk.Canvas(window, width=COLS * GRID_SIZE + PADDING * 2, height=ROWS * GRID_SIZE + PADDING * 2, bg="burlywood")
canvas.place(x=0, y=PADDING)

# 绘制棋盘线
for i in range(ROWS):
    canvas.create_line(PADDING, i * GRID_SIZE + PADDING, COLS * GRID_SIZE + PADDING - GRID_SIZE, i * GRID_SIZE + PADDING)
for i in range(COLS):
    canvas.create_line(i * GRID_SIZE + PADDING, PADDING, i * GRID_SIZE + PADDING, ROWS * GRID_SIZE + PADDING - GRID_SIZE)

# 绘制黑点
for i in range(3, ROWS, 6):
    for j in range(3, COLS, 6):
        canvas.create_oval(j * GRID_SIZE + PADDING - 3, i * GRID_SIZE + PADDING - 3,
                           j * GRID_SIZE + PADDING + 3, i * GRID_SIZE + PADDING + 3, fill="black")

以上代码使用tkinter库创建了一个窗口,并在窗口内创建了一个棋盘。我们使用了Canvas组件来绘制棋盘上的线条和黑点。

点击落子

接下来,我们需要实现在棋盘上点击鼠标落子的功能。

def on_click(event):
    # 处理鼠标点击事件
    row = round((event.y - PADDING) / GRID_SIZE)
    col = round((event.x - PADDING) / GRID_SIZE)

    if row < 0 or row >= ROWS or col < 0 or col >= COLS:
        # 落子在棋盘外侧
        messagebox.showinfo("提示", "不可以落子在棋盘外哦!")
        return

    if not is_valid_move(row, col):
        # 提示落子位置已有棋子
        messagebox.showinfo("提示", "此处已有棋子,不可重复落子")
        return

    global current_player
    if current_player == 1:  # 蓝方玩家
        color = "blue"
        label.config(text="红方玩家的回合")
    else:  # 红方玩家
        color = "red"
        label.config(text="蓝方玩家的回合")

    board[row][col] = current_player
    x = col * GRID_SIZE + PADDING
    y = row * GRID_SIZE + PADDING
    canvas.create_oval(x - GRID_SIZE // 2, y - GRID_SIZE // 2, x + GRID_SIZE // 2, y + GRID_SIZE // 2, fill=color)

    if is_winner(current_player):
        if current_player == 1:
            messagebox.showinfo("游戏结束", "蓝方玩家获胜")
        else:
            messagebox.showinfo("游戏结束", "红方玩家获胜")
        window.quit()
    else:
        current_player = 2 if current_player == 1 else 1

# 绑定鼠标点击事件
canvas.bind("<Button-1>", on_click)  # 左键点击
canvas.bind("<Button-3>", on_click)  # 右键点击

以上代码定义了一个on_click函数来处理鼠标点击事件。函数首先根据点击的位置计算出对应的行列索引,然后检查是否落子在有效位置上。如果位置无效(落子在棋盘外侧或已有棋子),则弹出提示信息。如果位置有效,根据当前玩家的不同,设置棋子的颜色,并绘制出棋子。然后检查是否有玩家获得胜利,如果有,则弹出提示信息并退出游戏。如果没有胜利,切换当前玩家。

判断胜负

接下来,我们需要编写一个函数来判断当前是否有玩家已经胜利。

def is_winner(player):
    # 检查玩家是否胜利
    for row in range(ROWS):
        for col in range(COLS):
            if board[row][col] == player:
                # 检查水平方向
                if col + 4 < COLS and all(board[row][col + i] == player for i in range(5)):
                    return True
                # 检查垂直方向
                if row + 4 < ROWS and all(board[row + i][col] == player for i in range(5)):
                    return True
                # 检查对角线方向(左上到右下)
                if row + 4 < ROWS and col + 4 < COLS and all(board[row + i][col + i] == player for i in range(5)):
                    return True
                # 检查对角线方向(右上到左下)
                if row + 4 < ROWS and col - 4 >= 0 and all(board[row + i][col - i] == player for i in range(5)):
                    return True
    return False

以上代码定义了一个is_winner函数来判断指定玩家是否获胜。函数首先遍历棋盘上的每个位置,如果该位置的棋子颜色与指定玩家相同,则进行进一步检查。检查水平方向、垂直方向以及两个对角线方向上是否有连续的五个相同颜色的棋子,如果有,则返回True表示获胜,否则返回False表示未获胜。

游戏结束判断

on_click函数中,每当有玩家落子后,会检查是否有玩家获胜,如果有,则弹出提示信息并退出游戏。

交替落子

on_click函数中,每当有玩家落子后,会切换当前玩家。这通过全局变量current_player实现,初始值为1(蓝方玩家),当某一方落子后,将current_player的值切换为另一方(2表示红方玩家)。

运行结果

通过以上的代码实现,我们可以得到一个能够实现基本五子棋功能的程序。

程序运行时,会弹出一个窗口,窗口中显示了一个19x19的五子棋棋盘。玩家可以通过鼠标左键或右键点击棋盘上的格子进行落子。每当有玩家落子后,程序会自动判断是否有玩家获胜,并在弹出提示信息后结束游戏。

在程序运行过程中,程序会在窗口底部显示当前是哪一方玩家的回合,玩家可以根据该提示进行操作,避免出现误操作。同时,程序还会对一些错误的操作给出相应的提示,提高了游戏的友好度。

在这里插入图片描述

在这里插入图片描述

完整代码

import tkinter as tk
from tkinter import messagebox

# 定义常量
ROWS = 19
COLS = 19
PADDING = 30
GRID_SIZE = 20

# 创建棋盘
board = [[0] * COLS for _ in range(ROWS)]


def is_valid_move(row, col):
    # 检查落子是否有效
    return board[row][col] == 0


def is_winner(player):
    # 检查玩家是否胜利
    for row in range(ROWS):
        for col in range(COLS):
            if board[row][col] == player:
                # 检查水平方向
                if col + 4 < COLS and all(board[row][col + i] == player for i in range(5)):
                    return True
                # 检查垂直方向
                if row + 4 < ROWS and all(board[row + i][col] == player for i in range(5)):
                    return True
                # 检查对角线方向(左上到右下)
                if row + 4 < ROWS and col + 4 < COLS and all(board[row + i][col + i] == player for i in range(5)):
                    return True
                # 检查对角线方向(右上到左下)
                if row + 4 < ROWS and col - 4 >= 0 and all(board[row + i][col - i] == player for i in range(5)):
                    return True
    return False


def on_click(event):
    # 处理鼠标点击事件
    row = round((event.y - PADDING) / GRID_SIZE)
    col = round((event.x - PADDING) / GRID_SIZE)

    if row < 0 or row >= ROWS or col < 0 or col >= COLS:
        # 落子在棋盘外侧
        messagebox.showinfo("提示", "不可以落子在棋盘外哦!")
        return

    if not is_valid_move(row, col):
        # 提示落子位置已有棋子
        messagebox.showinfo("提示", "此处已有棋子,不可重复落子")
        return

    global current_player
    if current_player == 1:  # 蓝方玩家
        color = "blue"
        label.config(text="红方玩家的回合")
    else:  # 红方玩家
        color = "red"
        label.config(text="蓝方玩家的回合")

    board[row][col] = current_player
    x = col * GRID_SIZE + PADDING
    y = row * GRID_SIZE + PADDING
    canvas.create_oval(x - GRID_SIZE // 2, y - GRID_SIZE // 2, x + GRID_SIZE // 2, y + GRID_SIZE // 2, fill=color)

    if is_winner(current_player):
        if current_player == 1:
            messagebox.showinfo("游戏结束", "蓝方玩家获胜")
        else:
            messagebox.showinfo("游戏结束", "红方玩家获胜")
        window.quit()
    else:
        current_player = 2 if current_player == 1 else 1


# 创建窗口
window = tk.Tk()
window.title("五子棋")
window.geometry(str(COLS * GRID_SIZE + PADDING * 2) + "x" + str(ROWS * GRID_SIZE + PADDING * 2 + 40))

# 创建画布
canvas = tk.Canvas(window, width=COLS * GRID_SIZE + PADDING * 2, height=ROWS * GRID_SIZE + PADDING * 2, bg="burlywood")
canvas.place(x=0, y=PADDING)

# 绘制棋盘线
for i in range(ROWS):
    canvas.create_line(PADDING, i * GRID_SIZE + PADDING, COLS * GRID_SIZE + PADDING - GRID_SIZE, i * GRID_SIZE + PADDING)
for i in range(COLS):
    canvas.create_line(i * GRID_SIZE + PADDING, PADDING, i * GRID_SIZE + PADDING, ROWS * GRID_SIZE + PADDING - GRID_SIZE)


# 绘制黑点
for i in range(3, ROWS, 6):
    for j in range(3, COLS, 6):
        canvas.create_oval(j * GRID_SIZE + PADDING - 3, i * GRID_SIZE + PADDING - 3,
                           j * GRID_SIZE + PADDING + 3, i * GRID_SIZE + PADDING + 3, fill="black")

# 绑定鼠标点击事件
canvas.bind("<Button-1>", on_click)  # 左键点击
canvas.bind("<Button-3>", on_click)  # 右键点击

# 创建游戏信息标签
label = tk.Label(window, text="蓝方玩家的回合", font=("宋体", 14))
label.place(x=PADDING, y=PADDING * 2 + ROWS * GRID_SIZE + 10)

# 初始化当前玩家为蓝方玩家
current_player = 1

# 运行窗口的主循环
window.mainloop()

总结

本文通过使用Python编写了一个简单的五子棋程序,实现了五子棋游戏的基本功能。通过tkinter库创建了一个可视化界面,实现了显示棋盘和点击落子的功能。通过编写相应的函数实现了胜负判断和游戏结束判断的功能。整个游戏流程简洁明了,代码结构清晰。通过本文的学习,相信读者们已经掌握了使用Python编写简单游戏的基本方法。希望本文的内容对读者们有所帮助,谢谢阅读!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/275350.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JavaScript基础知识点总结:从零开始学习JavaScript(四)

学习目标&#xff1a; 掌握函数的基本使用&#xff0c;让代码具备复用能力 理解封装的意义&#xff0c;能够具备封装函数的能力 学习内容&#xff1a; 函数 综合案例 学习时间&#xff1a; 周一至周五晚上 7 点—晚上9点周六上午 9 点-上午 11 点周日下午 3 点-下午 6 点 学…

【零成本实现接口自动化测试】Java+TestNG 测试Restful service

接口自动化测试 – JavaTestNG 测试 Restful Web Service 关键词&#xff1a;基于Rest的Web服务&#xff0c;接口自动化测试&#xff0c;数据驱动测试&#xff0c;测试Restful Web Service&#xff0c; 数据分离&#xff0c;JavaMavenTestNG 本文主要介绍如何用Java针对Restf…

金蝶云星空反写规则表结构同步另一个数据库

文章目录 金蝶云星空反写规则表结构同步另一个数据库在BOS找到《反写规则》的表反写规则相关表创建反写规则&#xff0c;或者已经创建好的反写规则定位反写规则数据导出表数据执行脚本BOS导入数据库直接执行 金蝶云星空反写规则表结构同步另一个数据库 在BOS找到《反写规则》的…

k8s 网络

还没有部署网络。 k8s的网络类型&#xff1a; k8s中的通信模式&#xff1a; 1&#xff0c;pod内部之间容器和容器之间的通信。 在同一个pod中的容器共享资源和网络&#xff0c;使用同一个网络命名空间。可以直接通信的。 2&#xff0c;同一个node节点之内不同pod之间的通信。…

香橙派5plus从ssd启动Ubuntu

官方接口图 我实际会用到的就几个接口&#xff0c;背面的话就一个M.2固态的位置&#xff1a; 其中WIFI模块的接口应该也可以插2230的固态&#xff0c;不过是pcie2.0的速度&#xff0c;背面的接口则是pcie3.0*4的速度&#xff0c;差距还是挺大的。 开始安装系统 准备工作 一张…

开源轻量级分布式文件系统FastDFS本地部署并实现远程访问服务器

文章目录 前言1. 本地搭建FastDFS文件系统1.1 环境安装1.2 安装libfastcommon1.3 安装FastDFS1.4 配置Tracker1.5 配置Storage1.6 测试上传下载1.7 与Nginx整合1.8 安装Nginx1.9 配置Nginx 2. 局域网测试访问FastDFS3. 安装cpolar内网穿透4. 配置公网访问地址5. 固定公网地址5.…

算法学习系列(十三):Trie树

目录 引言一、Trie概念二、Trie树模板三、例题 引言 这个Trie还是比较有用的&#xff0c;主要的功能就是高效的存储和查找字符串的数据结构。 一、Trie概念 假设这个Trie只存储小写字母的话&#xff1a; 这个大概就是这么个概念&#xff0c;就是头结点是0号&#xff0c;然后…

使用腾讯云轻量应用服务器基于SRS搭建个人直播间

使用腾讯云轻量应用服务器基于SRS音视频服务器应用模板镜像即可一键搭建个人直播间&#xff0c;SRS Stack让你一键拥有自己的视频云解决方案&#xff0c;可以在云上或私有化部署&#xff0c;支持丰富的音视频协议&#xff0c;提供鉴权、私人直播间、多平台转播、录制、虚拟直播…

js中变量的使用

文章目录 一、变量二、声明三、赋值四、更新变量五、声明多个变量(不推荐)六、变量的本质七、关键字八、变量名命名规则 一、变量 理解变量是计算机存储数据的“容器”&#xff0c;掌握变量的声明方式 白话&#xff1a;变量就是一个装东西的盒子。通俗&#xff1a;变量是计算机…

【MySQL学习笔记007】约束

1、概述 &#xff08;1&#xff09;概念&#xff1a;约束是作用于表中字段上的规则&#xff0c;用于限制存储在表中的数据。 &#xff08;2&#xff09;目的&#xff1a;保证数据库中数据的正确、有效性和完整性。 &#xff08;3&#xff09;分类 约束 描述 关键字 …

ZStack Cube超融合一体机助力电子支付企业升级改造

电子支付服务企业实壹信息通过ZStack Cube超融合一体机为业务生产环境构建新一代云基础设施&#xff0c;结合V2V迁移模块实现ZStack社区版云平台应用迁移到全新的云基础设施ZStack Cube 超融合一体机上&#xff0c;同时共享分布式存储和外接FC-SAN存储。此外&#xff0c;运维人…

Android 8.1 设置USB传输文件模式(MTP)

项目需求&#xff0c;需要在电脑端adb发送通知手机端接收指令&#xff0c;将USB的仅充电模式更改成传输文件&#xff08;MTP&#xff09;模式&#xff0c;便捷用户在我的电脑里操作内存文件&#xff0c;下面是我们的常见的修改方式 1、android12以下、android21以上是这种方式…

Elasticsearch:在不停机的情况下优化 Elasticsearch Reindex

实现零停机、高效率和成功迁移更新的指南。更多阅读&#xff1a;Elasticsearch&#xff1a;如何轻松安全地对实时 Elasticsearch 索引 reindex 你的数据。 在使用 Elasticsearch 的时候&#xff0c;总会有需要修改索引映射的时候&#xff0c;遇到这种情况&#xff0c;我们只能做…

go语言,ent库与gorm库,插入一条null值的time数据

情景介绍 使用go语言&#xff0c;我需要保存xxxTime的字段至数据库中&#xff0c;这个字段可能为空&#xff0c;也可能是一段时间。我采取的是统一先赋值为空&#xff0c;若有需要&#xff0c;则再进行插入&#xff08;需要根据另一个字段判断是否插入&#xff09; 在我的数据…

PTS 3.0:可观测加持的下一代性能测试服务

作者&#xff1a;肖长军&#xff08;穹谷&#xff09; 大家好&#xff0c;我是来自阿里云云原生应用平台的肖长军&#xff0c;花名穹谷&#xff0c;我此次分享的主题是《可观测加持的下一代性能测试服务》。提到性能测试大家并不陌生&#xff0c;性能测试已成为评估系统能力、…

使用rsync构建镜像网站

实验环境 某公司在深圳、北京两地各放置了一台网站服务器&#xff0c;分别应对南北大区内不断增长的客户访问需求&#xff0c;两台服务器的网站文档必须保持一致&#xff0c;如图12.3所示&#xff0c;同步链路已通过VPN专用线路实现。 需求描述 > 服务器 A&#xff08;北京…

SpringBoot多线程与任务调度总结

一、前言 多线程与任务调度是java开发中必须掌握的技能&#xff0c;在springBoot的开发中&#xff0c;多线程和任务调度变得越来越简单。实现方式可以通过实现ApplicationRunner接口&#xff0c;重新run的方法实现多线程。任务调度则可以使用Scheduled注解 二、使用示例 Slf…

linux如何清理磁盘,使得数据难以恢复

sda 是硬盘&#xff0c;sda1 和 sda2 是硬盘的两个分区。centos-root 是一个逻辑卷&#xff0c;挂载在根目录 /。 /dev/sda 是硬盘&#xff0c;/dev/sda1 和 /dev/sda2 是硬盘的两个分区。 [rootnode2 ~]# dd if/dev/urandom of/dev/sda bs4M这个命令将从 /dev/urandom 读取随…

【软件工程大题】数据流图_DFD图_精简易上手

数据流图(DFD)是一种图形化技术,它描绘信息流和数据从输人移动到输出的过程中所经受的变换。 首先给出一个数据流图样例 基本的四种图形 直角矩形:代表源点或终点,一般来说,是人,如例图的仓库管理员和采购员圆形(也可以画成圆角矩形):是处理,一般来说,是动作,是动词名词的形式…

<JavaEE> TCP 的通信机制(二) -- 连接管理(三次握手和四次挥手)

目录 TCP的通信机制的核心特性 三、连接管理 1&#xff09;什么是连接管理&#xff1f; 2&#xff09;“三次握手”建立连接 1> 什么是“三次握手”&#xff1f; 2> “三次握手”的核心作用是什么&#xff1f; 3&#xff09;“四次挥手”断开连接 1> 什么是“…