简介

程序基于Python3.7开发的斗地主AI出牌助手,目前支持欢乐斗地主桌面版,微信版,也可以自己制作相应其他版本。

此出牌助手核心是识别出三位玩家出牌内容,调用基于DouZero封装的API接口,输入出牌内容,根据AI出牌方案,打出相应的牌。

运行效果

![](https://img2023.cnblogs.com/blog/129408/202311/129408-20231114235431212-40412513.gif)

核心功能

  • 手牌和位置识别

    1. 游戏刚开始根据屏幕位置,截图识别AI玩家手牌及三张底牌
    2. 根据玩家手牌判断是否抢地主和加倍
    3. 确认三者之间的关系,识别地主和农民角色,确认队友及对手关系
  • 识别每轮三位玩家出牌
    1. 根据提示按钮,判断当前的操作
    2. 识别三位玩家此轮出的牌,并记录下来
  • AI出牌方案输出
    1. 将出牌记录按格式要求发送给斗地主AI
    2. 获取斗地主AI出牌方案,选取最高胜率方案
    3. 根据AI出牌方案,选择对相应的牌,并出牌

素材准备

  • 区域定位,获取坐标值

  • 按钮及牌面

核心代码

  • 根据指定窗口句柄截图

    def WindowShot(self):
    """
    根据窗口句柄截图
    返回: 图片对象
    """
    windll.user32.SetProcessDPIAware()
    hwnd = self.Handle
    left, top, right, bottom = win32gui.GetClientRect(hwnd)
    w = right - left
    h = bottom - top
    hwnd_dc = win32gui.GetWindowDC(hwnd)
    mfc_dc = win32ui.CreateDCFromHandle(hwnd_dc)
    save_dc = mfc_dc.CreateCompatibleDC()
    bitmap = win32ui.CreateBitmap()
    bitmap.CreateCompatibleBitmap(mfc_dc, w, h)
    save_dc.SelectObject(bitmap)
    # If Special K is running, this number is 3. If not, 1
    result = windll.user32.PrintWindow(hwnd, save_dc.GetSafeHdc(), 3)
    bmpinfo = bitmap.GetInfo()
    bmpstr = bitmap.GetBitmapBits(True)
    img = np.frombuffer(bmpstr, dtype=np.uint8).reshape((bmpinfo["bmHeight"], bmpinfo["bmWidth"], 4))
    img = np.ascontiguousarray(img)[..., :-1] # make image C_CONTIGUOUS and drop alpha channel
    #img = Image.frombuffer("RGB",(bmpinfo['bmWidth'], bmpinfo['bmHeight']),bmpstr, 'raw', 'BGRX', 0, 1)
    if not result: # result should be 1
    win32gui.DeleteObject(bitmap.GetHandle())
    save_dc.DeleteDC()
    mfc_dc.DeleteDC()
    win32gui.ReleaseDC(hwnd, hwnd_dc)
    raise RuntimeError(f"Unable to acquire screenshot! Result: {result}")
    #cv2.imwrite('./imgs/print.png', img)
    #return img
    return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)
  • 在图片中查找第一个相似的图片

    def LocateOnImage(self, template, image=None, region=None, confidence=0.9, grayscale=True):
    """
    在image中寻找template,返回第一个查找到的范围 参数:
    template: 需要查找的图片,文件名或图片对象
    image: 被查找的图片,文件名或图片对象
    region: 查找范围
    confidence: 置信度
    grayscale: 是否为灰度图 返回值:
    查找到的图片范围
    """
    if image is None:
    image = self.WindowShot()
    return pyautogui.locate(template, image, region=region, confidence=confidence, grayscale=grayscale)
  • 在图片中查找所有相似的图片

    def LocateAllOnImage(self, template, image=None, region=None, confidence=0.9, grayscale=True):
    """
    在image中寻找template,返回第一个查找到的范围 参数:
    template: 需要查找的图片,文件名或图片对象
    image: 被查找的图片,文件名或图片对象
    region: 查找范围
    confidence: 置信度
    grayscale: 是否为灰度图 返回值:
    查找到的图片范围
    """
    if image is None:
    image = self.WindowShot()
    return pyautogui.locateAll(template, image, region=region, confidence=confidence, grayscale=grayscale)
  • 识别手牌

    def GetCards(self, image, player):
    hand_cards = []
    cards = ""
    start_x = 0
    width = player["width"]
    for card in self.AllCardsNC:
    confidence = player["confidence"] or 0.85
    grayscale = True
    if(card in ('D', 'X')):
    confidence = 0.85
    grayscale = False card_key = player["prefix"] + card
    matches = self.LocateAllOnImageName(card_key, image, player["region"], confidence, grayscale) if len(matches) > 0:
    sorted_matches = sorted(matches, key=lambda match: match[0])
    #print(target_position)
    #print(mark) if(card != 'X'):
    start_x = 0 for match in sorted_matches:
    if(start_x == 0 or start_x + player["width"] < match[0]):
    #大小王容易判断错误,需要再判断一下颜色值
    if(card == 'D'):
    #match = sorted_matches[0]
    y,x,h,w = match
    cropped_image = image[x:x+w, y:y+h]
    #colors = cv2.mean(cropped_image)
    mean, stddev = cv2.meanStdDev(cropped_image)
    #print("均值:", mean)
    #print("差值:", stddev)
    if(stddev[2][0] > 30):
    continue
    start_x = match[0]
    width = match[2]
    hand_cards.append({card:match})
    cards += card return cards, hand_cards
  • 将出牌记录发送给AI,进行预测

    def GetCardsForPredict(self):
    #将出牌记录发送给AI,进行预测
    resultStr = self.PostPredict()
    #获取最高胜率的出牌
    last_move_cards = self.GetPredictWinRates(resultStr)
    return last_move_cards
  • 出牌

    def PlayedCards(self, cards, image=None):
    if image is not None:
    window_shot_image = image
    else:
    window_shot_image = self.WindowShot()
    player_self_cards, range = self.GetCards(window_shot_image, self.Players["PlayerSelf"])
    select_index = []
    select_cards = []
    #将cards中的字符顺序反转
    play_cards = cards[::-1]
    cards = play_cards for c in cards:
    index = -1
    for card in player_self_cards:
    index += 1 if c == card and index not in select_index:
    select_index.append(index)
    select_cards.append(c)
    #print(range[index])
    cards = cards.replace(c, '', 1)
    card_range = range[index][c]
    break cards = play_cards
    index = -1
    #window_shot_image = self.WindowShot()
    for n in select_index:
    window_shot_image = self.WindowShot()
    player_self_cards, range = self.GetCards(window_shot_image, self.Players["PlayerSelf"])
    if(len(player_self_cards) > n):
    #player_self_cards = player_self_cards
    index += 1
    card_range = range[n][cards[index]]
    #如果要出的牌还未选择完毕,则点击
    if(card_range[1] > self.CardTop):
    self.LeftClick(card_range) time.sleep(0.2) return self.GetSelectCards(play_cards)
  • DouZero 的请求结构体

    Predict = {
    "bomb_num":0,#炸弹数量
    "card_play_action_seq":'',#历史出牌动作序列,用逗号分隔
    "last_move_landlord":'',#地主最后出的牌
    "last_move_landlord_down":'',#地主下家最后出的牌
    "last_move_landlord_up":'',#地主上家最后出的牌
    "num_cards_left_landlord":20,#地主手牌剩余数量
    "num_cards_left_landlord_down":17,#地主下家手牌剩余数量
    "num_cards_left_landlord_up":17,#地主上家手牌剩余数量
    "other_hand_cards":'',#还剩余的牌
    "played_cards_landlord":'',#地主所有出的牌
    "played_cards_landlord_down":'',#地主下家所有出的牌
    "played_cards_landlord_up":'',#地主上家所有出的牌
    "player_hand_cards":'',#玩家手中的牌
    "player_position":0, #-当前玩家的位置序号 0 地主,1 地主下家,2 地主上家
    "three_landlord_cards":''#三张底牌
    }

可用的 DouZero 后端地址

免责声明

本程序仅供娱乐和学习使用,不得用于任何非法用途

参考项目

斗地主AI出牌助手--在线调用斗地主AI,实现自动斗地主的更多相关文章

  1. Unity3D手机斗地主游戏开发实战(04)_出牌判断大小(已完结)

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  2. Unity3D手机斗地主游戏开发实战(04)_出牌判断大小

    之前我们实现了叫地主.玩家和电脑自动出牌主要功能,但是还有个问题,出牌的时候,没有有效性检查和比较牌力大小.比如说,出牌3,4,5,目前是可以出牌的,然后下家可以出任何牌如3,6,9. 问题1:出牌检 ...

  3. Unity3D手机斗地主游戏开发实战(03)_地主牌显示和出牌逻辑(不定期更新中~~~)

    Hi,之前有同学说要我把源码发出来,那我就把半成品源码的链接放在每篇文件的最后,有兴趣的话可以查阅参考,有问题可以跟我私信,也可以关注我的个人公众号,互相交流嘛.当然,代码也是在不断的持续改进中~ 上 ...

  4. Android斗地主棋牌游戏牌桌实现源码下载

    本次给大家分享下Android斗地主棋牌游戏牌桌实现源码下载如下: 为了节约内存资源,每张扑克牌都是剪切形成的,当然这也是当前编程的主流方法. 1.主Activity package com.biso ...

  5. Java学习笔记34(集合框架八:综合案例:模拟斗地主的洗牌发牌)

    规则: 1.54张扑克牌,有花色 2.顺序打乱,一人一张依次发牌,一人17张,留三张作为底牌 3.看牌:按大小王2A....43的序排列打印 示例: package demo; import java ...

  6. 使用javascript随机生成斗地主玩家手牌

    学习javascript估摸着有半个多月了,好歹自己有过编程基础,学的还算轻松,不过js里的面向对象是真的打脑壳,但都但不懂,和我以前学过的c#简直相差太远 今天写了个随机生成斗地主玩家手牌的代码,自 ...

  7. java 模拟斗地主发牌洗牌

    一 模拟斗地主洗牌发牌 1.案例需求 按照斗地主的规则,完成洗牌发牌的动作. 具体规则: 1. 组装54张扑克牌 2. 将54张牌顺序打乱 3. 三个玩家参与游戏,三人交替摸牌,每人17张牌,最后三张 ...

  8. 百度AI开放平台- API实战调用

    百度AI开放平台- API实战调用 一.      前言 首先说一下项目需求. 两个用户,分别上传了两段不同的文字,要计算两段文字相似度有多少,匹配数据库中的符合条件的数据,初步估计列出来会有60-1 ...

  9. AI智能问答助手 AI智能批量文章生成器 网站优化SEO批量内容生成工具 原创文章生成软件

    <AI智能问答助手>   软件基于当下热门的OpenAI的ChatGPT技术,导入问题列表就可以批量生成对应的内容,内容质量高.原创度高.适合对内容生成需求量大的场景,如网站优化.广告文案 ...

  10. 百度大脑发布“AI开发者‘战疫’守护计划”,AI支援抗疫再升级

    面对新冠肺炎疫情,AI开发者们正在积极运用算法.算力.软件等“武器”助力抗疫.针对开发者们在疫情防控期间的开发与学习需求,2月6日,百度大脑推出“AI开发者‘战疫’守护计划”, 正在进行疫情防控相关应 ...

随机推荐

  1. 2022-1-11 控件学习3 文本渲染、TabIndex、Border、Slider、ProgressBar、

    WPF文本渲染  TextOptions.TextFormattingMode:默认值Ideal大部分是好用的,但是非常小的文本使用Display渲染会好一些 TextRenderMode:使用抗锯齿 ...

  2. git: 解决每次操作git时都要输入账户、密码

    解决方案 $ git config --global credential.helper store 使用该命令即可解决问题

  3. 青少年CTF平台-Web-PingME

    题目描述 题目难度一颗星,五十分. 解题记录 进入题目中,发现这是一个ping功能 我们用连字符||进行分割两个语句,保证同时运行且输出. Payload为127.0.0.1 || ls 发现有fla ...

  4. 在本地运行Kusto服务器

    我喜欢Kusto (或商用版本 Azure Data Explorer,简称 ADX) 是大家可以有目共睹的,之前还专门写过这方面的书籍,请参考 大数据分析新玩法之Kusto宝典, 很可能在今年还会推 ...

  5. PDF 补丁丁 1.0 正式版

    经过了一年多的测试和完善,PDF 补丁丁发布第一个开放源代码的正式版本了. PDF 补丁丁也是国内首先开放源代码.带有修改和阅读PDF的功能的 PDF 处理程序之一. 源代码网址:https://gi ...

  6. iOS日志获取

    IOS日志获取 崩溃日志存放目录: /var/mobile/Library/Logs/CrashReporter

  7. sublime运行php文件

    sublime 运行 php 文件 使用 sublime 打开一个php文件 然后 Tools -> Build System -> New Build System 将以上打开的文件内容 ...

  8. 【接口自动化测试】Eolink Apilkit 安装部署,支持 Windows、Mac、Linux 等系统

    Eolink Apikit 有三种客户端,可以依据自己的情况选择.三种客户端的数据是共用的,因此可以随时切换不同的客户端. 我们推荐使用新推出的 Apikit PC 客户端,PC 端拥有线上产品所有的 ...

  9. Vue 核心技术

    1.1 Vue简介 1.1.1 官网 英文官网 中文官网 1.1.2 介绍与描述 动态构建用户界面的 渐进式 JavaScript 框架 作者:尤雨溪 1.1.3 Vue的特点 遵循 MVVM 模式 ...

  10. 使用GPU训练Pytorch模型

    如何使用GPU训练Pytorch模型 这两天的深度学习实验真实让人头疼,传说中的"猫狗大战",对模型的训练用CPU的话9h起步,12h是常态,大学生哪耗得起,因此查找资料搭建了GP ...