简体   繁体   English

砰! 游戏无法正常工作

[英]BANG! game not working properly

I'm new to Python. 我是Python的新手。 I built this awesome game called BANG! 我制作了一款很棒的游戏,叫BANG! This game places you against the computer and gives you three options: to shoot, reload or put up your shield. 该游戏将您放置在计算机上,并为您提供三个选择:射击,重新加载或盖起盾牌。 The computer randomly selects one of these options for each turn. 计算机每转一圈随机选择这些选项之一。 Then,the showdown takes place. 然后,进行摊牌。 For example if you shoot when the computer is reloading, the computer dies. 例如,如果在重新加载计算机时进行拍摄,计算机将死机。 Occasionally an extra life may be won. 有时可能会赢得额外的生活。

However, the code isn't working properly. 但是,代码无法正常工作。 When I tell the computer to print something, under some circumstances it prints it, under other circumstances it doesn't. 当我告诉计算机打印某些东西时,在某些情况下它将打印它,而在其他情况下则不会。 For example when I shoot with my only bullet, the computer doesn't print its actions. 例如,当我用唯一的子弹射击时,计算机不会打印其动作。 Moreover, sometimes the computer shoots with no bullets, causing its bullet level to drop to -1: I thought I had solved this problem by giving the computer different ranges to randomize with under different bullet conditions. 此外,有时计算机射击时没有子弹,导致子弹级别降至-1:我以为我解决了这个问题,方法是给计算机提供不同的范围,以便在不同的子弹条件下进行随机分组。

Could anyone please help me out and test the code for me? 谁能帮我解决一下并为我测试代码吗?

import random

print "Welcome to the Wild West. You see a wild man come towards you. He has a loaded gun in his hand."

bullets = 0
bullets_comp = 3
lives = 1

for turn in range(200):
    if bullets_comp == 0:
        comp_move = random.randint(0,2)        
    elif bullets_comp > 0:
        comp_move = random.randint(0,3)  
    #0 will be reload, 1 wil be shield, 2 will be shoot

    life_chance = random.randint(0,6)
    if life_chance == 3:
        lives = lives + 1
        print "An angel descends randomly and gives you a life!"

    guess = raw_input('What do you choose to do: Reload, Shield, or Shoot?')

    if guess == 'reload' or guess == 'Reload':
        print 'You reload.'
        if comp_move == 0:
            bullets_comp = bullets_comp + 1
            print 'Your opponent reloads.'
        elif comp_move == 1:
            print 'Your opponent raises his shield.'
        elif comp_move == 2:
            if lives == 1:
                print 'Your opponent shoots...YOU DIE!'
                break
            if lives > 1:
                print 'Your opponent shoots...you lose a life.'
                lives = lives - 1


        bullets = bullets + 1

    elif guess == 'Shield' or guess == 'shield':
        print 'You protect yourself.'
        if comp_move == 0:
            bullets_comp = bullets_comp + 1
            print 'Your opponent reloads.'
        elif comp_move == 1:
            print 'Your opponent raises his shield.'
        elif comp_move == 2:
            print 'Your opponent shoots...but you are protected!'
            bullets_comp = bullets_comp - 1

    elif guess == 'Shoot' or guess == 'shoot':
        if bullets == 0:
            print 'You have no bullets!'
        elif bullets > 0:
            print 'You shoot.'
            if comp_move == 0:
                print 'Your opponent reloads.'
                print 'You kill your opponent! Congratulations!'
                break
            elif comp_move == 1:
                print '... but your opponent raises his shield.'
                bullets = bullets - 1
            elif comp_move == 2:
                print 'Your bullets meet each other halfway through the air and combust.'
                bullets_comp = bullets_comp - 1

        bullets = bullets - 1



    else:
        print "You can't do that mate!"

    print 'You have %d bullets and %d lives left' % (bullets, lives)
    print 'Your opponent has %d bullets' %  (bullets_comp)

    print """


    """

Updated for Python 3.3 and with a few issues fixed. 已针对Python 3.3更新,并修复了一些问题。

import random

print ("Welcome to the Wild West. You see a wild man come towards you. He has a loaded gun in his hand.")

bullets = 0
bullets_comp = 3
lives = 1
playing = True

It's neater to have a boolean variable that exits the loop. 具有退出循环的布尔变量是更明智的。 The previous game ended after 200 turns with no explanation. 上一场比赛在200回合后结束,没有任何解释。 If you meant there to be a time limit it should be more explicit. 如果您有时间限制,则应更加明确。

while playing:

Let's have the status report at the start as it's not obvious from the intro that your gun isn't loaded. 让我们从一开始就获得状态报告,因为从简介中不明显您的枪未装好。

    print ("You have",bullets," bullets and ",lives," lives left")
    print ("Your opponent has ",bullets_comp," bullets")

Possibly a Python 3 change to how randInt works. 可能会对randInt的工作方式进行Python 3更改。

    if bullets_comp == 0:
        comp_move = random.randint(0,1)        
    elif bullets_comp > 0:
        comp_move = random.randint(0,2)  
    #0 will be reload, 1 wil be shield, 2 will be shoot

    life_chance = random.randint(0,6)
    if life_chance == 3:
        lives = lives + 1
        print ("An angel descends randomly and gives you a life!")

Use single letter codes for the moves - to avoid a clash on the letter S, we change Shoot to Fire. 使用单个字母代码进行移动-为避免字母S发生冲突,我们将“射击”更改为“射击”。 Storing our move in a variable lets us avoid heavy nesting. 将移动存储在变量中可以避免大量嵌套。

    your_move = -1
    while your_move == -1:
        guess = input('What do you choose to do: (R)eload, (S)hield, or (F)ire?')
        if guess == 'r':
            your_move = 0
        elif guess == 's':
            your_move = 1
        elif guess == 'f':
            your_move = 2

Now report moves. 现在报告动作。 Since shooting is the only move where your opponent's action matters, this way peaceful moves can be reported in just one place. 由于射击是唯一影响对手动作的举动,因此可以在一个地方报告和平举动。

        if your_move == 0:
            print("You reload.")
            bullets = bullets + 1
        elif your_move == 1:
            print("You raise your shield.")
        else:
            assert your_move == 2
            if (bullets == 0):
                print("You fire your empty gun. D'oh.")
                your_move = 0

Note that we change your_move here so the player isn't considered shooting in the next step. 请注意,我们在此处更改了your_move,因此在下一步中不考虑播放器射击。 The original allows the player to fire the empty gun and lose a turn as a result so I assume this was intended and that it shouldn't be caught at move validation. 原始版本允许玩家射击空枪并因此掉头一转,所以我认为这是有意的,不应在移动验证时被抓住。

            else:
                bullets = bullets - 1
                print("You fire.")

        if comp_move == 0:
            print("Your opponent reloads.")
            bullets_comp = bullets_comp + 1
        elif comp_move == 1:
            print("Your opponent raises his shield.")
        else:

Using else+assert instead of elif means that conditions that should never happen in non-buggy code will not be tested in release versions. 使用else + assert代替elif意味着在非Buggy代码中永远不会发生的条件将不会在发行版本中进行测试。 Bear in mind that using an elif means that nothing at all will happen if an unexpected condition arises which will make debugging hard. 请记住,使用elif意味着如果出现意外情况,则根本不会发生任何事情,这会使调试变得困难。

            assert comp_move == 2
            assert bullets_comp > 0
            bullets_comp = bullets_comp - 1
            print("Your opponent fires.")

Now, if somebody fired we do need to compare the two moves.. 现在,如果有人开除了,我们确实需要比较这两个举动。

        if your_move == 2:
            if comp_move == 2:
                print("Your bullets meet each other in the air and explode.")
            elif comp_move == 1:
                print("Your bullet hits your opponent's shield.")
            else:
                assert comp_move == 0
                print("You kill your opponent! Congratulations!")
                playing = False
        elif comp_move == 2:
            if your_move == 1:
                print("Your opponent's bullet hits your shield.")
            else:
                assert your_move == 0
                print("Your opponent shoots you..",end="")
                if (lives>1):
                    print(".. you lose a life.")
                    lives = lives - 1
                else:
                    print(".. and you die.")
                    playing = False

Note that the game design could also be improved. 注意,游戏设计也可以改进。 At the moment the player can always win because the shield is 100% effective and eventually the angel gives an unlimited number of lives. 此刻,玩家始终可以获胜,因为盾牌有效率为100%,最终,天使给予了无限的生命。 This is why I thought the time limit might be deliberate. 这就是为什么我认为时间限制可能是故意的。

  • If you reload and the computer shoots, you don't subtract from bullets_comp . 如果重新加载并且计算机射击,则不要从bullets_comp减去。
  • You subtract from bullets in multiple places. 您在多个地方从bullets中减去。 If you shoot and your opponent raises his shield it takes two bullets. 如果您射击并且对手举起盾牌,则需要两发子弹。
  • If you attempt to shoot with no bullets it takes away a bullet anyway. 如果您尝试在没有子弹的情况下射击,则无论如何都会带走子弹。

I deleted the multiple subtraction of the var "bullet" and fixed the rest: 我删除了变量“ bullet”的多次减法,并修复了其余的:

import random

print "Welcome to the Wild West. You see a wild man come towards you. He has a loaded gun in his hand."

bullets = 0
bullets_comp = 3
lives = 1

for turn in range(200):
    if bullets_comp == 0:
        comp_move = random.randint(0,1)    #edited to (0,1) becuase when it got 2 the computer shot with no bullets.
    elif bullets_comp > 0:
        comp_move = random.randint(0,2)  #edited to (0,2) - when you get 3, the computer doen't do anything.
    #0 will be reload, 1 wil be shield, 2 will be shoot

    life_chance = random.randint(0,6)
    if life_chance == 3:
        lives = lives + 1
        print "An angel descends randomly and gives you a life!"

    guess = raw_input('What do you choose to do: Reload, Shield, or Shoot?')
    if guess == 'reload' or guess == 'Reload':
        print 'You reload.'
        if comp_move == 0:
            bullets_comp = bullets_comp + 1
            print 'Your opponent reloads.'
        elif comp_move == 1:
            print 'Your opponent raises his shield.'
        elif comp_move == 2:
            if lives == 1:
                print 'Your opponent shoots...YOU DIE!'
                break
            if lives > 1:
                print 'Your opponent shoots...you lose a life.'
                lives = lives - 1
        bullets = bullets + 1

    elif guess == 'Shield' or guess == 'shield':
        print 'You protect yourself.'
        if comp_move == 0:
            bullets_comp = bullets_comp + 1
            print 'Your opponent reloads.'
        elif comp_move == 1:
            print 'Your opponent raises his shield.'
        elif comp_move == 2:
            print 'Your opponent shoots...but you are protected!'
            bullets_comp = bullets_comp - 1

    elif guess == 'Shoot' or guess == 'shoot':
        if bullets == 0:
            print 'You have no bullets!'
        elif bullets > 0:
            print 'You shoot.'
            if comp_move == 0:
                print 'Your opponent reloads.'
                print 'You kill your opponent! Congratulations!'
                break
            elif comp_move == 1:
                print '... but your opponent raises his shield.'
            elif comp_move == 2:
                print 'Your bullets meet each other halfway through the air and combust.'
                bullets_comp = bullets_comp - 1
            bullets = bullets - 1 #Edited - now the subtruction is in the "elif bullets > 0:" so you won't subtruct when you have no bullets 



    else:
        print "You can't do that mate!"

    print 'You have %d bullets and %d lives left' % (bullets, lives)
    print 'Your opponent has %d bullets' %  (bullets_comp)

    print """


    """

I refactored your code, I apologize if I went to far. 我重构了您的代码,如果我走得太远,我深表歉意。 In short, I would recommend keeping the bullet and lives manipulation to a very few parts. 简而言之,我建议您将bulletlives操纵控制在很少的部分。 This will prevent bugs from double adding or subtracting. 这将防止错误两次加或减。 In my version of your code, I isolated the bullet manipulation to inside the Player class. 在我的代码版本中,我将bullet操作隔离到Player类内部。

import cmd
import random
import logging
try:
    import pyreadline as readline
except ImportError:
    pass

SHIELD='shield'
RELOAD='reload'
SHOOT='shoot'


class OutOfLivesException(Exception):
    pass

class Player():

    def __init__(self, name, lives, bullets):
        self.name = name
        self.lives = lives
        self.bullets = bullets
        self.shield_enabled = False

    def reload(self):
        logging.info('%s reloads' % self.name)
        self.bullets = self.bullets + 1

    def has_bullets(self):
        return self.bullets > 0

    def shoot(self, opponent=None):
        if self.has_bullets():
            self.bullets = self.bullets - 1
            if opponent:
                logging.info('%s shoots %s' % (self.name,opponent.name))
                opponent.take_hit()
            else:
                logging.info('%s shoots' % self.name)
        else:
            logging.info('%s has no bullets' % self.name)

    def enable_shield(self):
        logging.info('%s raises shield' % self.name)
        self.shield_enabled = True

    def disable_shield(self):
        self.shield_enabled = False

    def take_hit(self):
        if self.shield_enabled:
            logging.info('%s is protected by shield' % self.name)
            return False

        self.lives = self.lives - 1
        logging.info('%s is hit' % self.name)
        if self.lives <= 0:
            logging.info('%s dies' % self.name)
            raise OutOfLivesException()
        return True

    def __str__(self):
        return '%s has %d bullets and %d lives left' % (self.name, self.bullets, self.lives)


class TurnManager:

    def __init__(self, computer, human):
        self.computer = computer
        self.human = human

    def next_turn(self, computer_action, human_action):
        self._process_pre_turn()
        result = self._process_turn(computer_action, human_action)
        self._process_post_turn()
        return result

    def _run_angel(self, player):
        life_chance = random.randint(0, 6)
        if life_chance == 3:
            player.lives = player.lives + 1
            logging.info(
                "An angel descends randomly and gives %s a life!" % player.name)

    def _display_state(self):
        logging.info(str(self.computer))
        logging.info(str(self.human))

    def _process_pre_turn(self):
        self._run_angel(self.human)

    def _process_turn(self, computer_action, human_action):
        # handle shields
        if(computer_action == SHIELD):
            self.computer.enable_shield()
        if(human_action == SHIELD):
            self.human.enable_shield()

        # handle reloads
        if(computer_action == RELOAD):
            self.computer.reload()
        if(human_action == RELOAD):
            self.human.reload()

        # handle shooting
        if human_action == SHOOT and human_action == computer_action and self.computer.has_bullets() and self.human.has_bullets():
            self.computer.shoot()
            self.human.shoot()
            logging.info(
                'Your bullets meet each other halfway through the air and combust.')
        else:
            if(computer_action == SHOOT):
                try:
                    self.computer.shoot(self.human)
                except OutOfLivesException:
                    return True  # returning true causes Cmd to stop looping
            if(human_action == SHOOT):
                try:
                    self.human.shoot(self.computer)
                except OutOfLivesException:
                    return True  # returning true causes Cmd to stop looping

        self._display_state()

    def _process_post_turn(self):
        # reset shields
        self.computer.disable_shield()
        self.human.disable_shield()


class Bang(cmd.Cmd):

    """Implementation of "Bang" using cmd.Cmd"""

    def emptyline(self):
        pass

    def do_EOF(self, line):
        return True

    def __init__(self, turn_manager):
        cmd.Cmd.__init__(self)

        self.intro = "Welcome to the Wild West. You see a wild man come towards you. He has a loaded gun in his hand."
        self.prompt = "What do you choose to do: Reload, Shield, or Shoot?"

        self.turn_manager = turn_manager

    def process_turn(self, human_action):
        computer_action = random.choice((RELOAD, SHIELD, SHOOT))
        return self.turn_manager.next_turn(computer_action, human_action)

    #
    # RELOAD
    #
    def do_reload(self, line):
        "Reload gun"
        return self.process_turn(RELOAD)

    #
    # SHIELD
    #
    def do_shield(self, line):
        "Cover with Shield"
        return self.process_turn(SHIELD)

    #
    # SHOOT
    #
    def do_shoot(self, line):
        "Shoot the opponent"
        return self.process_turn(SHOOT)


if __name__ == '__main__':
    logging.basicConfig(level=logging.INFO,
                        format='\t%(message)s')

    computer = Player('Computer', 1, 3)
    human = Player('Human', 1, 0)

    turn_manager = TurnManager(computer, human)
    bang = Bang(turn_manager)
    bang.cmdloop()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM