Прежде всего, сделайте пользовательский опыт как можно лучше.Одновременный ввод матрицы может привести к ошибкам, упростить жизнь пользователя и сделать его шаг за шагом.
Во-вторых, создавать небольшие методы, выполняющие простые задачи;их легче рассуждать, легче писать, легче отлаживать и легче модифицировать, если появляются новые требования.Не заставляйте методы делать слишком много, это принесет вам только головную боль и больше времени на отладку, чем необходимо.Если вы учитесь, не волнуйтесь, если вам кажется, что вы ломаетесь от, казалось бы, нелепо простых задач, вы об этом не пожалеете.Всегда помните, что самые сложные проблемы, которые вы можете себе представить, всегда решаются путем решения более мелких и простых задач.
Итак, первое, что вам нужно, - это метод, который запрашивает у пользователя действительное целое число, поэтому давайте попробуем это:
private static int GetIntegerFromUser(string prompt)
{
int value;
Console.Write($"{prompt}: ");
while (!int.TryParse(Console.ReadLine(), out value))
{
Console.WriteLine("That is not a valid value. Please try again.");
Console.Write($"{prompt}: ");
}
return value;
}
Видите, как это работает?Этот метод имеет одну единственную цель в жизни;заставить пользователя ввести действительное целое число.Не берите в голову то, для чего предназначено целое число, это не заботится, это не его работа, этот метод будет продолжать спрашивать пользователя, пока его цель в жизни не будет достигнута.
Хорошо, что дальше?При заполнении матрицы нам нужно знать:
- Количество строк
- Количество столбцов
- Значения
OkДавайте напишем несколько методов, которые выбирают именно это:
private static (int Rows, int Columns) GetMatrixSize()
{
var rows = GetIntegerFromUser("Please enter number of rows");
var columns = GetIntegerFromUser("Please enter number of columns");
return (rows, columns);
}
И,
private static int[,] GetMatrixValues(int rows, int columns)
{
var matrix = new int[rows, columns];
for (var row = 0; row < rows; row++)
{
for (var column = 0; column < columns; column++)
{
matrix[row, column] =
GetIntegerFromUser($"Enter matrix value [{row}, {column}]");
}
}
}
Теперь вы должны понять, почему создание небольших методов, выполняющих простые задачи, - это отличная идея.Поскольку шансы действительно хороши, вы сможете использовать их повторно, и как только вы узнаете, что метод работает правильно, он будет работать везде, где нужно.
Хорошо, у нас есть все, что нам нужно, теперь это просто вопросвсе вместе:
public static int[,] GetMatrixFromUser()
{
var size = GetMatrixSize();
return GetMatrixValues(size.Rows, size.Columns);
}
Насколько легко это читать?
Итак, мы закончили!В самом деле?Ну нет.У нас вообще нет валидации значений, и это может быть проблемой.Что произойдет, если кто-то решит ввести отрицательное количество строк?Хорошо, нет проблем, давайте создадим метод, который гарантирует, что значение находится в допустимом диапазоне:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
if (value >= lowerInclusiveBound &&
value < upperExclusiveBound)
return true;
Console.WriteLine(messageOnFailedValidation);
return false;
}
А теперь, поскольку мы использовали небольшие методы, которые выполняют четко определенные задачи, добавление нового требованиялегко сделать, немного изменив наш GetMatrixSize
метод:
private static (int Rows, int Columns) GetMatrixSize()
{
int rows, columns;
do
{
rows = GetIntegerFromUser("Please enter number of rows");
columns = GetIntegerFromUser("Please enter number of columns");
} while (!IsInRange(rows,
1,
int.MaxValue,
"Number of rows must be equal or greater than one.") |
!IsInRange(columns,
1,
int.MaxValue,
"Number of columns must be equal or greater than one."));
return (rows, columns);
}
Да, теперь мы закончили ...
Почти!Одна последняя вещь.Еще одна хорошая привычка - убедиться, что истины, в которые вы верите, действительно верны.Во что вы верите, чтобы быть правдой внутри GetMatrixValues
?Вы верите, что rows
и columns
будут иметь допустимые значения.Но ваша вера основана исключительно на вере, вы не проверяете, верно ли это.
Но подождите ... Я уже зарегистрировался в GetMatrixSize
верно?Да, но какая у вас гарантия, что GetMatrixValues
не будет вызываться из какого-либо другого метода позже?Многоразовость помнишь?
Здесь вы можете пойти двумя путями.Вы можете выдать исключение, если значения недопустимы, или вы можете утверждать, что значения действительно действительны.Поскольку этот метод является закрытым и наличие недопустимых значений, вероятно, означает ошибку где-то в стеке вызовов, лучшим вариантом здесь является утверждение ваших истин:
private static int[,] GetMatrixValues(int rows, int columns)
{
Debug.Assert(rows > 0 && columns > 0);
var matrix = ...
}
Какие-либо другие истины только по вере?Кто следит за тем, чтобы upperExclusiveBound
и lowerInclusiveBound
в IsInRange
действительно имели смысл?Вам кто-то мешает сделать следующий звонок: IsInRange(10, 100, -100, ...)
?Подобный вызов, вероятно, является ошибкой где-то еще в вашем коде, упростит вашу жизнь, упрощая обнаружение таких ошибок.Опять же, отстаивайте свои истины:
private static bool IsInRange(int value,
int lowerInclusiveBound,
int upperExclusiveBound,
string messageOnFailedValidation)
{
Debug.Assert(upperExclusiveBound > lowerInclusiveBound);
if ...
}
Хороший случай также может быть сделан в отношении того, следует ли проверять, что prompt
в GetIntegerFromUser
и messageOnFailedValidation
в IsInRange
не являются пустыми или нулевыми строкамии т.д.
Да, теперь мы действительно закончили.