You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python特定屏幕区域卡牌识别与扑克胜率计算器开发问询

自动扑克胜率计算器解决方案

问题背景

我是Python新手,想开发一个自动扑克胜率计算器,能自动识别卡牌并计算获胜概率。目前代码仅能检测红桃K或红桃A,且是全屏幕检测,无法限定区域。需求如下:

  • 检测两张手牌存入变量,计算胜率
  • 检测桌面前三张公共牌(替换现有固定值)并计算胜率
  • 依次检测第四、第五张公共牌并计算胜率
  • 等待新牌后重复流程

现有代码:

import pied_poker as pp
import numpy as np
import pyautogui
import time
np.random.seed(420)
def find_item_on_screen(card_image, card_one, card_two, card_type) -> bool:
    try:
        pyautogui.locateOnScreen(card_image, confidence=0.9)
        print(f"{card_type}!")
        p1 = pp.Player('Artur', pp.Card.of(card_one, card_two))
        p2 = pp.Player('Opponent', pp.Card.of()) 
        community_cards = pp.Card.of("2h", "qh", "4h", "10c", "6c")
        print(p1)
        print(f'Community cards: {community_cards}')
        simulator = pp.PokerRound.PokerRoundSimulator(community_cards=community_cards, players=[p1, p2], total_players=2)
        num_simulations = 10000
        simulation_result=simulator.simulate(n=num_simulations, n_jobs=1)
        print(simulation_result.probability_of(pp.Probability.PlayerWins(p1)))
        return True
    except pyautogui.ImageNotFoundException:
        print(f"No {card_type}")
        return False

def check_king():
    locate_item = 'KH.png'
    card_one = "kh"
    card_two = "kd"
    card_type = 'KING'
    find_item_on_screen(locate_item, card_one, card_two, card_type)    

def check_aces(): 
    locate_item = 'AH.png'
    card_one = "ah"
    card_two = "ad"
    card_type = 'ACES'
    find_item_on_screen(locate_item, card_one, card_two, card_type)

check_king() 
check_aces()

核心修改方案

1. 限定检测区域

使用pyautogui.locateOnScreen的region参数,传入(x坐标, y坐标, 宽度, 高度)即可锁定检测范围。可以先运行pyautogui.displayMousePosition()获取游戏界面中手牌区、公共牌区的准确坐标。

2. 批量识别所有卡牌

放弃单独编写单卡牌检测函数,改用映射表批量处理所有卡牌,自动收集检测到的手牌和公共牌。

3. 分阶段处理公共牌

根据公共牌数量(3张=翻牌、4张=转牌、5张=河牌)分阶段计算胜率,符合扑克流程。

4. 循环等待新局

用无限循环+延时实现持续检测,适配游戏的新局节奏。


修改后的完整代码

import pied_poker as pp
import pyautogui
import time

# 卡牌图片与牌面代码映射,需补充完整所有卡牌
CARD_MAPPING = {
    'AH.png': 'ah', 'AD.png': 'ad', 'AC.png': 'ac', 'AS.png': 'as',
    'KH.png': 'kh', 'KD.png': 'kd', 'KC.png': 'kc', 'KS.png': 'ks',
    'QH.png': 'qh', 'QD.png': 'qd', 'QC.png': 'qc', 'QS.png': 'qs',
    'JH.png': 'jh', 'JD.png': 'jd', 'JC.png': 'jc', 'JS.png': 'js',
    '10H.png': '10h', '10D.png': '10d', '10C.png': '10c', '10S.png': '10s',
    '9H.png': '9h', '9D.png': '9d', '9C.png': '9c', '9S.png': '9s',
    '8H.png': '8h', '8D.png': '8d', '8C.png': '8c', '8S.png': '8s',
    '7H.png': '7h', '7D.png': '7d', '7C.png': '7c', '7S.png': '7s',
    '6H.png': '6h', '6D.png': '6d', '6C.png': '6c', '6S.png': '6s',
    '5H.png': '5h', '5D.png': '5d', '5C.png': '5c', '5S.png': '5s',
    '4H.png': '4h', '4D.png': '4d', '4C.png': '4c', '4S.png': '4s',
    '3H.png': '3h', '3D.png': '3d', '3C.png': '3c', '3S.png': '3s',
    '2H.png': '2h', '2D.png': '2d', '2C.png': '2c', '2S.png': '2s'
}

# 需根据你的游戏界面调整坐标,用pyautogui.displayMousePosition()获取
HAND_REGION = (150, 600, 220, 110)  # 手牌区域:x, y, 宽, 高
COMMUNITY_REGION = (320, 700, 550, 110)  # 公共牌区域

def detect_cards_in_region(target_region, card_map):
    """在指定区域内检测所有卡牌,返回去重后的牌面代码列表"""
    detected = []
    for img_path, card_code in card_map.items():
        try:
            # 在限定区域内查找卡牌
            pos = pyautogui.locateOnScreen(img_path, region=target_region, confidence=0.9)
            if pos:
                detected.append(card_code)
                time.sleep(0.1)  # 避免重复识别同一卡牌
        except pyautogui.ImageNotFoundException:
            continue
    return list(set(detected))

def calculate_win_probability(player_cards, community_cards):
    """根据手牌和公共牌计算获胜概率"""
    if len(player_cards) < 2:
        print("未检测到足够手牌,跳过计算")
        return
    
    # 初始化玩家和对手
    player = pp.Player('Artur', pp.Card.of(*player_cards))
    opponent = pp.Player('Opponent', pp.Card.of())  # 对手手牌未知
    
    # 转换公共牌格式
    community = pp.Card.of(*community_cards) if community_cards else []
    
    # 模拟计算胜率
    simulator = pp.PokerRound.PokerRoundSimulator(
        community_cards=community,
        players=[player, opponent],
        total_players=2
    )
    result = simulator.simulate(n=10000, n_jobs=1)
    win_rate = result.probability_of(pp.Probability.PlayerWins(player))
    
    # 输出结果
    print(f"\n当前手牌: {player_cards}")
    print(f"当前公共牌: {community_cards}")
    print(f"获胜概率: {win_rate:.2%}")

def main():
    while True:
        # 检测手牌
        player_cards = detect_cards_in_region(HAND_REGION, CARD_MAPPING)
        
        # 检测公共牌
        community_cards = detect_cards_in_region(COMMUNITY_REGION, CARD_MAPPING)
        
        # 分阶段计算胜率
        if len(community_cards) >= 3:
            print("=== 翻牌阶段 ===")
            calculate_win_probability(player_cards, community_cards[:3])
        if len(community_cards) >= 4:
            print("=== 转牌阶段 ===")
            calculate_win_probability(player_cards, community_cards[:4])
        if len(community_cards) == 5:
            print("=== 河牌阶段 ===")
            calculate_win_probability(player_cards, community_cards)
        
        # 等待新牌,可根据游戏节奏调整延时
        time.sleep(2)

if __name__ == "__main__":
    # 先取消注释下方代码,运行后获取界面坐标
    # pyautogui.displayMousePosition()
    main()

注意事项

  • 必须补充完整CARD_MAPPING中的所有卡牌图片路径与对应代码,确保图片文件名和实际文件一致;
  • 运行pyautogui.displayMousePosition()后,移动鼠标到区域的左上角和右下角,计算出区域的x, y, 宽, 高,替换HAND_REGION和COMMUNITY_REGION;
  • 调整confidence参数(范围0-1):值越高识别越准确,但可能漏检;值越低识别越快,但可能误检;
  • 如果出现同一卡牌被多次识别的情况,可以把手牌区分成两个独立小区域,分别检测第一张和第二张手牌。

内容的提问来源于stack exchange,提问作者Artur Petrun

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 02:07:13