首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用类和游戏循环测试终端文本游戏

用类和游戏循环测试终端文本游戏
EN

Code Review用户
提问于 2020-03-25 14:37:07
回答 1查看 134关注 0票数 3

我正在制作一个超级简单和哑巴的终端文字游戏,以尝试统一测试在蟒蛇。我遇到了一个问题。当我运行测试时,游戏循环被运行,我必须手动插入输入才能继续测试。

在我运行测试时,是否有一种方法可以不运行游戏循环,以便只测试类方法?

任何其他关于代码的建议也将是有帮助的。

游戏概念:玩家被提示建立,收集,招募,或攻击每一个回合,当某人的城堡生命值是<= 0,游戏结束。

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

class Player():
    def __init__(self):
        self.castle = 1
        self.villagers = 1
        self.warriors = 0
        self.food = 0
        self.stone = 0

    def takeTurn(self):
        action = 0
        action = int(input("1) Build\n2) Gather\n3) Recruit\n4) Attack\n"))
        if action == 1:
            self.build()
        elif action == 2:
            self.gather()
        elif action == 3:
            self.recruit()
        elif action == 4:
            self.attack()
        else:
            self.takeTurn()

    def build(self):
        if self.stone >= 1:
                self.castle += 1
                self.stone -= 1
        else:
            os.system('clear')
            if self.__class__.__name__ == "Player":
                print("You don't have enough stone!\n")
                printMenu()
            self.takeTurn()

    def gather(self):
        self.food += self.villagers
        self.stone += self.villagers

    def recruit(self):
        if self.food >= 1:
                self.warriors += 1
                self.food -= 1
        else:
            os.system('clear')
            if self.__class__.__name__ == "Player":
                print("You don't have enough food!\n")
                printMenu()
            self.takeTurn()

    def attack(self):
        if self.warriors >= 1:
            if self.__class__.__name__ == "Player":
                ai.castle -= self.warriors
            elif self.__class__.__name__ == "AI":
                player.castle -= self.warriors


class AI(Player):
    def __init__(self):
        super().__init__()

    def makeMove(self):
        action = 0
        # Win if player castle weak
        if player.castle == self.warriors:
            player.castle -= self.warriors
        # Build if castle weak
        elif self.castle == player.warriors:
            if self.stone >= 1:
                self.castle += 1
            else:
                action = random.randint(2, 4)
        else:
            action = random.randint(1, 4)

        if action == 1:
            super().build()
        if action == 2:
            super().gather()
        if action == 3:
            super().recruit()
        if action == 4:
            super().attack()


player = Player()
ai = AI()


def printMenu():
    print("You:\nCastle: " + str(player.castle) + " Food: " + str(player.food) + " Stone: " + str(player.stone) + " Villagers: " + str(player.villagers) + " Warriors: " + str(player.warriors) + "\n")
    print("Computer:\nCastle: " + str(ai.castle) + " Food: " + str(ai.food) + " Stone: " + str(ai.stone) + " Villagers: " + str(ai.villagers) + " Warriors: " + str(ai.warriors) + "\n")


def gameLoop():
    # MAIN LOOP
    playing = False
    if playing:
        printMenu()

        player.takeTurn()    
        ai.makeMove()   

        if ai.castle <= 0:
            playing = False
            print("You Win!\n")
        elif player.castle <= 0:
            playing = False
            print("You Lose!")
        else:
            os.system('clear')


gameLoop()
代码语言:javascript
复制
import unittest

from game.main import Player


class TestPlayer(unittest.TestCase):
    def setUp(self):
        self.player = Player()

    def test_build(self):
        # Should fail 
        self.player.castle = 2
        self.player.stone = 1
        self.player.build()
        self.assertEqual(self.player.castle, 1)

if __name__ == '__main__':
    unittest.main()
EN

回答 1

Code Review用户

回答已采纳

发布于 2020-03-26 18:28:06

您已经在评论中给出了您的"bug“的答案,但我将尝试给您一个更深入的回顾。不过,我将重复前面提到的解决方案:避免程序在导入时自动运行,但您的主要调用在if __name__ == "__main__"中(如果有兴趣,请阅读更多的这里 )。

对于您的__init__方法,将您的方法初始化器作为(默认)参数会随着项目的发展而提供更大的灵活性:

代码语言:javascript
复制
    def __init__(self, castle=1, villagers=1, warriors=0, food=0, stone=0):
        self.castle = castle
        self.villagers = villagers
        self.warriors = warriors
        self.food = food
        self.stone = stone

对于第一个真正的方法,我建议您继续使用snake_case over camelCase的Python标准。此外,将变量action初始化为0实际上并没有起到任何作用,因为您在下面的行中覆盖了它。而且,由于您依赖于这个输入,所以我认为,当您没有得到一个int时,或者如果您得到类似于11的东西,您应该知道该做什么(考虑到选项,这里的11可能是一个错误)。

这很自然地导致了测试的目的(耶!)。测试的一个好处是,它允许您考虑在创建对象或调用函数时到底想要发生什么。对于您的takeTurns函数,这可能是只允许输入数字,如果不输入0-5范围内的单个数字,则会引发异常或请求另一个输入。然后,您将基本上实现您的功能(在测试之后),以满足您在开始时提出的所有要求。然后,您可能还会发现,您可能是以错误的方式考虑它;在这种情况下,可能是take_turns (我为您重命名了它)。应该不是要求input(),而是接受一个论点,take_turns(user_choice)

最后,我将添加一些较小的建议。

  • 而不是self.__class__.__name__ == "Player":,您可以(而且应该)使用isinstance(self, Player)
  • action = random.randint(1, 4)与4 if-statements耦合,random中有一个名为choice的方便的小函数(请看这里)。您还可以通过重新考虑AI与Player的区别(或不不同),使您的D24类更小。
  • F-字符串是超好的。与print("You:\nCastle: " + str(player.castle) + " Food: " + str(player.food) + " Stone: " + str(player.stone) + " Villagers: " + str(player.villagers) + " Warriors: " + str(player.warriors) + "\n")不同,您可以使用(并且注意到我删除了str(),因为您不需要它):print(“f”“you :player.castle:{player.castle} Food:{player.food} Stone:{player.stone}村民:{player.villagers}勇士:{player.warriors}”)
票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

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

复制
相关文章

相似问题

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