能否优化简化这段石头剪刀布Python代码?现有条件判断待改进
Absolutely! That long chain of or conditions in your rock-paper-scissors code is definitely ripe for simplification. Let's walk through a few cleaner, more maintainable approaches to fix that clunky conditional logic.
优化方案1:使用胜负映射字典
This is probably the most intuitive approach—we can store the winning relationships in a dictionary, where each key is a player's choice, and the value is the choice it beats. This eliminates the need for all those or clauses entirely.
import random as ra out = ['rock', 'paper', 'scissor'] # 定义每个选项能击败的对手 winning_mappings = { 'rock': 'scissor', 'paper': 'rock', 'scissor': 'paper' } def match(): p1, p2 = ra.choice(out), ra.choice(out) print(f'P1: {p1} x P2: {p2}') if p1 == p2: print('Draw\n') elif winning_mappings[p1] == p2: print('P1 win\n') else: print('P2 win\n') for i in range(10): match()
优势
- 可读性强: 任何人看代码都能通过字典一眼看懂胜负规则
- 易维护: 如果以后要修改规则(比如新增选项),只需要更新字典,不用重写冗长的条件判断
- 简洁: 把复杂的多条件判断简化成一次字典查找
优化方案2:利用索引的循环数学关系
石头剪刀布的胜负是循环克制的,我们可以用选项列表的索引结合简单数学来判断:
rock(索引0)击败scissor(索引2)paper(索引1)击败rock(索引0)scissor(索引2)击败paper(索引1)
你会发现规律:当(p1索引 - p2索引) % 3 == 1时,玩家1获胜,这是因为获胜组合的索引差在模3运算后刚好为1。
import random as ra out = ['rock', 'paper', 'scissor'] def match(): # 先随机选索引,再映射到对应选项 p1_idx = ra.randint(0, 2) p2_idx = ra.randint(0, 2) p1, p2 = out[p1_idx], out[p2_idx] print(f'P1: {p1} x P2: {p2}') if p1_idx == p2_idx: print('Draw\n') elif (p1_idx - p2_idx) % 3 == 1: print('P1 win\n') else: print('P2 win\n') for i in range(10): match()
优势
- 无需硬编码配对: 不用列出所有获胜组合,用数学逻辑自动处理
- 扩展性好: 如果以后扩展游戏(比如加入
蜥蜴和史波克),只需要调整模数值和选项列表,不用修改判断逻辑
优化方案3:使用枚举增强类型可读性
如果想让代码更健壮(避免字符串拼写错误),可以用Python的Enum类型,它提供了命名常量,让代码意图更明确。
import random as ra from enum import Enum # 定义枚举类,限定合法选项 class RPSChoice(Enum): ROCK = 0 PAPER = 1 SCISSOR = 2 # 映射枚举值为人类可读的字符串 choice_to_str = { RPSChoice.ROCK: 'rock', RPSChoice.PAPER: 'paper', RPSChoice.SCISSOR: 'scissor' } def match(): p1 = ra.choice(list(RPSChoice)) p2 = ra.choice(list(RPSChoice)) print(f'P1: {choice_to_str[p1]} x P2: {choice_to_str[p2]}') if p1 == p2: print('Draw\n') elif (p1.value - p2.value) % 3 == 1: print('P1 win\n') else: print('P2 win\n') for i in range(10): match()
优势
- 类型安全: 不会出现
'roc'这种拼写错误的无效选项,枚举限定了只能选合法值 - 代码清晰: 枚举让代码意图更明确,尤其适合多人协作的大型项目
这三种方案都比原来的条件链更优秀,你可以根据场景选择:字典法适合小型脚本,索引法适合喜欢数学逻辑的场景,枚举法适合需要结构化、高可维护性的项目。
内容的提问来源于stack exchange,提问作者Salman Abdullah Idrees

