python - 如何处理许多几乎相同的 if 语句?

标签 python function loops if-statement

我需要帮助。我是编码新手,所以我用 pygame 开发了一个游戏。 这是一款你作为机器人对抗僵尸的游戏。如果火球与僵尸相撞,心脏图片会从填充更新为一半,依此类推。

Tech-Lead 说这段代码效率不高,因为 Enemy 类的 defhearts() 方法中有很多 if 语句。

你能帮我缩短一下吗?我完全不知道我能做什么。想到了循环,但不知道怎么做。请帮助我

这是我的代码:

#pygame importieren
import pygame

#pygame initialisieren
pygame.init()

#Konstante für die Farben initialisieren
WHITE   = [0xFF, 0xFF, 0xFF]
ORANGE  = [0xFF, 0x8C, 0x00]
RED     = [0xFF, 0x00, 0x00]
GREEN   = [0x00, 0xFF, 0x00]
BLUE    = [0x00, 0x00, 0xFF]
BLACK   = [0x00, 0x00, 0x00]

#Hintergrundbilder und Sounds einer Variablen zuweisen
background      = pygame.image.load("Grafiken/hintergrund.jpg")
attackLeft      = pygame.image.load("Grafiken/angriffLinks.png")
attackRight     = pygame.image.load("Grafiken/angriffRechts.png")
jumping         = pygame.image.load("Grafiken/sprung.png")
going_right     = [pygame.image.load("Grafiken/rechts1.png"), pygame.image.load("Grafiken/rechts2.png"), pygame.image.load("Grafiken/rechts3.png"), pygame.image.load("Grafiken/rechts4.png"), pygame.image.load("Grafiken/rechts5.png"), pygame.image.load("Grafiken/rechts6.png"), pygame.image.load("Grafiken/rechts7.png"), pygame.image.load("Grafiken/rechts8.png")]
going_left      = [pygame.image.load("Grafiken/links1.png"), pygame.image.load("Grafiken/links2.png"), pygame.image.load("Grafiken/links3.png"), pygame.image.load("Grafiken/links4.png"), pygame.image.load("Grafiken/links5.png"), pygame.image.load("Grafiken/links6.png"), pygame.image.load("Grafiken/links7.png"), pygame.image.load("Grafiken/links8.png")]
jumping_sound   = pygame.mixer.Sound("Sound/sprung.wav")
shooting_sound  = pygame.mixer.Sound("Sound/shoot.mp3")
#Fenster erstellen
screen = pygame.display.set_mode([1280, 800])

#Fenstertitel erstellen
pygame.display.set_caption("Mein erstes pygame-Spiel")

#Spielerklasse
class Spieler:
    def __init__(self, x, y, speed, jump, player_width, player_height, direction, steps_left, steps_right):
        self.x = x
        self.y = y
        self.speed = speed
        self.jump = jump
        self.player_width = player_width
        self.player_height = player_height
        self.direction = direction
        self.steps_left = steps_left
        self.steps_right = steps_right
        #Springt er?
        self.sprung = False
        #Anfangsposition des Spielers
        self.lastPosition = [1, 0]
        #Schießbereitschaft
        self.ready2shoot = True
    
    #Eine Methode zum nach links und nach rechts laufen
    def walking(self, liste):
        if liste[0]:
            #Index 0 des Arrays direction ist Links. Wenn nach Links, dann Position des Spielers auf x - Geschwindigkeit
            self.x -= self.speed
            self.direction = [1, 0, 0, 0]
            self.steps_left += 1
        if liste[1]:
            #Index 1 des Arrays direction ist Rechts. Wenn nach Rechts, dann Position des Spielers auf x + Geschwindigkeit
            self.x += self.speed
            self.direction = [0, 1, 0, 0]
            self.steps_right += 1
    
    #Schritte werden zurückgesetzt
    def resetsteps(self):
        self.steps_left = 0
        self.steps_right = 0
    
    #Index 3 des Arrays direction ist stehen. Wenn stehen, dann werden die Schritte zurückgesetzt
    def standing(self):
        self.direction = [0, 0, 1, 0]
        self.resetsteps()
    
    #Sprungmethode wenn die springen-Taste gedrückt wird
    def sprungsetzen(self):
        #Wenn der SPieler -16px springen will, ist die Sprungbereitschaft True.
        if self.jump == -16:
            self.sprung = True
            self.jump = 15
            pygame.mixer.Sound.play(jumping_sound)
    
    #Berechnung des Sprunges
    def springen(self):
        if self.sprung:
            self.direction = [0, 0, 0, 1]
            if self.jump >= -15:
                n = 1
                if self.jump < 0:
                    n = - 1
                self.y -= (self.jump**2)*0.15*n
                self.jump -= 1
            else:
                self.sprung = False
    
    #Die Erstellung des Spielers
    def spZeichnen(self):
        
        if self.steps_left == 63:
            self.steps_left = 0
        if self.steps_right == 63:
            self.steps_right = 0

        if self.direction[0]:
            screen.blit(going_left[self.steps_left//8], (self.x, self.y))
            self.lastPosition = [1, 0]
        if self.direction[1]:
            screen.blit(going_right[self.steps_right//8], (self.x, self.y))
            self.lastPosition = [0, 1]
        if self.direction[2]:
            if self.lastPosition[0]:
                screen.blit(attackLeft, (self.x, self.y))
            else:
                screen.blit(attackRight, (self.x, self.y))
        if self.direction[3]:
            screen.blit(jumping, (self.x, self.y))

class Enemy:
    def __init__(self, x, y, speed, player_width, player_height, direction, xMin, xMax):
        self.x = x
        self.y = y
        self.speed = speed
        self.player_width = player_width
        self.player_height = player_height
        self.direction = direction
        self.xMin   = xMin
        self.xMax   = xMax
        self.steps_left     = 0
        self.steps_right    = 0
        self.health = 12
        self.left_walk   = [pygame.image.load("Grafiken/l1.png"), pygame.image.load("Grafiken/l2.png"), pygame.image.load("Grafiken/l3.png"), pygame.image.load("Grafiken/l4.png"), pygame.image.load("Grafiken/l5.png"), 
        pygame.image.load("Grafiken/l6.png"), pygame.image.load("Grafiken/l7.png"), pygame.image.load("Grafiken/l8.png")]
        self.right_walk  = [pygame.image.load("Grafiken/r1.png"), pygame.image.load("Grafiken/r2.png"), pygame.image.load("Grafiken/r3.png"), pygame.image.load("Grafiken/r4.png"), pygame.image.load("Grafiken/r5.png"),
        pygame.image.load("Grafiken/r6.png"), pygame.image.load("Grafiken/r7.png"), pygame.image.load("Grafiken/r8.png")]
        self.health_full = pygame.image.load("Grafiken/voll.png")
        self.health_half = pygame.image.load("Grafiken/halb.png")
        self.health_zero = pygame.image.load("Grafiken/leer.png")
    
    def hearts(self):
        if self.health >= 2:
            screen.blit(self.health_full, (440, 75))
        if self.health >= 4:
            screen.blit(self.health_full, (500, 75))
        if self.health >= 6:
            screen.blit(self.health_full, (560, 75))
        if self.health >= 8:
            screen.blit(self.health_full, (620, 75))
        if self.health >= 10:
            screen.blit(self.health_full, (680, 75))
        if self.health == 12:
            screen.blit(self.health_full, (740, 75))
        
        if self.health == 1:
            screen.blit(self.health_half, (440, 75))
        if self.health == 3:
            screen.blit(self.health_half, (500, 75))
        if self.health == 5:
            screen.blit(self.health_half, (560, 75))
        if self.health == 7:
            screen.blit(self.health_half, (620, 75))
        if self.health == 9:
            screen.blit(self.health_half, (680, 75))
        if self.health == 11:
            screen.blit(self.health_half, (740, 75))
        
        if self.health == 0:
            screen.blit(self.health_zero, (440, 75))
        if self.health <= 2:
            screen.blit(self.health_zero, (500, 75))
        if self.health <= 4:
            screen.blit(self.health_zero, (560, 75))
        if self.health <= 6:
            screen.blit(self.health_zero, (680, 75))
        if self.health <= 8:
            screen.blit(self.health_zero, (680, 75))
        if self.health <= 10:
            screen.blit(self.health_zero, (740, 75))


    def enemy_zeichnen(self):
        if self.steps_left == 63:
            self.steps_left = 0
        if self.steps_right == 63:
            self.steps_right = 0

        if self.direction[0]:
            screen.blit(self.left_walk[self.steps_left//8], (self.x, self.y))
        if self.direction[1]:
            screen.blit(self.right_walk[self.steps_right//8], (self.x, self.y))
        
    def enemy_walking(self):
        self.x += self.speed
        if self.speed < 0:
            self.direction = [1, 0]
            self.steps_left += 1
        if self.speed > 0:
            self.direction = [0, 1]
            self.steps_right += 1

    def enemy_back_forth(self):
        if self.x > self.xMax:
            self.speed *= -1
        elif self.x < self.xMin:
            self.speed *= -1
        self.enemy_walking()

class FireBall:
    def __init__(self, spX, spY, fb_Direction, fb_radius, fb_color, speed):
        #Der Feuerball befindet sich auf der selben Position wie der Spieler
        self.x = spX
        self.y = spY
        #Feuerballrichtung nach Links, befindet sich immer 5px vom Spieler entfernt und bewegt sich *1,5 des speeds in - y-Richtung (-1 * speed)
        if fb_Direction[0]:
            self.x += 5
            self.speed = - 1 * speed * 1.5
        #Feuerballrichtung nach Rechts, befindet sich immer 90px vom Spieler entfernt und bewegt sich * 1,5 des speeds in y-Richtung
        elif fb_Direction[1]:
            self.x += 90
            self.speed = speed * 1.5
        #Feuerball ist 90px unter dem Spieler
        self.y += 90
        self.fb_radius = fb_radius
        self.fb_color = fb_color
    #Bewegung des Feuerballs
    def move(self):
        self.x += self.speed
    #Zeichnung des Feuerballs
    def fb_Zeichnen(self):
        pygame.draw.circle(screen, self.fb_color, (self.x, self.y), self.fb_radius, 0)

#Methode um Zeichnungen anzuzeigen
def show_player():
    screen.blit(background, (0,0))
    for f in fireball:
        f.fb_Zeichnen()

    spieler1.spZeichnen()
    zombie.hearts()
    zombie.enemy_zeichnen()
    zombie.hearts()
    pygame.display.flip()

#Verhalten vom Feuerball
def feuerkugeln():
    for f in fireball:
        if f.x >= 0 and f.x <= 1270:
            f.move()
        else:
            fireball.remove(f)

def collision():
    global fireball, win, loose, game_active
    zombieRect = pygame.Rect(spieler1.x+18,spieler1.y+36,spieler1.player_width-36, spieler1.player_height-36)
    
    player_rect = pygame.Rect(zombie.x+18,zombie.y+24,zombie.player_width-36, zombie.player_height-24)
    for f in fireball:
        fbRect = pygame.Rect(f.x-f.radius,f.y-f.radius,f.radius*2,f.radius*2)
        if zombieRect.colliderect(fbRect):
            fireball.remove(f)
            zombie.health -= 1
            if zombie.health <=0 and not verloren:
                gewonnen = True
                game_active = False
        
    if zombieRect.colliderect(player_rect):
        loose = True
        won = False
        game_active = False
        
#Grenzen erstellen
left_border     = pygame.draw.rect(screen, BLACK, [0, 0, 2, 800], 0)
right_border    = pygame.draw.rect(screen, BLACK, [1225, 0, 2, 800], 0)

#Klasse aufrufen
spieler1 = Spieler(300, 575, 5, -16, 30, 50, [0, 0, 1, 0], 0, 0)
zombie = Enemy(600, 575, 8, 30, 50, [0,0], 0, 1200)
loose = False
win = False
#fireball Array. Wieviele fireballs auf einmal auf dem Spielfeld sein können
fireball = []

#Bedingung für den Spielstart
game_active = True

#Bildschirmaktualisierung einstellen
clock = pygame.time.Clock()

#Hauptschleife des Spiels
while game_active:
    #Nutzeraktion überprüfen
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_active = False
    
    player_rect = pygame.Rect(spieler1.x, spieler1.y, spieler1.player_width, spieler1.player_height)
    
    pressed = pygame.key.get_pressed()

#Spielelogik wird berechnet (Bewegung der Figur, Kollision etc)
    #Ereignis wenn man sich nach links bewegt und auf die Grenze stößt
    if pressed[pygame.K_LEFT] and not player_rect.colliderect(left_border):
       spieler1.walking([1, 0])
    #Ereignis wenn man sich nach rechts bewegt und auf die Grenze stößt
    elif pressed[pygame.K_RIGHT] and not player_rect.colliderect(right_border):
        spieler1.walking([0, 1])
    #Ereignis wenn keine Taste gedrückt wird
    else:
        spieler1.standing()

    #Ereignis wenn die Sprung-Taste gedrückt wird
    if pressed[pygame.K_UP]:
        spieler1.sprungsetzen()

    #Ereignis wenn die Space-Taste gedrückt wird
    if pressed[pygame.K_SPACE]:
        #Solange 5 oder weniger Feuerbälle im fireball Array sind und der Spieler schießt, nimmt der Array um einen Index zu.
        if len(fireball) <= 4 and spieler1.ready2shoot:
            fireball.append(FireBall(spieler1.x, spieler1.y, spieler1.lastPosition, 8, RED, 7))
            pygame.mixer.Sound.play(shooting_sound)
        
        spieler1.ready2shoot = False

    if not pressed[pygame.K_SPACE]:
        spieler1.ready2shoot = True

    feuerkugeln()
    #Sprungvorgang
    spieler1.springen()
    #Die Anzeige vom Spieler
    show_player()
    zombie.hearts()
    #Die Anzeige vom Zombie
    zombie.enemy_back_forth()
    collision()
    #Framerate des Spiels
    clock.tick(60)

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_active = False
    show_player()
    
pygame.quit()

最佳答案

技术主管错了:您的代码按照其编写方式是非常高效的。缩短代码并不会使其更快或更“优雅”。

但是,较短的代码更容易维护和更改。只要心脏容器的数量始终恰好是 12,您的代码就可以。但是如果您想更改它(增加/减少游戏的难度,或者让玩家获得新的心脏容器),那么此代码将不会工作。它被硬编码为仅适用于 12 个心脏容器。

要更改此设置,请将此重复代码放入循环中。您需要查看数字变化的模式并为其创建一个小的数学公式。我想出了以下内容。 (我还添加了常量而不是整数文字,以便代码更易于阅读和更改。)

MAX_HEALTH = 12
LEFTMOST_HEART = 440
TOPMOST_HEART = 75
HEART_HALF_WIDTH = 30

def hearts(self):
    # Draw all the full hearts:
    for i in range(0, self.health, 2):
        screen.blit(self.health_full(LEFTMOST_HEART + (i * HEART_HALF_WIDTH), TOPMOST_HEART))

    # Draw the half-heart, if needed:
    if self.health % 2 == 1:
        screen.blit(self.health_half(LEFTMOST_HEART + ((i - 1) * HEART_HALF_WIDTH), TOPMOST_HEART))

    # Draw the empty hearts:
    for i in range(MAX_HEALTH, self.health, -2):
        screen.blit(self.health_zero(LEFTMOST_HEART + ((i - 2) * HEART_HALF_WIDTH), TOPMOST_HEART))        

此代码适用于任意数量的生命值(只要它是偶数)。您还可以通过更改 LEFMOST_HEARTTOPMOST_HEART 来更改心形的位置。

此代码与您的代码一样“高效”,但更容易维护,因为更改最大生命值或心脏位置只需要更改一些常量。

关于python - 如何处理许多几乎相同的 if 语句?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71432303/

相关文章:

python - pandas.read_json 导致 0xC0000005 错误

python - 如何按数字对 linux 中的文件进行排序?

Javascript:使用函数定义对象属性的值

javascript - 如何使用一个 Javascript 函数将数组中多张图片的大小加倍

vba - 如何使用 VBA 迭代 Word 中选定文本中的每个字符?

php - 如何在 PHP/MYSQL 中将两个 mysql 查询作为一个执行?

python - Python use re 中如何匹配这种字符串?

python - 如何从Python列表中获取不同的元素?

javascript - 一个(有点晦涩的)Javascript 继承问题

c - 具有 `for` 循环的菱形输出