namespace BombsAwayConsole;
///
/// Implements by writing to and reading from .
///
internal class ConsoleUserInterface : BombsAwayGame.IUserInterface
{
///
/// Write message to console.
///
/// Message to display.
public void Output(string message)
{
Console.WriteLine(message);
}
///
/// Write choices with affixed indexes, allowing the user to choose by index.
///
/// Message to display.
/// Choices to display.
/// Choice that user picked.
public int Choose(string message, IList choices)
{
IEnumerable choicesWithIndexes = choices.Select((choice, index) => $"{choice}({index + 1})");
string choiceText = string.Join(", ", choicesWithIndexes);
Output($"{message} -- {choiceText}");
ISet allowedKeys = ConsoleKeysFromList(choices);
ConsoleKey? choice;
do
{
choice = ReadChoice(allowedKeys);
if (choice is null)
{
Output("TRY AGAIN...");
}
}
while (choice is null);
return ListIndexFromConsoleKey(choice.Value);
}
///
/// Convert the given list to its equivalents. This generates keys that map
/// the first element to , the second element to ,
/// and so on, up to the last element of the list.
///
/// List whose elements will be converted to equivalents.
/// equivalents from .
private ISet ConsoleKeysFromList(IList list)
{
IEnumerable indexes = Enumerable.Range((int)ConsoleKey.D1, list.Count);
return new HashSet(indexes.Cast());
}
///
/// Convert the given console key to its list index equivalent. This assumes the key was generated from
///
///
/// Key to convert to its list index equivalent.
/// List index equivalent of key.
private int ListIndexFromConsoleKey(ConsoleKey key)
{
return key - ConsoleKey.D1;
}
///
/// Read a key from the console and return it if it is in the given allowed keys.
///
/// Allowed keys.
/// Key read from , if it is in ; null otherwise./>
private ConsoleKey? ReadChoice(ISet allowedKeys)
{
ConsoleKeyInfo keyInfo = ReadKey();
return allowedKeys.Contains(keyInfo.Key) ? keyInfo.Key : null;
}
///
/// Read key from .
///
/// Key read from .
private ConsoleKeyInfo ReadKey()
{
ConsoleKeyInfo result = Console.ReadKey(intercept: false);
// Write a blank line to the console so the displayed key is on its own line.
Console.WriteLine();
return result;
}
///
/// Allow user to choose 'Y' or 'N' from .
///
/// Message to display.
/// True if user chose 'Y', false if user chose 'N'.
public bool ChooseYesOrNo(string message)
{
Output(message);
ConsoleKey? choice;
do
{
choice = ReadChoice(new HashSet(new[] { ConsoleKey.Y, ConsoleKey.N }));
if (choice is null)
{
Output("ENTER Y OR N");
}
}
while (choice is null);
return choice.Value == ConsoleKey.Y;
}
///
/// Get integer by reading a line from .
///
/// Integer read from .
public int InputInteger()
{
bool resultIsValid;
int result;
do
{
string? integerText = Console.ReadLine();
resultIsValid = int.TryParse(integerText, out result);
if (!resultIsValid)
{
Output("PLEASE ENTER A NUMBER");
}
}
while (!resultIsValid);
return result;
}
}