Python 为什么此代码中有;“球”;似乎沿着边缘滑动

Python 为什么此代码中有;“球”;似乎沿着边缘滑动,python,Python,我儿子问我是否可以写一个小程序,让球在屏幕上弹起,然后让我解释一下。 看到一个整洁的父子机会,我说“是的,没问题”。所以我挖掘了我的python技能并写了这个 #!/usr/bin/python # # We have to tell python what stuff we're # going to use. We do this by asking to import # the code we'll be making use of # import curses import ran

我儿子问我是否可以写一个小程序,让球在屏幕上弹起,然后让我解释一下。 看到一个整洁的父子机会,我说“是的,没问题”。所以我挖掘了我的python技能并写了这个

#!/usr/bin/python

#
# We have to tell python what stuff we're
# going to use. We do this by asking to import
# the code we'll be making use of
#
import curses
import random
import time

#
# We'll be using a screen handling
# package called "curses" so we need
# to initialise the screen
stdscr = curses.initscr()

# We need to make sure that
# keys we type will not show up
# on the screen spoiling the
# stuff we're drawing
curses.noecho()

# We need to tell curses that we don't
# want to wait when we ask for keys from
# the user, if there's non there then 
# we want curses to carry on
stdscr.nodelay( True )

# This ones a bit tricky to explain.
# Basically it puts the keyboard into
# a mode which allows curses to do
# things with it...
curses.cbreak()

# Ok, now we can do the fun stuff

# First thing we need to do is to
# find out how big our screen is
max_y, max_x = stdscr.getmaxyx()

stdscr.box()

min_x = 1
min_y = 1

max_y = max_y - 2
max_x = max_x - 2

stdscr.addstr( min_y, min_x, "1" )
stdscr.addstr( min_y, max_x, "2" )
stdscr.addstr( max_y, min_x, "3" )
stdscr.addstr( max_y, max_x, "4" )

dir_x = 1
dir_y = 1

# Then we can pick a random point on the
# screen in both the y (up-down) and x
# (left-right) directions
y = random.randint( 0, max_y )
x = random.randint( 0, max_x )

# Ok, this basically says, while trying to
# get a key from the user keeps coming back
# with an error, meaning there aren't any keys
# to return, do the code inside the loop
while( stdscr.getch() == curses.ERR ):
    # Ok, at the location we got, put a "0"
    stdscr.addstr( y, x, "O" )
    # stdscr.addstr( str( (y, x) ) )

    # this just moves the cursor to a new location so we can see the "O" better
    stdscr.move( 0, 0 )

    # have the screen update
    stdscr.refresh()

    # now choose a new location
    x = x + dir_x
    y = y + dir_y

    # have we gone too far
    if x > max_x or x < min_x:
        # change direction
        dir_x = -dir_x
        x = x + dir_x

    if y > max_y or y < min_y:
        # change direction
        dir_y = -dir_y
        y = y + dir_y

    # wait a bit so we can see the screen we've drawn.
    time.sleep( 0.05 )

# Ok, we're finished. Tidy up
curses.nocbreak()
stdscr.keypad( False )
curses.echo()
curses.endwin()
#/usr/bin/python
#
#我们必须告诉python我们在做什么
#将要使用。我们通过要求进口来实现这一点
#我们将使用的代码
#
进口诅咒
随机输入
导入时间
#
#我们将使用屏幕处理
#包名为“诅咒”,所以我们需要
#初始化屏幕
stdscr=curses.initscr()
#我们需要确保
#我们键入的密钥将不会显示
#在荧屏上破坏电视
#我们正在画的东西
诅咒
#我们需要告诉诅咒者我们不知道
#想等我们向你要钥匙吗
#用户,如果没有,那么
#我们希望诅咒继续下去
stdscr.nodelay(真)
#这个有点难以解释。
#基本上它把键盘放进
#一种允许诅咒的方式
#关于它的事情。。。
诅咒
#好了,现在我们可以做有趣的事情了
#我们需要做的第一件事就是
#了解我们的屏幕有多大
max_y,max_x=stdscr.getmaxyx()
stdscr.box()
最小值x=1
最小值y=1
max_y=max_y-2
max_x=max_x-2
stdscr.addstr(最小值y,最小值x,“1”)
标准附加值(最小值y,最大值x,“2”)
stdscr.addstr(最大值,最小值,“3”)
stdscr.addstr(最大值y,最大值x,“4”)
dir_x=1
dir_y=1
#然后我们可以在地图上随机选取一个点
#在y轴(上下)和x轴上显示屏幕
#(左-右)方向
y=random.randint(0,max_y)
x=random.randint(0,max_x)
#好的,这基本上是说,在试图
#从用户处获取密钥并不断返回
#出现错误,表示没有任何键
#要返回,请在循环中执行代码
而(stdscr.getch()==curses.ERR):
#好的,在我们找到的位置放一个“0”
stdscr.addstr(y,x,“O”)
#stdscr.addstr(str((y,x)))
#这只是将光标移动到一个新位置,以便我们可以更好地看到“O”
stdscr.move(0,0)
#更新屏幕
stdscr.refresh()
#现在选择一个新位置
x=x+dir\ux
y=y+dir\U y
#我们走得太远了吗
如果x>max\ux或xmax\u y或y
我负责这个项目,非常高兴。然而,当球击中边缘时,它似乎“滑动”,而不是干净地反弹

晚上已经很晚了,所以我想我应该把它扔出去,看看有没有人能解释一下原因。 我并不是在修复代码之后,我非常确定with=测试会起作用。我只是不明白它做什么它做什么

Thx
标记。

您需要在“更改方向”代码中添加两次dir

不太熟悉python,但是

dir_x = -dir_x
可以接受吗?也许试试

dir_x *= -1


在测试之前,您正在计算一个新的x和y坐标。假设球在20,1,并且被画出来,假设方向是东北方向,坡度为1。下一个位置将在21,0处计算。在这里你可以看到y现在超出了范围。所以当你真正想要的是2的时候,你把它设置回1,这样你就得到了一个滑动的边缘。通常,我首先测试下一个条件,然后添加新的偏移。所以

if x + dir_x > max_x or x - dir_x < min_x:
如果x+dir\ux>max\ux或x-dir\ux
让这种模拟在边缘正常工作是一件棘手的事情。我在这里运行它,它看起来很不错(OSX)。当它击中边缘时,你会在边缘处得到两个连续的O,但随后它又回来了。据猜测,这与反转发生前虚拟x,y点必须穿透多远有关,这取决于它移动的速度。

我花了一段时间才明白你的意思。你是说当它改变方向时墙上的双“OO”字?在我看来,条件允许球越过(而不是向上)线,然后再把它拉回来。我改变了这一点:

# have we gone too far
if x >= max_x or x <= min_x:
    # change direction
    dir_x = -dir_x
    #x = x + dir_x

if y >= max_y or y <= min_y:
    # change direction
    dir_y = -dir_y
    #y = y + dir_y
我们走得太远了吗 如果x>=max\u x或x=max\u y或y to>=与<相同,我还注释掉了第二个增量-如果您在线路上捕捉到它,则不需要它。)


顺便说一下,这是一个很好的小例子。

这就是OP描述的问题。chrispy发布的答案是正确的解决方案。因此……对于那些已经做了这种模拟并自己遇到这些问题的下层选民,我仍然相信我的评论总体上是有效的,但不适用于这篇文章。原因是,这是一个玩具问题。此外,OP的描述不精确,动画没有“滑动”,沿边缘一行有2个,这可以通过@chrispy描述来解决,OP对答案的注释解释了为什么。啊!。。谢谢,我现在明白了。所以基本上,当我往一个方向加的时候,这个方向太远了,然后加上一个相反的方向,只会让我回到边缘。我需要增加两倍的“反弹”,这是克里斯皮建议的。。。我必须承认,你的“改变前测试”看起来比“神奇”的x=x+(2*dir_x)更优雅一些。。我试图将其付诸实践,我认为您的代码有点错误。在“x-dir_x# have we gone too far if x >= max_x or x <= min_x: # change direction dir_x = -dir_x #x = x + dir_x if y >= max_y or y <= min_y: # change direction dir_y = -dir_y #y = y + dir_y