用公式逻辑地确定游戏结果 [英] Logically determine game outcome with formula
问题描述
我正在努力成为一个更好的编码器,其中包括摆脱我的硬编码"习惯,以保持程序的动态性和易于维护性.
I am trying to become a better coder, which includes getting rid of my 'hard-coding' habits to keep my programs dynamic and easy to maintain.
现在,我正在练习编写一个简单的石头,剪刀,剪刀"游戏:
Right now I am writing a simple Rock, Paper, Scissors game as practice:
import time
validoptions = ["rock", "paper", "scissors"]
u1input = input("User 1, do you want to choose rock, paper or scissors?").lower()
if not u1input in(validoptions):
u1input = input("What the hell User 1, choose a valid option: rock, paper or scissors?").lower()
u2input = input("User 2, do you want to choose rock, paper or scissors?").lower()
if not u2input in(validoptions):
u2input = input("What the hell User 2, choose a valid option: rock, paper or scissors?").lower()
u1 = validoptions.index(u1input)
u2 = validoptions.index(u2input)
if u1 - u2 == 0:
result = "It's a draw! Both parties have proven to be of equal strength."
print("Stakes are high... The battle is on... Calculating losses...")
for i in range(1,4):
time.sleep(1)
print("...")
time.sleep(1)
print(result)
对于像Rock,Paper和Scissors这样的游戏,结果并不多(6次赢/输,1次平局或3 ^ 2个人结果).我可以轻松地将所有可能的结果编码到已经编码的抽奖结果旁边.但是,如果游戏扩展了3个选项,该怎么办?说:Rock, Paper, Scissors, Pans, Swords, and Rifles
:那将是6 ^ 2 = 36个结果!
For such a game like Rock, Paper, Scissors, there aren't many outcomes (6 wins/losses, and 1 draw outcome, or 3^2 individual outcomes). I could easily code all possible outcomes next to the draw outcome I have already coded. However, what if the game expands with 3 more options? Say: Rock, Paper, Scissors, Pans, Swords, and Rifles
: that would be 6^2 = 36 outcomes!
随着此列表的扩展,潜在结果的数量变得越来越难以硬编码.我想使用一种公式或另一种智能"的动态方法来确定游戏的结果,方法与if u1 - u2 == 0:
行类似.
As this list expands, the amount of potential outcomes becomes harder to hard-code. I want to use a formula or another 'smart', dynamic method of determining the game's outcome, in a similar fashion to the if u1 - u2 == 0:
line.
这有可能吗?
推荐答案
我最初对 R ock– P aper– S的看法剪刀( RPS )规则:
What I initially thought about the Rock–Paper–Scissors (RPS) rules:
- 这是元素之间的循环关系,其中每个元素在其之前击败一个(剪刀击败(剪切)纸张)
- 1 st 元素(之前没有任何内容)击败了最后一个元素(并且循环完成了)
- 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)
显然(由于 [Wikipedia]:Rock –paper–剪刀),用于平衡游戏(元素数量奇数):
Apparently (thanks to [Wikipedia]: Rock–paper–scissors), for a balanced game (odd number of elements):
-
每个元素都击败了其他元素的一半(结果是输给了另一半)
Each element beats half of the other ones (and as a consequence, loses to the other half)
- (1 st )之前的一个
- 前3个 rd
- 第5个第个
- ...
- 到达列表的开头时,跳到结尾(环绕)
- The (1st) one before it
- The 3rd one before it
- The 5th one before it
- ...
- When reaching beginning of the list, jump to its end (wrap-around)
这是3个元素( RPS )游戏的概括(也适用于 RPSLS )
This is a generalization of the 3 element (RPS) game (and also applies to RPSLS)
这是上面的规则在输入代码时的样子(我还对它进行了重新设计,以纠正您的代码段中的某些错误).所有的魔术"发生在结果中.
Here's what the above rule looks like when put into code (I've also redesigned it to correct some errors in your snippet). All the "magic" happens in outcome.
code00.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.")
输出:
[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.
这篇关于用公式逻辑地确定游戏结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!