我最初的想法是Rock–Paper–Scissors (RPS) rules:
- It's a cyclic relation between the elements where each element beats the one in before it (Scissors beats (cuts) Paper)
- The 1st element (that doesn't have anything before) beats the last one (and the cycle is complete)
- 当添加更多元素时,只是为了让更多的用户可以玩(只要用户数少了1比元素数),但现在我看到了这是不对的因为有些情况下结果可能是不确定的(实际上唯一有效的情况是没有 2 个玩家选择相同的选项)
显然(感谢[维基百科]:石头剪刀布), 为一个balanced游戏(元素数量为奇数):
下面是将上述规则放入代码中的样子(我还重新设计了它以纠正代码片段中的一些错误)。所有的“魔法”都发生在outcome.
代码00.py:
#!/usr/bin/env python3
import sys
_elements_list = [
["Rock", "Paper", "Scissors"],
["Rock", "Paper", "Scissors", "Spock", "Lizard"], # !!! The order is DIFFERENT (RPSSL) than the name of the game: RPSLS !!!
]
elements_dict = {len(item): item for item in _elements_list}
del _elements_list
def get_users_choices(valid_options):
ret = [-1] * 2
for i in (0, 1):
user_choice = None
while user_choice not in valid_options:
user_choice = input("Enter user {0:d} option (out of {1:}): ".format(i + 1, valid_options))
ret[i] = valid_options.index(user_choice)
return ret
def outcome(idx0, idx1, count): # Returns -1 when 1st player wins, 0 on draw and 1 when 2nd player wins
if idx0 == idx1:
return 0
index_steps = [-i * 2 - 1 for i in range(count // 2)] # Index steps (n // 2 items) from current index: {-1, -3, -5, ...} (negative values mean: before)
idx0_beat_idxes = [(idx0 + i + count) % count for i in index_steps] # Wrap around when reaching the beginning of the list
if idx1 in idx0_beat_idxes:
return -1
return 1
def main():
element_count = 3 # Change it to 5 for RPSLS
if element_count <= 2:
raise ValueError("Can't play game")
elements = elements_dict.get(element_count)
if not elements:
raise ValueError("Invalid option count")
choices = get_users_choices(elements)
res = outcome(*choices, element_count)
if res == 0:
print("'{0:s}' and '{1:s}' are DRAW.".format(elements[choices[0]], elements[choices[1]]))
elif res < 0:
print("'{0:s}' WINS over '{1:s}'.".format(elements[choices[0]], elements[choices[1]]))
else:
print("'{0:s}' LOSES to '{1:s}'.".format(elements[choices[0]], elements[choices[1]]))
if __name__ == "__main__":
print("Python {0:s} {1:d}bit on {2:s}\n".format(" ".join(item.strip() for item in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform))
main()
print("\nDone.")
Output:
[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q057491776]> "e:\Work\Dev\VEnvs\py_064_03.07.03_test0\Scripts\python.exe" code00.py
Python 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)] 64bit on win32
Enter user 1 option (out of ['Rock', 'Paper', 'Scissors']): Rock
Enter user 2 option (out of ['Rock', 'Paper', 'Scissors']): Scissors
'Rock' WINS over 'Scissors'.
Done.