如何运行一个while循环受多个变量的影响?

How to run a while loop affected by multiple variables?

我是 Python 的新手,我搜索这个答案已经几天了,但没有看到答案。如果我错过了 post,我深表歉意,并且很乐意去阅读它。这更像是一个概念性问题,所以只是浏览答案并没有让我走得太远。

我正在尝试使用我知道的纸笔 RPG 系统作为学习的跳板 Python,我想不仅按玩家顺序,而且按角色速度来划分回合嗯

示例代码(还有更多,但这是问题部分):

class char:
    def __init__(self,name,side,Spd):
    self.name=name
    self.side=side
    self.Spd=Spd

hero=char("Jimbo","good",4)
helplessSidekick=char("Timmy","good",2)
thug1="Crusher","evil",3)
thug2="Bruiser","evil",3)

所以 Jimbo spd 4,Timmy spd 2,Crusher spd 3,Bruiser spd 3。对于列出的角色,我希望一轮战斗的回合顺序是: J,C,B,T,J,C,B,T,J,C,B,J 有点倒数每个,直到他们都失去了速度。我可以使用 for 循环生成初始转弯顺序,没问题。但是我需要一个 while 循环来实际 运行 因为他们中的一个可以被击败,因此不再在回合顺序中,natch——当然,如果 Jimbo 在他的第一步中 KOs Crusher,那么回合顺序可能会崩溃.

我已经盯着这个看了几天了,我被难住了。对于这个问题的初学者性质,我提前表示歉意;我在这方面玩得很开心,但我肯定还有很多东西要学。谢谢!

您的缩进语法无效,但我假设这只是代码格式错别字。

无论如何,您都没有使用惯用的大写约定。特别是 class 名称应该是大写的前导字母。为什么只有 Spd 大写首字母而不是其他参数?

我怀疑您的查询的实质是关于在遍历容器的同时编辑容器。天真地这样做,迭代器不会知道您在迭代容器时对容器所做的更改。通常最佳做法是在编辑原始容器的同时迭代容器的副本。

这是一种方法,字符集合保持不变,但非活动字符的散列 table(Python 中的 set)随着字符被杀死而增长关闭。

为了便于说明,我硬编码了一个有 5 个回合的游戏和一个注定的未来,在这个游戏中,Crusher 在第 2 回合死于 Jimbo 的手中。

        class char:
            def __init__(self,name,side,Spd):
                self.name=name
                self.side=side
                self.Spd=Spd

        hero=char("Jimbo","good",4)
        helplessSidekick=char("Timmy","good",2)
        thug1=char("Crusher","evil",3)
        thug2=char("Bruiser","evil",3)
        
        global inactiveChars
        inactiveChars = set()
        global turns
        turns = 5
        def gameOver():
            global turns
            over = turns == 0
            if turns > 0:
                turns -= 1
            return over
        def killChar(name):
            global inactiveChars
            inactiveChars.add(name)
            print(f"Oof! {name} was KO'ed")
        def takeTurn(turnNumber, charName):
            if turnNumber == 2 and charName == "Jimbo":
                killChar("Crusher")

        chars = [hero, helplessSidekick, thug1, thug2]
        chars.sort(key=lambda character:character.Spd, reverse=True)
        curTurn = 0
        while not gameOver():
            curTurn += 1
            print(f"======== Turn number {curTurn}:")
            for ch in chars:
                if ch.name not in inactiveChars:
                    print(f"It's {ch.name}'s turn")
                    takeTurn(curTurn, ch.name)

示例输出:

======== Turn number 1:
It's Jimbo's turn
It's Crusher's turn
It's Bruiser's turn
It's Timmy's turn
======== Turn number 2:
It's Jimbo's turn
Oof! Crusher was KO'ed
It's Bruiser's turn
It's Timmy's turn
======== Turn number 3:
It's Jimbo's turn
It's Bruiser's turn
It's Timmy's turn
======== Turn number 4:
It's Jimbo's turn
It's Bruiser's turn
It's Timmy's turn
======== Turn number 5:
It's Jimbo's turn
It's Bruiser's turn
It's Timmy's turn

我喜欢@constantstranger 的回答,但另一种实现此目的的简单方法是在游戏进行时使用 list.removelist.pop.

将每个玩家从列表中删除
class Char:
    def __init__(self, name, side, Spd):
        self.name=name
        self.side=side
        self.Spd=Spd

def take_turn(char):
    print(f"{char.name}'s turn...")
    char.Spd -= 1

hero = Char("Jimbo","good",4)
helplessSidekick = Char("Timmy","good",2)
thug1 = Char("Crusher","evil",3)
thug2 = Char("Bruiser","evil",3)

in_game_chars = [hero, thug1, thug2, helplessSidekick]
i = 0  # index of character to go first
while len(in_game_chars) > 0:
    i = i % len(in_game_chars)
    char = in_game_chars[i]
    take_turn(char)
    if char.Spd < 1:
        in_game_chars.pop(i)
    else:
        i += 1
print("Game over")

输出:

Jimbo's turn...
Crusher's turn...
Bruiser's turn...
Timmy's turn...
Jimbo's turn...
Crusher's turn...
Bruiser's turn...
Timmy's turn...
Jimbo's turn...
Crusher's turn...
Bruiser's turn...
Jimbo's turn...
Game over

无限遍历 Python 中项目列表的标准方法是 cycle iterable. Unfortunately, it does not allow items to be removed from the cycle after instantiation. So you have to rebuild the cycle iterator every time you change the list. And then you need a 在指定索引处以确保玩家的顺序不被打乱:

from itertools import cycle, islice

in_game_chars = [hero, thug1, thug2, helplessSidekick]
i = 0  # index of character to go first
while len(in_game_chars) > 0:
    for char in islice(cycle(in_game_chars), i, None):
        take_turn(char)
        if char.Spd < 1:
            i = in_game_chars.index(char)
            # Remove player
            in_game_chars.pop(i)
            break
print("Game over")

最后,您还可以使用 filterfilterfalse 有条件地 include/drop 列表中的项目:

in_game_chars = [hero, thug1, thug2, helplessSidekick]
while len(in_game_chars) > 0:
    in_game_chars = list(filter(lambda x: x.Spd > 0, in_game_chars))
    for char in in_game_chars:
        take_turn(char)
print("Game over")