Новый ответ: используйте массив
Я медленный. Я не обратил внимания на то, что вы делаете игру, похожую на броненосец, и что мы знаем, что «коробки» образуют прямоугольник. Мы можем эффективно хранить это в массиве.
Почему я не догнал этот факт раньше? Я думаю, мне нужно проснуться правильно.
Итак, используйте массив:
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);