斗地主老输?只能领低保?看我用Python写一个AI出牌器!一亿欢乐豆了!

斗地主老输?只能领低保?看我用Python写一个AI出牌器!一亿欢乐豆了!

 

前言

最近在网上看到一个有意思的开源项目,快手团队开发的开源AI斗地主——DouZero。今天我们就一起来学习制作一个基于DouZero的欢乐斗地主出牌器,看看AI是如何来帮助我们斗地主,赢欢乐豆,实现财富自由的吧!

首先一起来看看AI斗地主出牌器的效果:

下面,我们开始介绍这个AI出牌器的制作过程。

一、核心功能设计 首先我们这款出牌器是基于DouZero开发的,核心是需要利用训练好的AI模型来帮住我们,给出最优出牌方案。 其次关于出牌器,先要需要确认一个AI出牌角色,代表我们玩家自己。我们只要给这个AI输入玩家手牌和三张底牌。确认好地主和农民的各个角色,告诉它三个人对应的关系,这样就可以确定队友和对手。我们还要将每一轮其他两人的出牌输入,这样出牌器就可以根据出牌数据,及时提供给我们最优出牌决策,带领我们取得胜利!

那么如何获取三者之间的关系呢?谁是地主?谁是农民?是自己一人作战还是农民合作?自己玩家的手牌是什么?三张底牌是什么?这些也都需要在开局后确认好。 拆解需求,大致可以整理出核心功能如下: UI设计排版布局 显示三张底牌 显示AI角色出牌数据区域,上家出牌数据区域,下家出牌数据区域,本局胜率区域 AI玩家手牌区域 AI出牌器开始停止

手牌和出牌数据识别

游戏刚开始根据屏幕位置,截图识别AI玩家手牌及三张底牌

确认三者之间的关系,识别地主和农民角色,确认队友及对手关系

识别每轮三位玩家依次出了什么牌,刷新显示对应区域

AI出牌方案输出

加载训练好的AI模型,初始化游戏环境

每轮出牌判断,根据上家出牌数据给出最优出牌决策

自动刷新玩家剩余手牌和本局胜率预测

二、实现步骤

1. UI设计排版布局

根据上述功能,我们首先考虑进行简单的

UI布局设计

,这里我们使用的是

pyqt5

。核心设计代码如下:

def setupUi(self, Form): Form.setObjectName("Form") Form.resize(440, 395) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(9) font.setBold(True) font.setItalic(False) font.setWeight(75) Form.setFont(font) self.WinRate = QtWidgets.QLabel(Form) self.WinRate.setGeometry(QtCore.QRect(240, 180, 171, 61)) font = QtGui.QFont() font.setPointSize(14) self.WinRate.setFont(font) self.WinRate.setAlignment(QtCore.Qt.AlignCenter) self.WinRate.setObjectName("WinRate") self.InitCard = QtWidgets.QPushButton(Form) self.InitCard.setGeometry(QtCore.QRect(60, 330, 121, 41)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(14) font.setBold(True) font.setWeight(75) self.InitCard.setFont(font) self.InitCard.setStyleSheet("") self.InitCard.setObjectName("InitCard") self.UserHandCards = QtWidgets.QLabel(Form) self.UserHandCards.setGeometry(QtCore.QRect(10, 260, 421, 41)) font = QtGui.QFont() font.setPointSize(14) self.UserHandCards.setFont(font) self.UserHandCards.setAlignment(QtCore.Qt.AlignCenter) self.UserHandCards.setObjectName("UserHandCards") self.LPlayer = QtWidgets.QFrame(Form) self.LPlayer.setGeometry(QtCore.QRect(10, 80, 201, 61)) self.LPlayer.setFrameShape(QtWidgets.QFrame.StyledPanel) self.LPlayer.setFrameShadow(QtWidgets.QFrame.Raised) self.LPlayer.setObjectName("LPlayer") self.LPlayedCard = QtWidgets.QLabel(self.LPlayer) self.LPlayedCard.setGeometry(QtCore.QRect(0, 0, 201, 61)) font = QtGui.QFont() font.setPointSize(14) self.LPlayedCard.setFont(font) self.LPlayedCard.setAlignment(QtCore.Qt.AlignCenter) self.LPlayedCard.setObjectName("LPlayedCard") self.RPlayer = QtWidgets.QFrame(Form) self.RPlayer.setGeometry(QtCore.QRect(230, 80, 201, 61)) font = QtGui.QFont() font.setPointSize(16) self.RPlayer.setFont(font) self.RPlayer.setFrameShape(QtWidgets.QFrame.StyledPanel) self.RPlayer.setFrameShadow(QtWidgets.QFrame.Raised) self.RPlayer.setObjectName("RPlayer") self.RPlayedCard = QtWidgets.QLabel(self.RPlayer) self.RPlayedCard.setGeometry(QtCore.QRect(0, 0, 201, 61)) font = QtGui.QFont() font.setPointSize(14) self.RPlayedCard.setFont(font) self.RPlayedCard.setAlignment(QtCore.Qt.AlignCenter) self.RPlayedCard.setObjectName("RPlayedCard") self.Player = QtWidgets.QFrame(Form) self.Player.setGeometry(QtCore.QRect(40, 180, 171, 61)) self.Player.setFrameShape(QtWidgets.QFrame.StyledPanel) self.Player.setFrameShadow(QtWidgets.QFrame.Raised) self.Player.setObjectName("Player") self.PredictedCard = QtWidgets.QLabel(self.Player) self.PredictedCard.setGeometry(QtCore.QRect(0, 0, 171, 61)) font = QtGui.QFont() font.setPointSize(14) self.PredictedCard.setFont(font) self.PredictedCard.setAlignment(QtCore.Qt.AlignCenter) self.PredictedCard.setObjectName("PredictedCard") self.ThreeLandlordCards = QtWidgets.QLabel(Form) self.ThreeLandlordCards.setGeometry(QtCore.QRect(140, 10, 161, 41)) font = QtGui.QFont() font.setPointSize(16) self.ThreeLandlordCards.setFont(font) self.ThreeLandlordCards.setAlignment(QtCore.Qt.AlignCenter) self.ThreeLandlordCards.setObjectName("ThreeLandlordCards") self.Stop = QtWidgets.QPushButton(Form) self.Stop.setGeometry(QtCore.QRect(260, 330, 111, 41)) font = QtGui.QFont() font.setFamily("Arial") font.setPointSize(14) font.setBold(True) font.setWeight(75) self.Stop.setFont(font) self.Stop.setStyleSheet("") self.Stop.setObjectName("Stop") self.retranslateUi(Form) self.InitCard.clicked.connect(Form.init_cards) self.Stop.clicked.connect(Form.stop) QtCore.QMetaObject.connectSlotsByName(Form) def retranslateUi(self, Form): _translate = QtCore.QCoreApplication.translate Form.setWindowTitle(_translate("Form", "AI欢乐斗地主--Dragon少年")) self.WinRate.setText(_translate("Form", "胜率:--%")) self.InitCard.setText(_translate("Form", "开始")) self.UserHandCards.setText(_translate("Form", "手牌")) self.LPlayedCard.setText(_translate("Form", "上家出牌区域")) self.RPlayedCard.setText(_translate("Form", "下家出牌区域")) self.PredictedCard.setText(_translate("Form", "AI出牌区域")) self.ThreeLandlordCards.setText(_translate("Form", "三张底牌")) self.Stop.setText(_translate("Form", "停止"))

实现效果如下:

​​

2. 手牌和出牌数据识别

下面我们需要

所有扑克牌的模板图片与游戏屏幕特定区域的截图进行对比

,这样才能获取AI玩家手牌、底牌、每一轮出牌、三者关系(地主、地主上家、地主下家)。

识别AI玩家手牌及三张底牌:

我们可以截取游戏屏幕,根据固定位置来识别当前AI玩家的手牌和三张底牌。核心代码如下:

# 牌检测结果滤波 def cards_filter(self, location, distance): if len(location) == 0: return 0 locList = [location[0][0]] count = 1 for e in location: flag = 1 # “是新的”标志 for have in locList: if abs(e[0] - have) =5.2.0 opencv-python rlcard

2. 坐标调整确认

我们可以打开欢乐斗地主游戏界面,将游戏窗口模式下最大化运行,把AI出牌器程序窗口需要移至右下角,不能遮挡手牌、地主标志、底牌、历史出牌这些关键位置。

其次我们要确认屏幕截图获取的各个区域是否正确。如果有问题需要进行区域位置坐标调整。

# 坐标 self.MyHandCardsPos = (414, 804, 1041, 59) # 我的截图区域 self.LPlayedCardsPos = (530, 470, 380, 160) # 左边截图区域 self.RPlayedCardsPos = (1010, 470, 380, 160) # 右边截图区域 self.LandlordFlagPos = [(1320, 300, 110, 140), (320, 720, 110, 140), (500, 300, 110, 140)] # 地主标志截图区域(右-我-左) self.ThreeLandlordCardsPos = (817, 36, 287, 136) # 地主底牌截图区域,resize成349x168

如果还是有小伙伴通过文章感觉没学会的!需要完整视频教程或者源码的可以点击蓝色字体:点击这里 领取 或者加Q羣:754370353 自取即可,对于这快有疑问的,有不会的小伙伴可以直接进去提问哈!小编看到会第一时间回复大家!

3. 运行测试 当所有环境配置完成,各区域坐标位置确认无误之后,下面我们就可以直接运行程序,测试效果啦~ 首先我们运行AI出牌器程序,打开欢乐斗地主游戏界面,进入游戏。当玩家就位,手牌分发完毕,地主身份确认之后,我们就可以点击画面中开始按钮,让AI来帮助我们斗地主了。 下面可以一起来看看这款AI出牌器的实验效果喔,看看AI是如何带领农民打倒地主,取得胜利的!此文转载文。著作权归作者所有,如有侵权联系小编删除!

今天我们就到这里,明天继续努力!

若本篇内容对您有所帮助,请三连点赞,关注,收藏支持下。


比丘资源网 » 斗地主老输?只能领低保?看我用Python写一个AI出牌器!一亿欢乐豆了!

发表回复

提供最优质的资源集合

立即查看 了解详情