Pętla, powtórzenie ostatniej komendy

0

Witam,
jestem początkującym programistą i jestem w trakcie pisania swojej pierwszej gry tekstowej.
Napotkałem problem z pętlą a mianowicie z poniższym kodem.

while gameLength > 0:

    gameAnswer = input("Do you want to move forward? \n")

    if gameAnswer == "yes":
        print("Great, lets see what is inside")
        drawnEvent = random.choices(eventList, eventProbability)[0]

        if drawnEvent == Event.Chest:
            drawnChest = random.choices(chestList, chestProbability)[0]
            goldAcquire = find_aprox_value(colorValue[drawnChest])
            print("You have find ", drawnChest.value, "inside was", goldAcquire, "gold")
            Gold = Gold + goldAcquire
            gameLength = gameLength - 1
        elif drawnEvent == Event.Monster:
            drawnMonster = random.choices(MonsterList, MonsterProbability)[0]
            print("Oh no, you have find", drawnMonster.value, "which has", monsterLife[drawnMonster],
                  "life .If you will defeat him, you will find great treasure.")
            eventAnswer = input(" What is your choice?(fight, run)")
            if eventAnswer == "fight":
                while monsterLife[drawnMonster] > 0:
                    weapon_hit(0)
                    if monsterLife[drawnMonster] > 0:
                        monster_hit()
                        if playerLife <= 0:
                            print("You died, your body will lay in chambers forever")
                            sys.exit(0)
                drawnPremiumChest = random.choices(PremiumChestList, PremiumChestProbability)[0]
                goldAcquire = find_aprox_value(colorValue[drawnPremiumChest])
                print("Congratulations, you have defeat a monster, and you found", drawnPremiumChest.value,
                      ", inside was", goldAcquire, " gold")
                Gold = Gold + goldAcquire
                gameLength = gameLength - 1
            elif eventAnswer == "run":
                gameLength = gameLength - 1
                print("you have successfully run")
            else:
                print("Only options is run or fight")


w chwili obecnej w momencie spotkania potwora i wyboru innej opcji niż run lub fight, program cofa mnie na sam początek pętli z komunikatem "do you want to move forward".
Chciałbym, żeby po wyborze złej komendy nie dochodziło znowu do losowania zdarzenia, tylko, żeby program znowu zapytał mnie czy chce walczyć czy uciec.
Będę bardzo wdzięczny za pomoc.

Pozdrawiam

6

Podstawowa sprawa - te zagnieżdżone IF'y oraz elif to zło. Zamiast szukać przyczyny, dlaczego program się zachowuje tak, jak się zachowuje - sugeruję lekką jego zmianę.

Czy kojarzysz, czym są funkcje? Jeśli nie - przeczytaj proszę te artykuły - https://www.learnpython.org/pl/Funkcje oraz https://analityk.edu.pl/funkcje-w-python/

A potem, jak zrozumiesz o co chodzi w funkcjach, to postaraj się wydzielić poszczególne fragmenty do funkcji tak, aby całość miała kształt w stylu:

if drawnEvent == Event.Chest:
  zrob_cos_tam_z_Chest()

Wtedy łatwiej Ci będzie zrozumieć cały przepływ sterowania przez program. Bo to, że teraz coś Ci gdzieś przeskakuje do momentu, którego nie planowałeś oznacza jednoznacznie, że nie masz kontroli nad kolejnością wykonywania poszczególnych fragmentów kodu/nie panujesz nad tym, co się w aplikacji dzieje. A wynika to w mojej ocenie z tego, że taki blok kodu jaki pokazałeś w swoim pierwszym poście jest totalnie nieczytelny i mega łatwo (nawet osobie doświadczonej) się w tym zakręcić/pogubić/coś przeoczyć (a do tego jakiekolwiek zmiany w takim rozbudowanym IF'ie to jak chodzenie po polu minowym). Rzuć okiem także na ten wątek - Czy zagnieżdżone ify to zawsze zło?

Do tego taka druga uwaga - postaraj się nie mieszać logiki z "efektami"/zachowaniem/działaniem aplikacji. Nie wiem, jak to wytłumaczyć w prostych słowach - ale u Ciebie jest taki miks. Masz z jednej strony ten blok z zagnieżdżoną drabinką IF'ów, z drugiej strony, gdzieś pomiędzy różnymi sprawdzeniami masz powciskane jakieś print(). Jakbyś miał to porozbijane na funkcje, to mógłbyś uniknąć takich mieszanek.

0

Dzięki za uwagę, czym są funkcje wiem, mam ich nawet napisanych kilka w tym programie. Postaram się zmienić kod według Twojej sugestii, jeśli dalej będę miał problemy to wrócę tu z ponownym pytaniem.
Pozdrawiam

1

Nie piszę w Pythonie, ale musisz zapętlić fragment w którym pobierasz od użytkownika wprowadzony tekst i sprawdzać, czy wpisał odpowiednią wartość

Rufus0407 napisał(a):
eventAnswer = ''

while eventAnswer != "fight" and eventAnswer != "run":
  eventAnswer = input(" What is your choice?(fight, run)")

if eventAnswer == "fight":
  # ...
elif eventAnswer == "run":
  # ...
3

bez konkretnych zmian

gameAnswer = input("Do you want to move forward? \n")

dodałbym funkcję pomocniczą until(cb, acceptedValues) - która będzie tak długo wywoływać cb aż wartość będzie z zakresu acceptedValues

def until(cb, acceptedValues):
   while True:
     v = cb()

     if v in acceptedValues:
       return v

W użyciu

gameAnswer = until(lambda: input("Do you want to move forward? \n"), ["yes", "no"])
2
def restrict_input(*acceptable):
    answer='\0'
    while answer not in acceptable:
        answer=input(f"What is your choice {acceptable}? ")
    return answer

answer=restrict_input('fight','run')
print(answer)
0

Ok, przerobiłem mój kod według sugestii i obecnie wygląda on tak. Jednak mam jeszcze jeden problem z którym nie potrafię sobie poradzić. Mianowicie potwory są losowane ze słownika monsterLife. Do każdego klucza jest przypisana wartość w postaci pkt życia. Jeśli dany potwór zostanie zabity, wartość klucza w słowniku nadpisuje się. Powoduje to, że jeśli ten sam rodzaj potwora wylosuje się przy kolejnym zdarzeniu, ma on od razu ujemną wartość życia. Co zmienić w kodzie, żeby wartości ze słownika nie były nadpisywane?

import random
import sys

from enum import Enum

playerDamage = 4
playerLife = 100
gameLength = 10
Gold = 0


def restrict_input(*acceptable):
    answer = ""
    while answer not in acceptable:
        answer = input(f"What is your choice {acceptable}? ")
    return answer


def chest_draw():
    global Gold
    global gameLength
    drawnChest = random.choices(chestList, chestProbability)[0]
    goldAcquire = find_aprox_value(colorValue[drawnChest])
    Gold = Gold + goldAcquire
    gameLength = gameLength - 1
    print("You have find ", drawnChest.value, "inside was", goldAcquire, "gold")


def find_aprox_value(value):
    lowestValue = 0.9 * value
    highestValue = 1.1 * value
    return random.randint(lowestValue, highestValue)


def weapon_hit(chance):
    if_hit = random.uniform(1, 100)
    if if_hit < chance:
        monsterLife[drawnMonster] = monsterLife[drawnMonster] - playerDamage
        print("You hit a monster and you dealt 4 damage. It has", monsterLife[drawnMonster], " life")
    else:
        print("You missed")


def monster_draw():
    global goldAcquire
    global Gold
    global gameLength
    print("Oh no, you have find", drawnMonster.value, "which has", monsterLife[drawnMonster],
          "life .If you will defeat him, you will find great treasure.")
    eventAnswer = restrict_input('fight', 'run')
    if eventAnswer == "fight":
        while monsterLife[drawnMonster] > 0:
            weapon_hit(70)
            if monsterLife[drawnMonster] > 0:
                monster_hit()
                if playerLife <= 0:
                    print("You died, your body will lay in chambers forever")
                    sys.exit(0)
        drawnPremiumChest = random.choices(PremiumChestList, PremiumChestProbability)[0]
        goldAcquire = find_aprox_value(colorValue[drawnPremiumChest])
        print("Congratulations, you have defeat a monster, and you found", drawnPremiumChest.value,
              ", inside was", goldAcquire, " gold")
        Gold = Gold + goldAcquire
        gameLength = gameLength - 1
    elif eventAnswer == "run":
        gameLength = gameLength - 1
        print("you have successfully run")
    else:
        print("Only options is run or fight")


def monster_hit():
    global playerLife
    monsterHit = monsterDamage[drawnMonster]
    playerLife = playerLife - monsterHit
    print("Monster did", monsterDamage[drawnMonster], "damage")
    print("You have ", playerLife, "life")


Event = Enum('Event', ['Chest', 'Monster'])
Chest = Enum('Chest', {'greenChest': 'zieloną skrzynię',
                       'blueChest': 'niebieską skrzynię',
                       'violetChest': 'fioletową skrzynię',
                       'orangeChest': 'pomarańczową skrzynię'
                       })
Monster = Enum('Monster', {'Rat': 'Szczura',
                           'Bat': 'Nietoperza',
                           'GiantSpider': 'Ogromnego Pająka',
                           'Wolf': 'Wilka',
                           })

Color = Enum('Color', ['greenChest', 'blueChest', 'violetChest', 'orangeChest'])
MonsterKind = Enum('MonsterKind', ['Rat', 'Bat', 'GiantSpider', 'Wolf'])

eventDictionary = {

    Event.Chest: 0.4,
    Event.Monster: 0.6
}

eventList = list(eventDictionary.keys())
eventProbability = list(eventDictionary.values())

chestDictionary = {
    Chest.greenChest: 0.5,
    Chest.blueChest: 0.3,
    Chest.violetChest: 0.15,
    Chest.orangeChest: 0.05
}
PremiumChestDictionary = {
    Chest.blueChest: 0.5,
    Chest.violetChest: 0.35,
    Chest.orangeChest: 0.15
}

MonsterDictionary = {
    Monster.Rat: 0.5,
    Monster.Bat: 0.3,
    Monster.GiantSpider: 0.15,
    Monster.Wolf: 0.05
}

chestList = list(chestDictionary.keys())
chestProbability = list(chestDictionary.values())

MonsterList = list(MonsterDictionary.keys())
MonsterProbability = list(MonsterDictionary.values())

PremiumChestList = list(PremiumChestDictionary.keys())
PremiumChestProbability = list(PremiumChestDictionary.values())

colorValue = {
    Chest.greenChest: 1000,
    Chest.blueChest: 4000,
    Chest.violetChest: 9000,
    Chest.orangeChest: 16000
}
monsterLife = {
    Monster.Rat: 5,
    Monster.Bat: 10,
    Monster.GiantSpider: 15,
    Monster.Wolf: 30
}
monsterDamage = {
    Monster.Rat: 3,
    Monster.Bat: 5,
    Monster.GiantSpider: 8,
    Monster.Wolf: 12
}

while gameLength > 0:

    gameAnswer = input("Do you want to move forward? \n")

    if gameAnswer == "yes":
        print("Great, lets see what is inside")
        drawnEvent = random.choices(eventList, eventProbability)[0]

        if drawnEvent == Event.Chest:
            chest_draw()

        elif drawnEvent == Event.Monster:
            drawnMonster = random.choices(MonsterList, MonsterProbability)[0]
            monster_draw()
    else:
        print("Your only options is move forward")

print("Congratulations you have acquired", Gold, "gold")


1

Tego:

    else:
        print("Only options is run or fight")

już nie potrzebujesz.

1 użytkowników online, w tym zalogowanych: 0, gości: 1