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
相关产品推荐
相关产品推荐

