简体   繁体   English

全局变量设置出现问题

[英]Issue with a global variable setting

The program is supposed to update the value of the global variable int_choice every time a player scores (it's a pong game) 该程序应该在每次玩家得分时更新全局变量int_choice的值(这是一个乒乓球游戏)

int_choice can only have a value of 1 or 0. If it's 1, the function left_or_right "tells" the ball to go right, if it's 0, the ball goes left. int_choice的值只能为1或0。如果为1,则函数left_or_right “告诉”球向右移动,如果为0,则球向左移动。

int_choice is updated in few places: at the beginning it's initialized, then in the left_or_right() function, then in the draw() function. int_choice在几个地方进行了更新:首先将其初始化,然后在left_or_right()函数中,然后在draw()函数中。

Every time the user scores, the ball should be respawned from the centre of the table towards that user, but the ball always respawns twice in the same direction and then twice in the opposite direction and so on, regardless of who was the last one to score. 每次用户得分时,都应从桌子的中心向该用户重生该球,但是该球总是在相同方向上重生两次,然后在相反方向上重生两次,依此类推,无论谁是最后一个得分。

Here's the code: 这是代码:

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

You pass in the old value of direc , before left_or_right is called. 您传递的direc ,前left_or_right被调用。

Say, you set int_cohice to 1: 假设您将int_cohice设置为1:

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

then in spawn_ball() : 然后在spawn_ball()

def spawn_ball(direction):
    left_or_right()

so direction is set the old value, but left_or_right() sets it to a new value, which is then entirely ignored in spawn_ball() . 因此将direction设置为值,但是left_or_right()将其设置为值,然后在spawn_ball()完全忽略 You use direction throughout the function. 您可以在整个功能中使用direction

The quick fix is to use the return value of left_or_right() ; 快速的解决方法是使用left_or_right()的返回值; or use the direc global. 或使用direc全局。 Since either operates on globals, there is no point in passing in direc here: 由于任何一个都在全局变量上运行,因此在这里传递direc是没有意义的:

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

and

def spawn_ball():
    direction = left_or_right()

However, the better way is to always pass in a direction, and completely remove the (double) globals. 但是,更好的方法是始终朝一个方向传递,并完全删除(双精度)全局变量。

Just pass in a number, you can give that number symbolic names: 只需传递一个数字,即可为该数字提供符号名称:

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)]

Note that the function returns new ball positions and velocity; 注意,该函数返回新的球的位置和速度。 store the result when you call the function: 调用函数时存储结果:

ball_pos, ball_vel = spawn_ball(direction)

Perhaps the draw function still treats these as globals, but that's no longer a concern for the spawn_ball() function at the very least. 也许draw函数仍然将它们视为全局变量,但这至少不再是spawn_ball()函数的问题。

Now all you need to do is set one local variable to either LEFT or RIGHT to spawn a ball and pass that variable into the function. 现在,您需要做的就是将一个局部变量设置为LEFTRIGHT来生成一个球并将该变量传递给函数。

Your problem exists because you update the variable at the wrong time in your code. 存在问题是因为您在错误的时间在代码中更新了变量。 Let's look at an example of what happens after a game ends. 让我们看一个游戏结束后发生的例子。

int_choice = 0
spawn_ball(direc)

You set int_choice to 0, then you call spawn_ball(direc), but direc is the old direction - it hasn't changed yet, only int_choice has. 您将int_choice设置为0,然后调用spawn_ball(direc),但是direc是旧的方向-尚未改变,只有int_choice改变了。 So now direc has been bound to the "direction" variable in your spawn_ball function. 因此,现在direc已绑定到spawn_ball函数中的“ direction”变量。 Even though spawn_ball immediately calls left_or_right(), that will only update direc, not direction , meaning that spawn_ball will continue with the same direction it was originally passed in, no matter what the call to left_or_right did. 即使spawn_ball立即调用left_or_right(),这只会更新 direc ,而不更新direction ,这意味着spawn_ball将继续沿其最初传递的方向前进,无论对left_or_right的调用是什么。

The quick solution would be to say 快速的解决方案是说

def spawn_ball(direction):
    direction = left_or_right()

Which will likely fix that problem. 这可能会解决该问题。 However, I would suggest you refactor your code quite a bit - it is very bad style. 但是,我建议您对代码进行大量重构-这是非常糟糕的样式。 Passing around global variables as you are is so prone to errors like this one - using locals passed around through function calls is a much better option. 照原样传递全局变量很容易发生这样的错误-使用通过函数调用传递的局部变量是一个更好的选择。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM