全局变量设置问题
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 变量设置为 LEFT
或 RIGHT
以生成球并将该变量传递给函数.
程序应该在玩家每次得分时更新全局变量的值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 变量设置为 LEFT
或 RIGHT
以生成球并将该变量传递给函数.