我有大量的If语句列表,并想清理我的代码

时间:2019-03-25 09:09:28

标签: python python-3.x pygame

这是学习编码的第4天,我对一些基础知识仍然有些困惑。它具有pygame,pygame.text,所以本质上我的代码看起来像这样。

#Mouse click to get mouse Position
    if event.type == pygame.MOUSEBUTTONDOWN:
        if gamestage == 0 and gamestage <= 1:
            gamestage += 1
            mx, my =pygame.mouse.get_pos()
        #Total rectangle dimentions mx>806 and mx<889 and my>890 and my<920
        #Clickable squares for Shots and Team
        #Use print function if bug arises
            if mx>848 and mx<889 and my>890 and my<920:

                #numberonscreen_x=859
                #numberonscreen_y=905
                n+=1
                print(n)
                n=str(n)
                text_surface, rect = gamefont.render(n,(4, 8, 18))
                n=int(n)
                screen.blit(board,(0,0))
                pygame.display.flip()

            if mx>806 and mx<848 and my>890 and my<920:
                print("Pass")
            if mx>764 and mx<806 and my>890 and my<920:
                print("Pass")
            if mx>722 and mx<764 and my>890 and my<920:
                print("Pass")
            if mx>680 and mx<722 and my>890 and my<920:
                print("Pass")
            if mx>638 and mx<680 and my>890 and my<920:
                print("Pass")
            if mx>596 and mx<638 and my>890 and my<920:
                print("Pass")
            if mx>554 and mx<596 and my>890 and my<920:
                print("Pass")
            if mx>512 and mx<554 and my>890 and my<920:
                print("Pass")
            if mx>470 and mx<512 and my>890 and my<920:
                print("Pass")
            if mx>428 and mx<470 and my>890 and my<920:
                print("Pass")
            if mx>386 and mx<428 and my>890 and my<920:
                print("Pass")
            if mx>344 and mx<386 and my>890 and my<920:
                print("Pass")
            if mx>302 and mx<344 and my>890 and my<920:
                print("Pass")
            if mx>260 and mx<302 and my>890 and my<920:
                print("Pass")
            if mx>218 and mx<260 and my>890 and my<920:
                print("Pass")
            if mx>176 and mx<218 and my>890 and my<920:
                print("Pass")
            if mx>134 and mx<176 and my>890 and my<920:
                print("Pass")
    if event.type == pygame.MOUSEBUTTONUP:
        if gamestage != 0:
            gamestage = 0

    #Press 0 set given on screen button to zero
    if event.type == pygame.KEYDOWN and event.key == pygame.K_0:
        mx, my =pygame.mouse.get_pos()
        if mx>848 and mx<889 and my>905 and my<920:
            n=0
            print(n)
        if mx>806 and mx<848 and my>905 and my<920:
            print("Pass1")
        if mx>764 and mx<806 and my>905 and my<920:
            print("Pass1")
        if mx>722 and mx<764 and my>905 and my<920:
            print("Pass1")
        if mx>680 and mx<722 and my>905 and my<920:
            print("Pass1")
        if mx>638 and mx<680 and my>905 and my<920:
            print("Pass1")
        if mx>596 and mx<638 and my>905 and my<920:
            print("Pass1")
        if mx>554 and mx<596 and my>905 and my<920:
            print("Pass1")
        if mx>512 and mx<554 and my>905 and my<920:
            print("Pass1")
        if mx>470 and mx<512 and my>905 and my<920:
            print("Pass1")
        if mx>428 and mx<470 and my>905 and my<920:
            print("Pass1")
        if mx>386 and mx<428 and my>905 and my<920:
            print("Pass1")
        if mx>344 and mx<386 and my>905 and my<920:
            print("Pass1")
        if mx>302 and mx<344 and my>905 and my<920:
            print("Pass")
        if mx>260 and mx<302 and my>905 and my<920:
            print("Pass1")
        if mx>218 and mx<260 and my>905 and my<920:
            print("Pass1")
        if mx>176 and mx<218 and my>905 and my<920:
            print("Pass1")
        if mx>134 and mx<176 and my>905 and my<920:
            print("Pass1")

看起来真的很糟糕。我正在制作一个垄断游戏,并且为每个属性添加2个屏幕按钮。意味着将有100多种不同的(mx,my)集。仅基于查看其他人的代码,它看起来效率很低。由于董事会中会有许多不同的可点击部分,因此我需要找到一种方法来使它更加有效和易于阅读。

尽管有人“随便做”会很好,但我还是希望通过很多链接做出回应。使用这种方法,我还需要100个具有不同名称的text_surfaces,以及100个不同的变量n。我的思维过程是制作一些东西来存储所有n,text_surfaces并调用它。但是我真的不知道该怎么做,怎么称呼它以及它是否从“导入”中起作用。

2 个答案:

答案 0 :(得分:2)

您可以初始化一个mx范围的数组:

mx_ranges = [
    (806,848),
    (764,806),
    (722,764),
    (680,722),
    (638,680),
    (596,638),
    (554,596),
    (512,554),
    (470,512),
    (428,470),
    (386,428),
    (344,386),
    (302,344),
    (260,302),
    (218,260),
    (176,218),
    (134,176),
]

然后使用此函数代替那些“ if大块”中的每个块:

def check_mx_range(mx, min_my, max_my, result):
    for mx_range in mx_ranges:
        if mx_range[0] < mx < mx_range[1] and min_my < my < max_my:
            print(result)
            return True
    return False

答案 1 :(得分:2)

您缺少abstraction的某些级别。

让我们从pygame游戏的基本框架开始:

import pygame

def main():
    pygame.init()
    screen = pygame.display.set_mode((500, 500))
    screen_rect = screen.get_rect()
    sprites = pygame.sprite.Group()
    clock = pygame.time.Clock()
    rects = []
    dt = 0

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        sprites.update(dt, events)
        screen.fill(pygame.Color('darkgrey'))
        sprites.draw(screen)
        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

我们要实现的是Separation of concerns,所以让我们的主循环保持简洁。我们处理事件(主循环关心的唯一事件是QUIT),我们更新游戏状态(即名为sprites的精灵的Group),我们将内容绘制到屏幕上,我们将帧速率限制为Clock

因此,您说您有一个垄断委员会,那么让我们考虑一种表示这种情况的方法。让我们创建一个属性列表,每个属性都有一个颜色,一个名称和一个价格:

properties = (
    ('purple', 100, 'Oriental Avenue'),
    ('purple', 200, 'Vermont Avenue'),
    ('purple', 300, 'Connecticut Avenue'),
    ('white',  400, 'Atlantic Avenue'),
    ('white',  500, 'Ventnor Avenue'),
    ('white',  600, 'Marvin Gardens'),
    ('blue',   700, 'Park Place'),
    ('blue',   800, 'Boadwalk')
)

请注意,那只是一些数据的列表(实际上是元组的元组),因为我们想要Separation Of Data And Code

属性是游戏状态的一部分。让我们创建一个包含所有游戏状态的类,并为我们创建一些sprites,用于将内容绘制到屏幕上。此类还将计算每个精灵的位置。

class Board:
    def __init__(self, properties, font):
        self.properties = properties
        self.sprites = []

        side = len(properties) / 4 + 1
        size = (side * PROP_SIZE.width, side * PROP_SIZE.height)

        x, y = 0, 0
        flow = 'r'
        for prop in properties:
            if flow == 'r':
                if x == side - 1:
                    flow = 'd'
                else:
                    x += 1

            if flow == 'd':
                if y == side - 1:
                    flow = 'l'
                else:
                    y += 1

            if flow == 'l':
                if x == 0:
                    flow = 'u'
                else:
                    x -= 1

            if flow == 'u':
                y -= 1

            self.sprites.append(Property(*prop, (x*PROP_SIZE.width, y*PROP_SIZE.height), font))

我们希望每个属性都有两个按钮,所以让我们创建一个精灵类Property来处理事件检查是否使用:

class Property(pygame.sprite.Sprite):
    def __init__(self, color, price, name, pos, font):
        super().__init__()
        self.image = pygame.Surface(PROP_SIZE.size)
        self.rect = self.image.get_rect()
        pygame.draw.rect(self.image, (0, 0, 0), self.rect)
        pygame.draw.rect(self.image, pygame.Color(color), self.rect.inflate(-2, -2))
        self.color = color
        self.price = price
        self.name = name

        font.render_to(self.image, (11, 21), name, pygame.Color('black'))
        font.render_to(self.image, (10, 20), name, pygame.Color('white'))

        self.buttons = {
            'A': pygame.Rect(10, 100, 100, 20),
            'B': pygame.Rect(10, 125, 100, 20),
        }

        self.rect.topleft = pos

    def update(self, dt, events):
        pos = pygame.mouse.get_pos()
        for button in self.buttons:
            hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
            pygame.draw.rect(self.image, pygame.Color('red' if hovered else 'darkgrey'), self.buttons[button])

        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                for button in self.buttons:
                    hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
                    if hovered:
                        print(f'{self.name} says: You clicked {button}')

我们使用了一些不错的pygame之类的东西,例如Rect类,它是inflatemovecollidepoint方法,因此我们不必自己计算位置/冲突。

这是完整的运行代码。你会得到的想法:

import pygame
import pygame.freetype

PROP_SIZE = pygame.Rect(0, 0, 120, 180)

class Property(pygame.sprite.Sprite):
    def __init__(self, color, price, name, pos, font):
        super().__init__()
        self.image = pygame.Surface(PROP_SIZE.size)
        self.rect = self.image.get_rect()
        pygame.draw.rect(self.image, (0, 0, 0), self.rect)
        pygame.draw.rect(self.image, pygame.Color(color), self.rect.inflate(-2, -2))
        self.color = color
        self.price = price
        self.name = name

        font.render_to(self.image, (11, 21), name, pygame.Color('black'))
        font.render_to(self.image, (10, 20), name, pygame.Color('white'))

        self.buttons = {
            'A': pygame.Rect(10, 100, 100, 20),
            'B': pygame.Rect(10, 125, 100, 20),
        }

        self.rect.topleft = pos

    def update(self, dt, events):
        pos = pygame.mouse.get_pos()
        for button in self.buttons:
            hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
            pygame.draw.rect(self.image, pygame.Color('red' if hovered else 'darkgrey'), self.buttons[button])

        for event in events:
            if event.type == pygame.MOUSEBUTTONDOWN:
                for button in self.buttons:
                    hovered = self.buttons[button].move(*self.rect.topleft).collidepoint(pos)
                    if hovered:
                        print(f'{self.name} says: You clicked {button}')

class Board:
    def __init__(self, properties, font):
        self.properties = properties
        self.sprites = []

        side = len(properties) / 4 + 1
        size = (side * PROP_SIZE.width, side * PROP_SIZE.height)

        x, y = 0, 0
        flow = 'r'
        for prop in properties:
            if flow == 'r':
                if x == side - 1:
                    flow = 'd'
                else:
                    x += 1

            if flow == 'd':
                if y == side - 1:
                    flow = 'l'
                else:
                    y += 1

            if flow == 'l':
                if x == 0:
                    flow = 'u'
                else:
                    x -= 1

            if flow == 'u':
                y -= 1

            self.sprites.append(Property(*prop, (x*PROP_SIZE.width, y*PROP_SIZE.height), font))


def main():
    pygame.init()
    screen = pygame.display.set_mode((800, 600))
    screen_rect = screen.get_rect()

    font = pygame.freetype.SysFont(None, 14)
    font.origin = True

    properties = (
        ('purple', 100, 'Oriental Avenue'),
        ('purple', 200, 'Vermont Avenue'),
        ('purple', 300, 'Connecticut Avenue'),
        ('white',  400, 'Atlantic Avenue'),
        ('white',  500, 'Ventnor Avenue'),
        ('white',  600, 'Marvin Gardens'),
        ('blue',   700, 'Park Place'),
        ('blue',   800, 'Boadwalk')
    )

    board = Board(properties, font)
    sprites = pygame.sprite.Group(*board.sprites)
    clock = pygame.time.Clock()
    rects = []
    dt = 0

    while True:
        events = pygame.event.get()
        for e in events:
            if e.type == pygame.QUIT:
                return

        sprites.update(dt, events)
        screen.fill(pygame.Color('darkgrey'))
        sprites.draw(screen)
        pygame.display.update()
        dt = clock.tick(60)

if __name__ == '__main__':
    main()

enter image description here