Конвертировать введенную пользователем строку в объект в c # - PullRequest
0 голосов
/ 06 мая 2018

У меня есть терминальная игра, похожая на линейный корабль, пользователь вводит координату, подобную e2, и программа проверяет одну из переменных экземпляра моего объекта Box, проверяет, имеет ли hasShip значение true, если его значение true, тогда она получит координату e2. false и выведите «Корабль уничтожен»

Проблема в том, что все мои объекты называются a1, a2, a3, a4, a5, b1, b2 и т. Д.

Я создал 25 экземпляров класса Box. Все имена как таковые.

Как только программа получит ввод, e4, e5 и т. Д. Я хочу преобразовать эту строку в объект.

Например (я хочу сделать что-то подобное)

target = Console.ReadLine();
target.hasShip == true; 

Я хочу преобразовать target в объект, а затем использовать target для использования методов класса Box.

Поскольку другой подход требует, чтобы я загружал операторы if, которые не являются чистым кодом, выглядят не очень хорошо, и если вы спрашиваете меня, это пустая трата.

Заранее спасибо,

1 Ответ

0 голосов
/ 06 мая 2018

Новый ответ: используйте массив

Я медленный. Я не обратил внимания на то, что вы делаете игру, похожую на броненосец, и что мы знаем, что «коробки» образуют прямоугольник. Мы можем эффективно хранить это в массиве.

Почему я не догнал этот факт раньше? Я думаю, мне нужно проснуться правильно.

Итак, используйте массив:

var board = new Box[5, 5];

Теперь, чтобы заполнить его, мы можем сделать двойной цикл for:

for(var indexRow = 0; indexRow < 5; indexRow++)
{
    for(var indexCol = 0; indexCol < 5; indexCol++)
    {
        board[indexRow, indexCol] = new Box();
    }
}

Примечание : обратите внимание, что индексы идут от 0 до 4. Всего 5 значений: {0, 1, 2, 3, 5}.

И для запроса нам понадобятся индексы ...


Дополнение по заполнению массива

В комментариях OP сказал, что у каждого Box есть идентификатор, и позиции корабля выбираются случайным образом.

Мы можем дать идентификатор в цикле:

for(var indexRow = 0; indexRow < 5; indexRow++)
{
    for(var indexCol = 0; indexCol < 5; indexCol++)
    {
        var box = new Box();
        box.vhID = (((char)(((int)'a') + indexRow))).ToString() + ((char)(((int)'1') + indexCol)).ToString();
        board[indexRow, indexCol] = box;

    }
}

То, что я здесь делаю, - это создание идентификатора из индексов. В основном, взяв значение 'a' и добавив indexRow, мы получим 'a', если indexRow равно 0, 'b', когда оно 1 и так далее. Точно так же мы получаем цифру, которая представляет столбец.

Примечание : мы конвертируем char в int, делаем сложение, затем конвертируем обратно в char ... и затем из char в string. Как только у нас есть строка, мы можем объединить их.

Я не думаю, что нам нужен этот идентификатор. Но, эй, вы можете сделать это следующим образом.

ОП также упоминает, что он выберет 4 позиции корабля наугад. Достаточно справедливо:

var random = new Random();
for (var ships = 0; ships < 4; ships++)
{
    board[random.Next(0, 4), random.Next(0, 4)].hasShip = true;
}

Поскольку пользователь вводит строку, я предлагаю создать функцию для преобразования ее в индексную пару:

 var input = Console.ReadLine();
 if (TryGetCoordinates(input, out int irow, out int icol))
 {
     var target = board[irow, icol];
 }
 else
 {
     Console.WriteLine("The cell {0} does not exist.", input);
 }

 // ...

 bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
 {
     // ...
 }

Начните с проверки null:

 bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
 {
     indexRow = -1;
     indexCol = -1;
     if (cell == null)
     {
         return false;
     } 
     // ...
 }

Примечание : Не стесняйтесь использовать Trim, ToUpper или ToUpperInvariant.

Мы знаем, что это должна быть буква, за которой следует цифра, мы можем подтвердить длину:

 bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
 {
     indexRow = -1;
     indexCol = -1;
     if (cell == null)
     {
         return false;
     }
     if (cell.Length != 2)
     {
         return false;
     }
     // ...
 }

Извлекаем символы и из них координаты. Отмечая, что первая буква, а другая цифра. Мы также можем подтвердить, что они не выходят за границы.

 bool TryGetCoordinates(string cell, out int indexRow, out int indexCol)
 {
     indexRow = -1;
     indexCol = -1;
     if (cell == null)
     {
         return false;
     }
     if (cell.Length != 2)
     {
         return false;
     }
     indexRow = (int)cell[0] - (int)'a';
     indexCol = (int)cell[1] - (int)'1';
     return indexRow < 5 && indexRow >= 0 && indexCol < 5 && indexCol >= 0;
 }

И, конечно, вы можете выполнить цикл проверки, аналогичный тому, что был объяснен в старом ответе.

Примечание : проблема с типами значений, которые я описываю в предыдущем ответе, все еще относится к массиву.


Старый ответ: используйте словарь

Полагаю, вы не хотите преобразовывать string в объект (кстати, string - это объект), вы хотите выбрать объект Box, который вы ранее создали на основе string. И вы хотите сделать это без использования операторов if. Вам нужен словарь.

Таким образом, у вас будет Dictionary<string, Box>, означающее, что это словарь, который вы можете запросить по строке и хранит Box.

* 1099 Дополнения *:

  • В этом случае строка - это тип ключа, по которому мы будем обращаться к словарю. Когда мы добавляем объект в словарь, мы идентифицируем его с помощью ключа, а когда мы получаем его, мы также используем ключ. Ключ не должен быть string, вы можете выбрать другой тип. string удобно в этом случае, потому что это то, что вы получаете от Console.ReadLine().
  • Вы можете создать словарь для хранения любого типа, который вам нужен. Если вам не нужен Box, вы можете создать словарь, в котором будет храниться что-то еще.

Создание и заполнение словаря

Затем вы добавляете в словарь все свои объекты Box, например:

var dict = new Dictionary<string, Box>();

// ...

dict.Add("a1", CreateBoxA1());

Где CreateBoxA1 обозначает все, что вам нужно для создания объекта. Нет, вам не нужно создавать метод для каждого Box ... вы можете сделать это так:

dict.Add("a1", new Box());

Или что угодно. Я не знаю, как вы их создаете, так что считайте это заполнителем, хорошо? ок.


Запрос и получение значений из словаря

Если в вашем словаре есть все экземпляры Box, вы можете получить тот, который вам нужен, с помощью string:

Console.WriteLine("Enter the name of the Box:");
var name = Console.ReadLine();
var target = dict[name];

Приложение : значение, которое вы получаете из dict[name], - это значение, которое вы добавили в словарь с этим ключом. Так, если пользователь набрал "a1", то dict[name] будет значением, которое мы добавили с "a1" (dict.Add("a1", new Box());). Опять же, если вам нужно не Box, вы можете создать словарь для хранения другого типа.


Подтверждение ввода

Вы также можете использовать Словарь для проверки, если string соответствует существующему Ящику, например:

Console.WriteLine("Enter the name of the Box:");
var name = Console.ReadLine();
if (dict.KeyExists(name))
{
    var target = dict[name];
    // ...
}
else
{
    Console.WriteLine("The Box {0} does not exist", name);
}

Само собой разумеется, но ... вы можете сделать цикл на основе этого, например:

Box target = null;
while(true)
{
    Console.WriteLine("Enter the name of the Box:");
    var name = Console.ReadLine();
    if (dict.KeyExists(name))
    {
        target = dict[name];
        break;
    }
    Console.WriteLine("The Box {0} does not exist", name);
}

Кроме того, само собой разумеется, но ... вы можете добавить свои собственные проверки и этапы санитарии. Например, используя ToUpper, ToUpperInvariant или Trim. И я хотел бы напомнить вам, что изменение string s в нижний или верхний регистр зависит от культуры.

См. Также: Рекомендации по использованию строк в .NET .


Редактирование удаления объектов из словаря

Как только у вас есть объект, который вы извлекли из словаря ...

 var target = dict[name];

Мы можем использовать его и даже изменить:

 var target = dict[name];
 if (target.hasShip) // no need for "== true" if hasShip bool
 {
      target.hasShip = false;
      Console.WriteLine("Ship Destroyed");
 }

Особое примечание должно быть сделано, если Box является типом значения. Для пользовательского типа это означает, что это не class, а struct. Проблема с типами значений заключается в том, что они копируются при присваивании, что означает, что когда вы делаете var target = dict[name]; с типом значения, вы получаете копию. Затем вы должны обновить словарь, как только вы им манипулировали:

 var target = dict[name];
 if (target.hasShip) // no need for "== true" if hasShip bool
 {
      target.hasShip = false;
      dict[name] = target;
      Console.WriteLine("Ship Destroyed");
 }

Примечание : Как я уже говорил выше, это необходимо только для типов значений.


И вы даже можете удалить Box из словаря, если это необходимо:

dict.Remove(name); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...