2

タイトルが最もよく説明されているかどうかはわかりません。しかし、これが私の問題です。'Ball'という名前のクラスがあります。各ボールには、独自の幅、半径、色があります。ループの前に自分のボールを追加している間、私のコードはうまく機能しました。ball1 = Ball().... ball2 = Ball()pygameを使用しています。必要なのは、「スペース」を押すたびに、独自の特性を持つ別のボールが追加されるようにすることです。幅、半径、色がランダムに出るようにしています。これが私のコードです:

BLACK = (0,0,0)
WHITE = (255, 255, 255)
BLUE = (0, 0, 255)
RED = (255, 0, 0)
GREEN = (0, 255, 0)

fps = 30

color_list = [BLACK, BLUE, GREEN, RED]

col = None
siz = None
wit = None
posx = None
posy = None
ball = None


class Ball:

    ballCount = 0

    def __init__(self):
        Ball.ballCount +=1
        self.col = random.choice(color_list)
        self.siz = random.randint(20, 80)
        self.wit = random.randint(1, 3)
        self.posx = random.randint(self.siz, width-self.siz)
        self.posy = random.randint(self.siz, height-self.siz)

    def blitball(self):
        pygame.draw.circle(screen, self.col, (self.posx, self.posy),self.siz, self.wit)


    def move(self):
        self.posx+=1



ball2 = Ball()
ball1 = Ball()
ball3 = Ball()

while True:

    amount = 0



    event = pygame.event.poll()
    keys = pygame.key.get_pressed()

    if event.type == QUIT:
        pygame.quit()
        sys.exit()

    if keys[K_q]:
        pygame.quit()
        sys.exit()

    #############################################################

    if keys[K_SPACE]:
        eval("ball"+str(Ball.ballCount+1)) = Ball()

    #############################################################

    screen.fill(WHITE)

    for r in range(Ball.ballCount):
        amount+=1
        eval("ball"+str(amount)).move()
        eval("ball"+str(amount)).blitball()


    pygame.time.wait(int(1000/fps))

    pygame.display.update()

を使用for r in range(Ball.ballCount):しているので、ボールごとに関数を入力する必要はありません。これは完全に機能します。もっと簡単な方法を知っているなら、私に知らせてください。

したがって、追加する必要があるのは次のとおりです。

if keys[K_SPACE]:  
    #add another ball, ball3, ball4,..etc. 

これが私のコードの一部を変更することを意味する場合は、遠慮なく私に教えてください。よろしくお願いします。(ハッシュタグ内に問題があります)

デニス

4

2 に答える 2

3

あなたのボールをリストに保存し、そこで行動します

# starting three balls
balls = [Ball(),Ball(),Ball()]

while True:
    amount = 0

    event = pygame.event.poll()
    keys = pygame.key.get_pressed()

    if event.type == QUIT:
        pygame.quit()
        sys.exit()

    if keys[K_q]:
        pygame.quit()
        sys.exit()

    #############################################################

    if keys[K_SPACE]:
        balls.append(Ball())

    #############################################################

    screen.fill(WHITE)

    for ball_in_play in balls:
        ball_in_play.move()
        ball_in_play.blitball()


    pygame.time.wait(int(1000/fps))

    pygame.display.update()
于 2013-02-15T18:33:28.627 に答える
2

名前で新しい変数を作成することはほとんどありません。

evalまた、まれに実行する場合でも、またはで実行することはほとんどありませんexec

evalまた、 orを使用したい場合でも、デフォルトの/execでそれらを使用することはほとんどありません。localsglobals

しかし、最初にコードが機能しない理由を見てから、それを改善する方法を見てみましょう。

eval("ball"+str(Ball.ballCount+1)) = Ball()

のような文字列を生成し"ball4"、それを呼び出しevalています。当然のことながら、これは string に評価されます"ball4"。次に、変数ではなくその文字列に新しい値 (新しく構築されたインスタンス) を割り当てようとしてBallいますが、明らかにそれは機能しません。SyntaxError(実際には、何かが評価される前に、関数呼び出しに代入しようとするための が得られると思います。)

それを修正するには、すべてを内部に配置する必要がありますeval

eval("ball"+str(Ball.ballCount+1) + " = Ball()")

しかし、evalステートメントではなく式に対してのみ機能するため、それは機能しません。ステートメントには、次のものが必要ですexec

exec("ball"+str(Ball.ballCount+1) + " = Ball()")

そして、それはあなたのエラーを取り除きます。

ball4しかし、変数を作成する正しい方法を見てみましょう:

locals()["ball" + str(Ball.ballCount+1)] = Ball()

間違いを犯すのははるかに簡単で困難です。

しかし、それがわかったら、任意の名前で anyを使用できるのにlocals()、わざわざ を使用する必要はありません。dictdict

my_balls["ball" + str(Ball.ballCount+1)] = Ball()

そして、一度それをしたら、それぞれに「ボール」プレフィックスは必要ありません:

my_balls[Ball.ballCount+1] = Ball()

そしてその時点で、キーが単なる自然数であることに気付くlistかもしれdictません。my_ballslist

そして、Ball.ballCountもう必要ありませんlen(my_balls)

evalでは、 andを使用することの何が悪いのexecでしょうか?

それは効率が悪く、コードのデバッグ (およびインタラクティブ ターミナルでの実験) が難しくなり、巨大なセキュリティ ホールが開いてしまいます (ユーザーに次のボール番号を尋ねたところ、"3 ; os.system('rm -rf /'); _ "そしてあなたはしようとしましたexec("Ball" + user_input_string + " = Ball()"))。

しかし、それはすべて、コードが読みにくくなるという事実に比べれば何でもありません。比較:

eval("ball"+str(amount)).move()

balls[amount].move()
于 2013-02-15T18:38:05.107 に答える