2012-07-03 49 views
0

我正在为终端写一个蛇游戏,即通过打印输出。基于终端的蛇游戏:输入线程操纵输出

下面的作品就好了:

while status[snake_monad] do 
    print to_string draw canvas, compose_all([ 
    frame, 
    specs, 
    snake_to_hash(snake[snake_monad]) 
    ]) 

    turn! snake_monad, get_dir 
    move! snake_monad, specs 

    sleep 0.25 
end 

但我不希望turn! ING阻止的,当然。所以我把它变成一个新的线程,并让它循环:

Thread.new do 
    loop do 
    turn! snake_monad, get_dir 
    end 
end 

while status[snake_monad] do 
    ... 
    # no turn! here 
    ... 
end 

也可以工作在逻辑(蛇转弯),但输出以某种方式与换行符穿插。只要我杀死输入线程(^C),它再次看起来很正常。

那么为什么以及线程对我的输出有什么影响? 我该如何解决这个问题?
(我不知道很多有关线程,甚至更少关于他们在同一个终端上的红宝石。输入和输出同时更糟的是,我想...)



也(并不重要) :为了让我的程序尽可能纯粹,在传递所有内容时,是否可以非常容易地获得非阻塞输入?

谢谢!

+0

更糟?永远不要*让两个线程来控制IO。它会很糟糕地结束。如果你尝试在STDIN和STDOUT周围添加一个互斥锁......我不寒而栗地看到代码。 – Linuxios

+0

也许我做错了,但它也行不通。我得到的最接近的是:冻结的第一帧,我可以在其中键入'^ C' ...然后它会按照我输入的方向进行操作。任何其他组合都有原始(坏)影响。 – enlightened

回答

0

你不想要非阻塞 IO-你想要无缓冲 IO。

不需要线程,在这里 - 你只需要把你的终端进入正确的模式,然后等待主事件循环的按键。

这是一个非常荒谬的例子。

require 'io/wait' 

def ping 
    term = `stty -g` 
    `stty raw -echo cbreak` 
    loop do 
    if STDIN.ready? 
     #command thy snake! 
     ret = STDIN.getc 
    end 
    if ret 
     #process the snake command if there was one 
     STDOUT.write("you told the snake to #{ret}\n") 
    else 
     #slither around bitin' fools and hustling apples. 
    end 
    end 
ensure 
    `stty #{term}` 
end 
+0

我想,我已经在使用相同的东西了:在1.9.3上,我需要'io/console'',它提供'STDIN.getch'和'STDIN.noecho(&:getch)','getch'没有缓冲。无论如何,这似乎并没有问题,因为它没有线程工作正常... – enlightened

+0

而与阻塞我的意思是我的程序还得等待一些键被按下和阅读,我想你的代码必须也是;或者如何获得其输入? – enlightened

+0

我不确定你的意思。在更新蛇位置之前,这并不等待按键。如果你没有转过身,那蛇就会直行。 – prater

0

我发现了一个肮脏的解决方案:

我不得不添加在to_string函数中的每个换行后回车(\r),所以一切都将被覆盖后会打印。由于它是一个换行符,它失去了它的效果。现在一切都好了。

但我宁愿知道为什么发生这种情况,并修复它(如果可能)干净。