#arrays #scala #mapping #case-class
#массивы #scala #сопоставление #case-класс
Вопрос:
Я посещаю начальный курс программирования, и мы приступаем к созданию текстовых игр, больше похожих на «Прочитай свои собственные приключения», чем на реальные игры, и я не совсем понимаю, как получить информацию из моей карты, которая содержит всю информацию о комнате, в файл, который будет ее запускать. У меня есть файл rooms, настроенный следующим образом…
0 roomone
you enter a room, and it looks odd. you can go north or south. which way?
2
north 1
south 2
//will having a space here make a difference? should i delete these?
1 hall
theres a hall here, with a door running east. continue north,go east, or go back south?
3
north 3
south 0
east 4
и так далее, чтобы комнате был присвоен номер и имя, затем она получила описание, затем перечислите количество выходов, перечислите, что это такое, а затем перечислите, в какую пронумерованную комнату этот ответ должен вас привести. Я не знаю, как сделать так, чтобы она считывалась в две вещи: одна, которая принимает первые три бита информации в качестве информации о комнате, а вторая, которая считывает количество выходов и создает массив с этим количеством выходов, а затем считывает выходы и их номера.
что у меня есть
case class Map(location:Int,place:String,description:String,exits:Array )
case class Exits(numberexits:Int,direction:String,destination:Int)
Я знаю, что, вероятно, есть какой-то простой ответ, но я действительно не понимаю, что я должен делать. Я не знаю, как заставить мой файл считываться, чтобы нужные части попадали в нужные места, и я достаточно новичок, что многое из того, что я читал, мне не очень понятно, поэтому, надеюсь, мои вопросы достаточно ясны, чтобы кто-нибудь мог мне помочь и сказать, могу ли яя собираюсь сделать это даже отчасти правильно, и если это сработает, когда я действительно попытаюсь собрать это вместе, поскольку, если я понимаю, что я делаю, это должно принимать пользовательский ввод, искать направление, введенное из массива выходов, смотреть на пункт назначения, связанный с этим, затем приниматьэто место назначения и найдите местоположение на карте с этим номером и перенесите вас туда, а затем println(Map.description) и дождитесь следующего ввода?
Ответ №1:
Кажется, что каждый второй вопрос в наши дни я вижу комбинаторы синтаксического анализа.
case class Exit(direction:String,destination:Int)
case class Map(location:Int, place:String, description:String, exits:List[Exit] )
object ReadConf extends scala.util.parsing.combinator.RegexParsers {
override protected val whiteSpace = " ".r
def eol = "n"
def number = "\d ".r ^^ (_.toInt)
// Overall format
def conf = (comment.* ~> map).*
def map = header ~ description ~ exits ^^ {
case location ~ place ~ description ~ exits =>
Map(location, place, description, exits)
}
def comment = "//.*".r ~ eol
// Map parts (except exits)
def header = location ~ place <~ eol
def description = ".*".r <~ eol
def location = number
def place = "\w ".r
// Exits
def exits = numberOfExits <~ eol >> nExits
def nExits(n: Int) = repN(n, exit)
def exit = direction ~ destination <~ eol ^^ {
case direction ~ destination => Exit(direction, destination)
}
def numberOfExits = number
def direction = "\w ".r
def destination = number
}
Ответ №2:
Прочитайте файл с val lines = scala.io.source.fromFile.getLines().toList
помощью или как-то так.
Ничего не вызывайте Map
, поскольку в Scala уже есть a Map
, который вы, возможно, захотите использовать.
Теперь, когда у вас есть все строки, вы можете выяснить, как их разобрать. Возможно, вы захотите использовать сопоставление:
lines match {
case a :: b :: c :: remainder =>
// Execute this code if and only if there are at least 3 lines in the list;
// if so, pull the first 3 out and call them a, b, and c
case _ =>
// Otherwise execute this
}
И вы также можете захотеть использовать рекурсию (это просто разбило бы объект на список комнат, но не извлекло бы информацию из каждой комнаты):
def parse(lines: List[String], roomsText: List[List[String]] = Nil): List[List[String]] = {
lines match {
case Nil => rooms // Parsed all the lines, so return what we've already found
case /* whatever conditions you need */ =>
// do stuff to find one more room
parse(remainingLines, newRoom :: roomsText)
}
}
Как только вы выполните дополнительный синтаксический анализ ( .split(" ")
может быть полезно для строк) и перенесете все в класс case , который я буду вызывать Room
вместо Map
, вы принимаете ввод пользователя (см. Console
), преобразуете его в целое число (попробуйте .toInt
) и просматриваете его в своем списке комнат. Для этого может быть полезна реальная карта:
val roomsByNumber = rooms.map(room => (room.location, room)).toMap
Теперь roomsByNumber(n)
посмотрим на n
‘-ю комнату.
Надеюсь, это поможет вам начать. Удачи!
PS Я понятия не имею, чему вас уже учили, поэтому я не могу сказать, имеет ли смысл то, что я пишу, или выглядит как тарабарщина; большинство классов ожидают, что вы будете использовать в основном то, чему вас уже научили, поэтому вы должны посмотреть, что вы можете сделать, учитывая то, что вы уже узнали, пытаясьпримите любую стратегию, которую я здесь предложил. Но не называйте класс room case Map
, если явно не указано — это просто вызовет проблемы с использованием встроенного Map
.