我正在用 Scala 写一个 roguelike。例如,我需要能够看到用户何时按下箭头键。我发现的所有解决方案都需要玩家按回车键。
有没有办法以与 C 中的 getch() 类似的方式检测控制台应用程序中的按键?
问题Enter
在于终端缓冲输入,因此您需要将其转换为raw
模式。请注意,这是一个特定于平台的问题,因此它不是很便携。
查看这个问题的答案:How to read a single char from the console in Java (as the user type it)?
UNIX 系统的简短回答:
import sys.process._
(Seq("sh", "-c", "stty -icanon min 1 < /dev/tty") !)
(Seq("sh", "-c", "stty -echo < /dev/tty") !)
(1 to 20).foreach { _ =>
val c = Console.in.read
println("Got " + c)
}
Scala 包含jline
在其发行版中(包装略有修改),因为它在 REPL 中使用它。它通常不会被加载,但如果你知道你的 Scala lib 目录在哪里,你可以将它添加到类路径中。如果将它添加到类路径中,那么这将起作用:
object Key extends App {
val con = new tools.jline.console.ConsoleReader()
println( con.readVirtualKey() )
}
(请注意,此方法将分别为上、下、左和右提供 ^P ^N ^B ^F,以匹配标准控制键)。但这也会覆盖 的标准行为System.in.read()
,因此您可以将长度为 1 的数组传递给它以获取下一个等待字节(并使用 测试等待字节System.in.available
,对于箭头键,它应该大于 1)。
我肯定错过了什么:
System.in.read
为我工作。
Scala 位于 JVM 之上,因此 Scala 的答案与 Java 的答案完全相同。
不幸的是,我认为您不会喜欢它 - 有关详细信息,请参阅其他答案。
我用的是版本 3 jline
。它在 IntelliJ IDE 中不起作用,但在我的 Macbook 终端的 SBT 中完美。
构建.sbt
libraryDependencies += "org.jline" % "jline" % "3.1.3"
这是一个示例应用程序,它将在按下“输入”键时停止。
Main.scala
import org.jline.terminal.TerminalBuilder
object Main extends App {
val terminal = TerminalBuilder.builder().jna(true).system(true).build()
terminal.enterRawMode()
val reader = terminal.reader()
var input = -1
while (input != 13) {
input = reader.read
input match {
case 'a' =>
println("you pressed 'a'")
case unknown =>
println(s"you pressed a unknown key $unknown")
}
}
}
terminal.close()
reader.close()
那应该行得通。