Как обнаружить нажатия клавиш на консоли? - PullRequest
4 голосов
/ 21 декабря 2011

Я пишу roguelike в Scala. Мне нужно иметь возможность видеть, когда пользователь нажимает клавишу со стрелкой, например. Все найденные мной решения требуют от игрока нажатия клавиши ввода.

Есть ли способ обнаружить нажатия клавиш в консольном приложении аналогично getch () в C?

Ответы [ 5 ]

6 голосов
/ 21 декабря 2011

Проблема с Enter заключается в том, что терминал буферизует ввод, поэтому вам нужно перевести его в режим raw.Обратите внимание, что это проблема, специфичная для платформы, поэтому она не очень переносима.

Посмотрите на ответы на этот вопрос: Как читать один символ с консоли на Java (когда пользователь вводит его)?

Краткий ответ для систем 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)
}
3 голосов
/ 21 декабря 2011

Scala включает в свой дистрибутив jline (со слегка измененной упаковкой), поскольку использует его в REPL.Обычно он не загружается, но если вы знаете, где находится ваш каталог Scala lib, вы можете добавить его в classpath.Если вы добавите его в classpath, то это будет работать:

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 для клавиш со стрелками).

3 голосов
/ 21 декабря 2011

Я должен что-то упустить:

System.in.read

У меня работает.

1 голос
/ 21 декабря 2011

Scala находится на вершине JVM, поэтому ответ для Scala точно такой же, как и для Java.

К сожалению, я не думаю, что вам это понравится - см. этот другой ответ для деталей.

0 голосов
/ 28 октября 2018

Я использовал версию 3 из jline. Он не работает внутри IntelliJ IDE, но прекрасно работает в SBT на терминале моего Macbook.

build.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()

Это должно сработать.

...