首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Python中的摇滚、纸剪刀游戏(基于控制台)

Python中的摇滚、纸剪刀游戏(基于控制台)
EN

Code Review用户
提问于 2017-03-11 17:47:41
回答 2查看 669关注 0票数 3

我是Python编程的初学者,我只做过一些小项目,这就是其中之一。代码的一个部分来自于我为解决问题所做的堆栈溢出的回答(尝试部分),而所有其他代码都是我的。

代码语言:javascript
复制
import random,os,time
score = {'human':0,'robot':0}
def game(): #Basic Game code.
    time.sleep(1)
    os.system('clear')
    print('IA: ' + str(score['robot']) + ' Human: ' + str(score['human']))
    print('1.Rock 2.Scissors 3.Paper')
    while True:
        try:
            choice = int(input("Input your choice:\n"))
            if choice < 1 or choice > 3: #Valid number but outside range, don't let through
                raise ValueError
            else: #Valid number within range, quit loop and the variable selection contains the input.
                break
        except ValueError: #Invalid input
            print("Enter a number from 1 to 3.")
    rchoice = random.randint(1,3)
    time.sleep(1)
    if rchoice == 1:
        print('IA choice is Rock.')
    elif rchoice == 2:
        print('IA choice is Scissors.')
    elif rchoice == 3:
        print('IA choice is Paper.')

    if (rchoice==1 and choice==2)or(rchoice==2 and choice==3)or(rchoice==3 and choice==1):
        print('IA wins!\n')
        score['robot'] += 1
        time.sleep(0.5)
    elif (rchoice == choice):
        print("Draw, let's repeat")
        time.sleep(0.5)
        game()
    else:
        print('You win!\n')
        time.sleep(0.5)
        score['human'] += 1

def startgame(): #The introduction of the game.
    os.system('clear')
    print('Rock-Paper-Scissors v.1')
    print('Developed by P.R.B.\n')
    ngames = int(input('How many games do you want to play?\n'))
    time.sleep(1)
    i = 0
    while i != ngames:
        game()
        i += 1
    print('Final Score:')
    print('IA: ' + str(score['robot']) + ' Human: ' + str(score['human']))
    if score['human'] > score['robot']:
        print('You win the game!\n')
    else:
        print('Game Over')
        print('IA wins the game!\n')

startgame()
EN

回答 2

Code Review用户

回答已采纳

发布于 2017-03-13 10:40:01

免责声明:我对这篇长篇文章表示歉意。选择我的建议,特别是关于使用clear的部分。希望这里没有任何排印/错误。

这个问题类似于我先前回答的另一个问题(位于这里),并将使用下面大致相同的注释。

进口

正如PEP8和个人经验所指出的,通过将进口放在单独的行上,可以更容易地跟踪它们。

代码语言:javascript
复制
import random
import os
import time

此外,由于您只使用来自每个模块的特定内容,所以您可以简单地导入您感兴趣的每个单独的内容:

代码语言:javascript
复制
from random import randint
from os import system
from time import sleep

最后,从您使用os的方式来判断,您可能最好使用subprocess。它应该是一个改进版本

因此,与其:

代码语言:javascript
复制
import os
# ...
os.system('clear')

你可以:

代码语言:javascript
复制
from subprocess import call
# ...
call(['clear'])

clear

的使用

如果您确定运行代码的任何操作系统都有一个clear命令,请跳到下一节.

我喜欢你在游戏中使用clear的方式。

不幸的是,您的代码不是跨平台的(主要是因为clear不存在于windows上,而是它的cls)。不管这对你是否重要,最好检查一下你现在在哪个操作系统上。

我不太确定这条路是怎么走的。

这是我支持Windows的方式:

代码语言:javascript
复制
from sys import platform

# use __ to denote to others not to modify this variable
if platform == "win32":
    __clear_cmd = 'cls'
else: # assume any other OS uses "clear"
    __clear_cmd = 'clear'

无论何时调用clear命令,都必须执行如下操作:

代码语言:javascript
复制
call([__clear_cmd], shell=True)

有关此问题的更多信息,请参见这里

不必要的注释

您的许多代码已经自我记录,不需要注释(这是一件好事)。

你应该只评论一些你认为很难理解的地方。

变量名

我建议重命名几个标识符,即:

game

  • game to play_rps (或更具有描述性的内容)
  • choiceuser_choice
  • rchoice to robot_choice (在score中与您的姓名保持一致)

startgame

  • startgame to game_counter (或更具有描述性的内容)
  • ngamesnum_games

产出:

  • IARobot (保持一致性)
  • HumanPlayer (保持一致性)

用户输入

正如您在使用score时所注意到的,我假设您知道字典是如何工作的。

就像您如何跟踪人类和机器人的得分一样,您可以使用字典来跟踪有效的用户输入:

代码语言:javascript
复制
options = {1:'rock', 2:'paper', 3:'scissors'} 

使用options并在while循环中稍微重新排列代码,我们可以生成以下内容:

代码语言:javascript
复制
while choice not in options:
    try:
        choice = int(input("Input your choice: "))
        if user_choice not in options:
            raise ValueError
    except ValueError:
        print("Enter a number from 1 to 3.")

计算机选择

options添加到我们的代码中(来自上一节)简化了后面的部分:

代码语言:javascript
复制
print('IA chose:', options[robot_choice])

计算获胜者

这部分值得商榷。我宁愿把这些行写成这样:

代码语言:javascript
复制
winner = None
#...
# determine winner of current game
if user_choice == robot_choice:
    winner = None
elif user_choice == 1: # rock
    if robot_choice == 2:
        winner = 'robot'
    else:
        winner = 'player'
elif user_choice == 2: # paper
    if robot_choice == 3:
        winner = 'robot'
    else:
        winner = 'player'
else: # scissors
    if robot_choice == 1:
        winner = 'robot'
    else:
        winner = 'player'

# update score of winner if applicable
if winner:
    print(winner, 'won!')
else:
    print('Draw, let\'s repeat')

您的代码获得堆栈溢出的可能性非常小,但仍然是可能的。

如果您一直得到一个抽签,您的程序的调用堆栈将显示如下内容:

代码语言:javascript
复制
start_game():
    game():
        game():
            game():
                ...and so on.

通过返回一个值来避免这一点,标记游戏是否完成。

代码语言:javascript
复制
# update score of winner if applicable
if winner:
    print(winner, 'won!')
else:
    print('Draw, let\'s repeat')

# returns None if no winner
return winner

startgame

您的num_games while循环可能会遇到以下错误:

  1. 如果用户输入要玩的游戏数量为负数,它就可以无限地运行。
  2. 如果用户输入一个值(该值不是整数),则会崩溃。

根据您希望如何做到这一点(循环与否),执行一个try/except来捕获它(就像您如何实现user_choice一样):

代码语言:javascript
复制
num_games = 0
try:
    num_games = int(input('How many games do you want to play?\n'))
except ValueError:
    print('Invalid amount of games to play! Quitting game.')
    num_games = 0

另一个问题是:如果玩家和机器人得分相同,你不会检查会发生什么。向此添加一个==大小写。

score移到此方法中。我们可以使用从另一个函数返回的winner来查看谁赢了,并控制我们想玩多少个游戏。

使用for循环(与while循环混合)来跟踪玩过的游戏和得分(_通常会注意到一个未使用的变量):

代码语言:javascript
复制
winner = None
for _ in range(num_games):
    # play current game until there is a winner
    while not winner:
        winner = play_rps()

    # update score of winner
    score[winner] += 1

最后,当您调用game_counter (或原始代码中的startgame )时,您应该确保您的代码只在被调用为main时才运行。

代码语言:javascript
复制
if __name__ == '__main__':
    game_counter()

并且通过python rps.py调用,或者承载代码的文件名可能是。

更多关于__main__ 这里的信息。

最终产品

在应用了上述所有建议和一些额外的调整之后,下面是生成的代码(添加跨平台支持命令使事情变得有点烦人):

代码语言:javascript
复制
from random import randint
from subprocess import call
from sys import platform
from time import sleep

if platform == "win32":
    __clear_cmd = 'cls'
else: # assume every other OS uses "clear"
    __clear_cmd = 'clear'


def play_rps():
    sleep(1)

    options = {1:'Rock', 2:'Paper', 3:'Scissors'}
    user_choice = None

    while user_choice not in options:
        print('1. Rock')
        print('2. Scissors')
        print('3. Paper')

        try:
            user_choice = int(input("Input your choice: "))

            if user_choice not in options:
                raise ValueError
        except ValueError: #Invalid input
            print("ERROR: Input must be a number within 1 to 3.")

    # determine Robot's choice
    robot_choice = randint(1,3)
    sleep(1)
    print('Robot choice is:', options[robot_choice])

    # determine winner of current game
    if user_choice == robot_choice:
        winner = None
    elif user_choice == 1: # rock
        if robot_choice == 2:
            winner = 'Robot'
        else:
            winner = 'Player'
    elif user_choice == 2: # paper
        if robot_choice == 3:
            winner = 'Robot'
        else:
            winner = 'Player'
    else: # scissors
        if robot_choice == 1:
            winner = 'Robot'
        else:
            winner = 'Player'

    # update score of winner if applicable
    if winner:
        print(winner, 'won!')
    else:
        print('Draw, let\'s repeat')

    sleep(0.5)

    return winner

def game_counter():
    call([__clear_cmd], shell=True)

    print('Rock-Paper-Scissors v.1')
    print('Developed by P.R.B.\n')

    score = {'Player':0,'Robot':0}
    winner = None
    num_games = 0

    try:
        num_games = int(input('How many games do you want to play?\n'))

        if num_games <= 0:
            raise ValueError
    except ValueError:
        print('Invalid amount of games to play! Quitting game.')
        num_games = 0

    sleep(1)

    for _ in range(num_games):
        # play current game until there is a winner
        while not winner:
            sleep(1)
            call([__clear_cmd], shell=True)
            print('Robot:', score['Robot'], 'Player: ', score['Player'])
            winner = play_rps()

        # update score after game and reset winner
        score[winner] += 1
        winner = None

    # played at least one game
    if num_games > 0:
        print('Final Score:')
        print('Robot:', score['Robot'], 'Player: ', score['Player'])
        if score['Player'] > score['Robot']:
            print('You won the game!\n')
        elif score['Player'] == score['Robot']:
            print('You both tied.\n')
        else:
            print('Robot won the game!\n')

if __name__ == '__main__':
    game_counter()
票数 1
EN

Code Review用户

发布于 2017-03-13 03:01:43

看起来你对字典和清单都很熟悉。那么,让我们来看看您是如何收集和输入输入的。看起来,您正在尝试使用try/以外和if语句来控制错误的输入。不过也有一些麻烦。如果代码中有像1.22.5这样的值,我可以通过它发送浮点。您的代码会将其转换为int,然后尝试使用该值,但还有另一种处理以下内容的方法:

代码语言:javascript
复制
if choice not in ['1','2','3']:
    raise ValueError
else:
    break

因此,在本例中,我使用了唯一可接受的值的列表,检查选择是否在那里,然后继续前进。

你的控制流程看起来有点混乱。有几种方法可以解决这个问题。

如果我们保持相同的一般方法,您可以通过扩展它来提高它的可读性。我会为此做一个新的功能:

代码语言:javascript
复制
def compare(x,y):
    if x == y:
        state = "It's a Draw!"
    if x == '1':
        if y == '2':
            state = "You Lose!"
        else:
            state == "You Win!"
    elif x == '2':
        if y == '1':
            state = "You Win!"
        else:
            state == "You Lose!"
    else:
        if y == '1':
            state = "You Lose!"
        elif y == '2':
            state = "You Win!"
    return state

然而,取决于你对列表的舒适感,还有另一种更简单的方法!

您可以设置一个可能的游戏条件列表,然后对它们做任何您想做的事情:

代码语言:javascript
复制
game_result = ["tie!", "win!", "lose!"]

(实际上,列表中的那个序列是为Rock,2)纸张和3)剪刀编码的。应该有另一个安排岩石剪刀纸,虽然这使事情顺利)。

然后定义一个比较函数,它只查看用户和机器人输入之间的差异(首先需要将它们转换为int数据类型)。

代码语言:javascript
复制
def compare(x,y):
result = game_result[ (x-y)%3 ]
return result

有一些棘手的事情,你是如何检查你应该在哪一轮。因此,首先,如果将变量名更改为有用的东西(如round_numbermatches_left ),则可能会有所帮助/更易读。

然后,如果循环数不等于n,则将其设置为结束while循环。这里还有另一个潜在的错误。如果用户输入了一个浮点或者你不想要的东西呢?--实际上,你在输入上使用int(),这就纠正了这一点。打得好!但是,这种设计模式并不总是延续得很好,其他读者可能也不太清楚(对我来说也不是这样)。

假设播放机进入1.2,那么如果您不使用int(),则while循环将永远进行下去。处理此问题的一种方法是使用“尝试/除”;另一种方法是使用isinstance;另一种方法是执行以下操作:

代码语言:javascript
复制
while num_of_rounds <= ngames:
        game()
        num_of_rounds += 1

通过这种方式,您将涵盖更广泛的一组可接受/不可接受的内容,并且不让您的代码在一个小的操作窗口(以及可利用性)上运行。

总的来说,您的代码工作,是有趣的发挥!最重要的事情是风格,可读性,以及如何处理错误输入的不同想法。我将查阅PEP8Python风格指南,以获得一些一般性见解:https://www.python.org/dev/peps/pep-0008/

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/157528

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档