全局变量设置问题

Issue with a global variable setting

程序应该在玩家每次得分时更新全局变量的值int_choice(这是乒乓球游戏)

int_choice的值只能是1或0。如果是1,函数left_or_right "tells"小球向右,如果是0,小球向左.

int_choice 在几个地方更新:在开始时它被初始化,然后在 left_or_right() 函数中,然后在 draw() 函数中。

每次用户得分时,球应该从 table 的中心朝向该用户重生,但球总是在同一方向重生两次,然后在相反方向重生两次,依此类推,不管谁是最后一个进球。

代码如下:

import random

int_choice = random.randint(0,1)
direc = None

def left_or_right():
    global direc, int_choice
    if int_choice == 0:
        direc = "LEFT"
    elif int_choice == 1:
        direc = "RIGHT"
    return direc

def spawn_ball(direction):
    left_or_right()
    global ball_pos, ball_vel # these are vectors stored as lists
    ball_pos = [WIDTH / 2, HEIGHT / 2]
    if direction == "LEFT":
        ball_vel[0] = (random.randrange(12, 25)*(-0.1))
        print "Velocity[0]: ", ball_vel[0]
        ball_vel[1] =  (random.randrange(6, 19)*(-0.1))
    elif direction == "RIGHT":
        ball_vel[0] = (random.randrange(12, 25)*(0.1))
        print "Velocity[0]: ", ball_vel[0]
        ball_vel[1] =  (random.randrange(6, 19)*(-0.1))
        print "Velocity[1]: ", ball_vel[1]

def new_game():
    global paddle1_pos, paddle2_pos, paddle1_vel, paddle2_vel, direc
    global score1, score2, 
    spawn_ball(direc)
    score1 = 0
    score2 = 0

def draw(canvas):
    global remaining_names, score1, score2, paddle1_pos, paddle2_pos,          ball_pos, ball_vel, BALL_RADIUS, direc
    global int_choice


    # update ball
    ball_pos[0] += ball_vel[0]
    ball_pos[1] += ball_vel[1]
    if ball_pos[1] - BALL_RADIUS <= 0:
        ball_vel[1] = ball_vel[1] + (ball_vel[1] * (-2))     
    elif ball_pos[1] + BALL_RADIUS >= HEIGHT:
        ball_vel[1] = ball_vel[1] + (ball_vel[1] * (-2))
    elif ball_pos[0] - BALL_RADIUS <= (0 + PAD_WIDTH):
        if (ball_pos[1] > paddle1_pos) and (ball_pos[1] < (paddle1_pos + PAD_HEIGHT)):
            ball_vel[0] = ball_vel[0] + (ball_vel[0] * (-2.1))
        else:
            int_choice = 1
            spawn_ball(direc)
            score2 = score2 + 1

    elif (ball_pos[0] + BALL_RADIUS) >= (WIDTH - PAD_WIDTH):
        if (ball_pos[1] > paddle2_pos) and (ball_pos[1] < (paddle2_pos + PAD_HEIGHT)):
            ball_vel[0] = ball_vel[0] + (ball_vel[0] * (-2.1))
        else:
            int_choice = 0
            spawn_ball(direc)
            score1 = score1 + 1

您的问题存在是因为您在代码中错误的时间更新了变量。让我们看一个游戏结束后发生的例子。

int_choice = 0
spawn_ball(direc)

您将 int_choice 设置为 0,然后调用 spawn_ball(direc),但 direc 是 old 方向 - 它尚未更改, 只有 int_choice 有。所以现在 direc 已经绑定到 spawn_ball 函数中的 "direction" 变量。即使 spawn_ball 立即调用 left_or_right(),那将 仅更新方向,而不更新方向 ,这意味着 spawn_ball 将继续以相同的方向进行最初是传入的,无论对 left_or_right 的调用是什么。

快速的解决方案是

def spawn_ball(direction):
    direction = left_or_right()

这可能会解决该问题。但是,我建议您重构您的代码——这是非常糟糕的风格。像这样传递全局变量很容易出现这样的错误 - 使用通过函数调用传递的局部变量是一个更好的选择。

您在调用 left_or_right 之前传入 direc 值。

比如说,你将 int_cohice 设置为 1:

int_choice = 1
spawn_ball(direc)  # old value of `direc`, nothing changed this yet

然后在 spawn_ball():

def spawn_ball(direction):
    left_or_right()

所以 direction 设置为 old 值,但 left_or_right() 将其设置为 new 值,然后在 spawn_ball() 完全忽略 。您在整个函数中使用 direction

快速修复是使用 left_or_right() 的 return 值;或者使用 direc 全局。由于两者都对全局变量进行操作,因此在此处传递 direc 没有意义:

int_choice = 1
spawn_ball()  # don't pass anything in

def spawn_ball():
    direction = left_or_right()

但是,更好的方法是始终 传递一个方向,并完全移除(双)全局变量。

只要传入一个数字,你可以给这个数字起符号名:

LEFT, RIGHT = 0, 1  # symbolic names for direction

def spawn_ball(direction):
    ball_pos = [WIDTH / 2, HEIGHT / 2]
    if direction == LEFT:  # using the global symbolic name
        return ball_pos, [
            random.randrange(12, 25)*(-0.1),
            random.randrange(6, 19)*(-0.1)]
    else:   # naturally the other option is going to be RIGHT
        return ball_pos, [
            random.randrange(12, 25)*(0.1)
            random.randrange(6, 19)*(-0.1)]

注意函数returns新的小球位置和速度;调用函数时存储结果:

ball_pos, ball_vel = spawn_ball(direction)

也许 draw 函数仍然将它们视为全局变量,但这至少不再是 spawn_ball() 函数的问题。

现在您需要做的就是将一个 local 变量设置为 LEFTRIGHT 以生成球并将该变量传递给函数.