如何在Python Match/Case中同时测试多条件?21点程序案例排查
问题:Python Match/Case 多条件匹配失效(21点程序)
我知道可以用|作为"或"逻辑分隔测试用例,但当前场景更复杂:我有4个布尔相关变量,对应真值表的16种状态。我给21点程序写的动作测试代码里,所有case都没触发,代码如下:
for x in range(10): myHandTotal = myHand.getTotal() #获取当前手牌的总点数 isSoft = myHand.isSoft #判断手牌是否为软牌(至少有一张A计为11点) hardAction = at.getHardAction(myHand, dealer) #根据硬牌策略表获取Hit或Stand动作 softAction = at.getSoftAction(myHand, dealer) #根据软牌策略表获取Hit或Stand动作 print("Total: ", myHandTotal, " - isSoft: ", isSoft, " - getHardAction: ", hardAction, " - getSoftAction: ", softAction) match (myHandTotal < 21, isSoft, hardAction, softAction): case [True, True, "Stand", "Hit" | True, True, "Hit", "Hit"]: #若为软牌且软牌策略表要求Hit myHand.draw1(deck) print("Should Hit") continue case [True, False, "Hit", "Hit" | True, False, "Hit", "Stand"]: #若为硬牌且硬牌策略表要求Hit myHand.draw1(deck) print("Should Hit") continue case [False, True, "Stand", "Hit" | False, True, "Hit", "Hit" | False, False, "Hit", "Hit" | False, False, "Hit", "Stand" | False, True, "Stand", "Stand" | False, False, "Stand", "Stand" | False, True, "Hit", "Stand" | False, False, "Stand", "Hit"]: break #爆牌(bust) case [True, True, "Stand", "Stand" | True, True, "Hit", "Stand"]: #若手牌点数小于21且软牌策略表要求Stand break case [True, False, "Stand", "Stand" | True, False, "Stand", "Hit"]: #若手牌点数小于21且硬牌策略表要求Stand break
解决方案
你的代码核心问题是Match/Case中"或"逻辑的语法使用错误:Python模式匹配里,|只能用来分隔完整的匹配模式,不能在单个列表/元组模式内部直接拼接多组条件。
修正步骤
1. 拆分"或"条件为独立完整模式
把每个需要"或"的完整四元组用|分隔,而不是混在一个列表里。比如原来的软牌Hit条件,要拆成两个独立的元组模式:
case (True, True, "Stand", "Hit") | (True, True, "Hit", "Hit"):
2. 简化爆牌逻辑
爆牌只需要判断第一个变量myHandTotal < 21为False,后面三个变量可以用通配符_匹配任意值,不用枚举所有8种情况,大幅简化代码。
3. 统一匹配模式类型
你用(...)定义了匹配目标(元组),case里用元组()更贴合语法,避免和列表混淆(虽然Python支持列表匹配,但元组更对应)。
修正后的完整代码
for x in range(10): myHandTotal = myHand.getTotal() #获取当前手牌的总点数 isSoft = myHand.isSoft #判断手牌是否为软牌(至少有一张A计为11点) hardAction = at.getHardAction(myHand, dealer) #根据硬牌策略表获取Hit或Stand动作 softAction = at.getSoftAction(myHand, dealer) #根据软牌策略表获取Hit或Stand动作 print("Total: ", myHandTotal, " - isSoft: ", isSoft, " - getHardAction: ", hardAction, " - getSoftAction: ", softAction) match (myHandTotal < 21, isSoft, hardAction, softAction): # 软牌且软牌策略要求Hit的两种情况 case (True, True, "Stand", "Hit") | (True, True, "Hit", "Hit"): myHand.draw1(deck) print("Should Hit") continue # 硬牌且硬牌策略要求Hit的两种情况 case (True, False, "Hit", "Hit") | (True, False, "Hit", "Stand"): myHand.draw1(deck) print("Should Hit") continue # 爆牌:总点数>=21,其余条件任意 case (False, _, _, _): break #爆牌(bust) # 软牌且软牌策略要求Stand的两种情况 case (True, True, "Stand", "Stand") | (True, True, "Hit", "Stand"): break # 硬牌且硬牌策略要求Stand的两种情况 case (True, False, "Stand", "Stand") | (True, False, "Stand", "Hit"): break
额外说明
- 通配符
_在模式匹配中表示匹配任意值,适合用来忽略不需要判断的变量。 - 每个
case的逻辑要保持单一明确,避免把多个无关条件混在一起,方便后续维护。
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

