首页 > 编程语言 >[python+opencv]从0开始的ChineseChessOL项目

[python+opencv]从0开始的ChineseChessOL项目

时间:2023-07-30 11:55:06浏览次数:42  
标签:鼠标 python opencv 棋子 ChineseChessOL 坐标 服务器

背景

暑假某日,家父突然提出想我做一个象棋的程序。由于在上个学期,我学过一点java的网络编程,也搭建了一台自己的服务器(腾讯云,后面考),同时考虑到下象棋没有什么复杂的算法,于是欣然答应。

项目地址

纯代码在github,完整客户端(包含所需要的图片和一个python安装包)在个人网页

目前的版本仍无法发行,有一些细节需要处理,同时需要使用者自行安装python+numpy+opencv的环境,但已经实现了相关的功能。

经验分享

第一步:选择编程语言和GUI工具。

C++和java的网络编程我猜不会比python更简单,rust没有考虑过网络编程,所以选择了python。图形化界面本来想选用PySimpleGUI,但是发现不太方便获取鼠标点击的坐标,我没想出合适的方法控制圆形的棋子,最后还是选择了opencv。

第二步:初始棋盘棋子界面显示。

由于opencv使用imread得到的其实是<class 'numpy.ndarray'>,所以可以采用如下的方式在一个棋盘的左上角显示一个棋子

import cv2
img = cv2.imread("pad.jpg") # pad.jpg为棋盘资源。
h,w,b = img.shape
print(h,w)#实际上是ndarray的index range,也是图片的分辨率
pieces = cv2.imread("pieces.png") # 实际项目中没有这个文件,这是举个例子
h2,w2,b2 = pieces.shape
img[0:h2,0:w2] = pieces
cv2.imshow("img",img)
cv2.waitkey(0)# 后面考

如法炮制,显示所有棋子即可(具体的像素坐标要找一下,可以用画图,也可以见第三步

tip:这里有个小问题,就是我在网上下载的素材,棋子虽然是png格式,周围也确实是透明的,但是opencv如果直接用imread读取图片,得到的数据只有3通道,没有透明度通道,导致棋子显示时周围会有白边,也意味着我以后显示所有图片都是矩形。通过添加参数可以读到透明度,但我尝试了把棋盘转成png格式后没办法读出4通道,导致无法将棋子叠加到棋盘上,最后只能退而求其次保留白色边框。

第三步:鼠标反馈

opencv中有一个setMouseCallback函数,不知道为什么pycharm显示没找到reference,但是可以正常使用的。它有两个参数,第一个参数是窗口的名称,即想要在哪个窗口获得反馈,第二个参数是反馈的方式,参数类型是函数指针(函数名)

这个第二个参数所需的函数大概长这样,并且这样就可以得到鼠标左击的坐标

def on(event, x, y, flags, param):
      if event == cv2.EVENT_LBUTTONDOWN:
            print(x,y)

有了鼠标的像素坐标,也有了棋子的像素坐标(如果你能正常显示棋子,那你一定有办法知道它所在的像素坐标),下面你应该知道该干什么了吧

第四步:选中效果

在一个象棋程序里,点击一个棋子的选中效果大概有2,一是棋子要有标识,二是提示棋子可以往哪走。

一:根据第二步的tip,我选择通过画图把每个棋子的透明白边染成绿色作为选中效果,一旦哪个棋子被选中,则使用选中的图片覆盖先前的图片

二:最难,最容易出bug也是最核心的地方。对于每一种棋子,需要有不同的提示方式,象棋的规则也在这里体现出来。

tip:要考虑选中一个棋子后再选另一个棋子的时候如何复原。我采用的方式是每次选取前都重新加载棋盘。虽然浪费资源,但对象棋来说也足够了。

第五步:棋子移动

既然第四步已经在选中棋子后已经在棋盘上显示了往哪走的提示,那么相信你也有办法获得这些提示的像素坐标。则你可以判断是否点击了提示的坐标。则可以判断棋子是否移动。移动则改变初始坐标即可。

第六步:细节完善

至此,你已经可以做出一方棋子无限下棋的样子了。以下是一些规则方面的细节,不做赘述。

  1. 吃子
  2. 胜利条件

如果你在程序开始加上随机数使得你可以随机执黑棋或者红棋,那么你可以同时把另一方下棋的样子也实现了。

更多的细节,在开始网络编程之后才会出现。

第七步:服务端,客户端通信

本来以为按照教程创建socket就行了,但是实际操作之后才发现有2个问题。

一是腾讯云服务器bind绑定公网IP失败

二是客户端在连接服务端时无法访问端口

问题一与云服务器的部署有关。具体参见NAT协议。简单的说解决方法就是客户端绑定公网IP,服务端绑定私网IP,然后套接字才能连接

问题二与云服务器的防火墙有关。以下是我的入门级服务器默认打开的端口。

fig1

可以看到默认打开的只有web服务,ssh服务,windows远程桌面(还没尝试过,懒得用了~咕)和ping服务

所以需要手动打开你想要使用的那个端口。(这边顺便吐槽以下,腾讯云服务器不允许用户拿自己的服务器当邮箱。除非连接第三方平台,否则邮件的端口是禁止打开的。所以不要想用自己帅气的域名给自己搞个帅气的邮箱了。其实也很合理,毕竟假如服务器用一年就不用了,到时候这个邮箱就找不到人或者只能找到它的下一个主人了)

anyway,然后就可以通信了

第八步:轮流对弈

我一开始的想法就是,后下的人等待服务器的消息,等到了之后再下棋。发送的消息只要同步了坐标,一切都可以正常运行。(没有把运算工作放到服务端。服务器只起一个连接的发送消息的作用)

但是发现这样opencv显示的图片无响应

在查询了资料后发现,显示图片之后主程序必须停留在waitkey上给图片显示的时间,否则就无响应。setMouseCallback参数里的函数有点类似于在另一个线程中运行,也是现在唯一能运行代码的地方。但是这个函数在鼠标在图像上移动的时候就会执行一遍,导致如果在这个函数里接收服务器端的消息非常不现实。看似我们这里已经走到死局了,这个项目并不像我们想的那么好实现。

但是柳暗花明又一村。我们可以加入多线程。单独开一个线程来接收信息并控制鼠标反馈。

为了防止两方一起下棋。我本来想找setMouseCallback的退出方式,发现没有,但可以改变它调用的函数。于是我在一方下过棋之后改成do_nothing(见代码),do_nothing根据监听的线程的消息把函数再调回去。这样这个项目就算完成了。

总结

1:学到了不少东西,动手做的东西很多。主要是第一次网络编程和从0开始学习了python-opencv。

2:目前还有一些不足,如对于结尾没有处理好,草草收尾了,以及等待的一方没有例如对方思考中这类提示,必须鼠标移动之后才能看到棋子的变化。同时没有加背景音乐,数据存储等待功能。

标签:鼠标,python,opencv,棋子,ChineseChessOL,坐标,服务器
From: https://www.cnblogs.com/Q-M-double-j/p/17591221.html

相关文章

  • python数据分析师入门-学习笔记(第二节)
    爬虫(数据采集)序言1.爬虫到底是什么2.爬虫的应用场景3.爬虫的分类4.爬虫合法吗5.爬虫如何搞钱初级1.开始爬虫的准备工作2.爬虫的核心流程3.数据获取4.数据提取5.数据存储6.应对反爬虫中级1.提升性能2.令牌池(cookie......
  • 玩转Python属性和方法,成为高手不再难!
    导言Python是一种简洁而强大的编程语言,其支持面向对象的编程范式。在Python中,属性和方法是面向对象编程的核心概念之一。本文将从入门到精通介绍Python中的属性和方法,帮助你深入了解这些重要的概念,并学会如何在实际开发中灵活应用它们。1.属性是什么?属性是对象的特性或数据,可......
  • # yyds干货盘点 # 使用Python统计下桌面某个文件夹下(含多层子文件夹)具体文件的数量(方
    大家好,我是皮皮。一、前言前几天在Python最强王者群【东哥】问了一个Python自动化办公的问题,一起来看看吧。这个是他自己在实际工作中遇到的需求,正好遇到了这个问题,想着用Python来实现下。二、实现过程上一篇文章中已经分享了一个方法,这一篇文章继续分享另外一个方法,由【巭孬嫑勥烎......
  • python数据分析师入门-学习笔记
    第一节数据分析整体介绍应用领域数据分析爬虫开发数据存储数据可视化数据分析内容1.语言基础python基础2.数据获取爬虫课程3.数据存储MySQL数据库4.数据处理NumpyPandas5.数据可视化Matplot......
  • python单例模式实现
    classSingleton(object):​  def__new__(cls,*args,**kwargs):    ifnothasattr(cls,'_instance'):      cls._instance=super(Singleton,cls).__new__(cls)    returncls._instance 注:__new__方法用于生成类实例,__new__应返回一个......
  • C++程序获取python脚本控制台输出的一种方法
    作者:朱金灿为什么大多数人学不会人工智能编程?>>>  最近要使用C++程序调用python脚本,调用方法是通过启动python进程来调用,其中遇到的一个问题是在C++程序中需要获取python脚本的控制台输出信息。经过摸索使用_popen函数实现了。下面用python脚本和C++调用示例程序来说明。py......
  • 【Python】使用 pyecharts 模块绘制动态时间线柱状图 ① ( 列表排序 | 使用 sorted 函
    文章目录一、列表排序1、使用sorted函数对容器进行排序2、使用list.sort函数对列表进行排序3、使用list.sort函数对列表进行排序-设置排序函数4、使用list.sort函数对列表进行排序-设置lambda匿名排序函数pyecharts画廊网站:https://gallery.pyecharts.org/#/......
  • 使用Python统计下桌面某个文件夹下(含多层子文件夹)具体文件的数量(方法三)
    大家好,我是皮皮。一、前言前几天在Python最强王者群【东哥】问了一个Python自动化办公的问题,一起来看看吧。这个是他自己在实际工作中遇到的需求,正好遇到了这个问题,想着用Python来实现下。二、实现过程上一篇文章中已经分享了一个方法,这一篇文章继续分享另外一个方法,由【巭孬......
  • 使用python基于boto3和tkintrer模块-编写一个AWS-EC2的管理器界面
    当我们管理自己AWS账号下的EC2资源时,一般都是登录到Console界面进行管理笔者自己的AWS经常是用于做一些实验时,才会去创建EC2,部署一些环境等,为了不用登录Console操作于是使用python,tkinter模块写了一个GUI的管理工具,先看一下整体界面如下:这个小工具,有创建EC2,查询EC2,删除指......
  • 使用 OpenCV 进行图像模糊度检测(拉普拉斯方差方法)
    写在前面工作中遇到,简单整理人脸识别中,对于模糊程度较高的图像数据,识别率低,错误率高。虽然使用AdaFace模型,对低质量人脸表现尤为突出。但是还是需要对模糊程度高的图像进行丢弃处理当前通过阈值分类,符合要求的进行特性提取实际应用中,可以维护一个质量分数比如由模糊程度,图片字......