C#. Использование System.Console для создания игр в текстовом режиме. Часть 3
Главный цикл
Есть еще одна вещь, о которой вы должны знать, когда будете создавать игру, которая будет работать в окне консоли: главный цикл. Все игры обычно имеют основной цикл, который работает пока игра не завершится. Вот полезные шаблоны, которые можно использовать в главном цикле программы:
- Console.CancelKeyPress делает курсор невидимым. Таким образом, вас не будет раздражать мерцание;
- событие Console.CancelKeyPress возникает, когда пользователь нажимает Ctrl-C, но только если свойство Console.TreatControlCAInput не установлено в true;
- смотрите комментарии к коду статьи для получения больше информации, как обрабатывать событие CancelKeyPress;
- вызов System.Threading.Thread.Sleep() в главном цикле добавляет небольшую задержку, а также разгружает ваш процессор;
- устанавливайте свойство Console.KeyAvailable в true, если хотите принимать сообщения с клавиатуры. Таким образом, вы сможете прочитать его с помощью метода Console.ReadKey();
Посмотрите на комментарии к следующему коду, которые описывают, где происходит инициализация игры, а где пользовательский ввод и обновление экрана:
1 |
/// <summary> |
2 |
/// Установите это статическое поле в true для выхода из игры |
3 |
/// </summary> |
4 |
static bool quit = false; |
5 |
6 |
/// <summary> |
7 |
/// Точка входа, инициализация игры и старт основного цикла |
8 |
/// </summary> |
9 |
static void Main(string[] args) |
10 |
{ |
11 |
// Будьте уверены, что пользователь нажмет Ctrl-C для выхода из игры |
12 |
// Установите Console.TreatControlCAsInput в true если хотите использовать Ctrl-C как допустимое входное значение |
13 |
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress); |
14 |
15 |
Console.CursorVisible = false; |
16 |
17 |
/*** Инициализация игры! ***/ |
18 |
19 |
MainLoop(); |
20 |
} |
21 |
22 |
/// <summary> |
23 |
/// Обработка нажатия Ctrl-C |
24 |
/// </summary> |
25 |
static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) |
26 |
{ |
27 |
// К сожалению, в связи с ошибкой в .NET Framework v4.0.30319 вы не можете олаживать это |
28 |
// потому что Visual Studio 2010 выдает ошибку "No Source Available". |
30 |
Console.WriteLine("{0} hit, quitting...", e.SpecialKey); |
31 |
quit = true; |
32 |
e.Cancel = true; // Установка в true позволяет на закрывать программу сразу |
33 |
} |
34 |
35 |
/// <summary> |
36 |
/// Главный цикл игры |
37 |
/// </summary> |
38 |
static void MainLoop() |
39 |
{ |
40 |
int elapsedMilliseconds = 0; |
41 |
int totalMilliseconds = TIME_LIMIT_SECONDS * 1000; |
42 |
const int INTERVAL = 100; |
43 |
44 |
while (elapsedMilliseconds < totalMilliseconds && !quit) |
45 |
{ |
46 |
// Задержка на определенный период |
47 |
Thread.Sleep(INTERVAL); |
48 |
elapsedMilliseconds += INTERVAL; |
49 |
50 |
/*** Обновление экрана! ***/ |
51 |
} |
52 |
53 |
Console.WriteLine("Игра окончена!"); |
54 |
} |
Теперь у вас есть все части, которые нужны для создания игры. Это все, что нужно для создания WordFinder. WordFinder – игра-головоломка, в которой игрок имеет 60 секунд, чтобы найти как можно больше слов в таблице со случайными буквами.
Вы можете загрузить все эти файлы в проект Visual Studio 2010 под названием WordFinder. После этого вы должны создать в проекте текстовый файл с именем words.txt. Убедитесь в том, что он копируется в выходной каталог при компиляции.
Также, вы можете скомпилировать его из командной строки следующим образом:
1. Сохраните каждый из четырех файлов в одну папку.
2. Используя Блокнот, создайте текстовый файл и сохраните его под именем words.txt. Заполните его словами для игры (можно использовать вот этот список).
3. Откомпилируйте ваше приложение:
%SYSTEMROOT%\Microsoft.NET\Framework\v3.5\csc.exe /out:WordFinder.exe Program.cs Game.cs Puzzle.cs WordChecker.cs
4. Когда вы будете запускать игру, убедитесь, что файл words.txt находится в той же папке, что и WordFinder.exe.
Конечно, есть и более элегантное решение, к примеру, использование файла ресурса, но я хотел, чтобы моя игра была быстрая и хардкорная!
Обратите внимание, если вы пользуетесь Блокнотом для сохранения файлов, вы получите предупреждение, что Unicode-символы будут утеряны. Потому что Game.cs содержит символы, которые были вставлены из буфера обмена в Unicode-кодировки. На этот счет у вас есть два варианта. Вы можете сохранить все файлы, используя настройки по умолчанию, которые автоматически преобразуют символы линий в +, - и |. Но если вы хотите сохранить символы Unicode правильно, то в окне сохранения «Сохранить как…» выберите «Unicode» из выпадающего списка выбора кодировок.
Все описанное выше и комментарии к коду помогут вам разобраться, как работают игры. Удачи вам в написании игр в текстовом режиме! Если вам что-то не понравилось, дайте мне об этом знать.
Исходный код игры WordFinder
1 |
using System; |
2 |
using System.IO; |
3 |
using System.Threading; |
4 |
5 |
namespace WordFinder |
6 |
{ |
7 |
/// <summary> |
8 |
/// Класс Program содержит главный цикл, окончание игры, запуск таймера, |
9 |
/// и обработку нажития пользователем Ctrl-C для выхода из игры. Весь геймплей и отрисовка |
10 |
/// обрабатывается в классе Game. |
11 |
/// </summary> |
12 |
class Program |
13 |
{ |
14 |
/// <summary> |
15 |
/// Длина головоломки в буквах |
16 |
/// </summary> |
17 |
const int PUZZLE_LENGTH = 49; |
18 |
19 |
/// <summary> |
20 |
/// Каждая n-я буква должна быть гласной |
21 |
/// </summary> |
22 |
const int VOWEL_EVERY = 5; |
23 |
24 |
/// <summary> |
25 |
/// Отведенный лимит времени |
26 |
/// </summary> |
27 |
const int TIME_LIMIT_SECONDS = 60; |
28 |
29 |
/// <summary> |
30 |
/// Список слов -- Я скачал отсюда http://unix-tree.huihoo.org/V7/usr/dict/words.html |
31 |
/// и вставил в words.txt, не забудьте установить своейство копирования в целевую директорию |
32 |
/// в "Copy Always" (таким образом он будет в той же папке, где и запускной файл). Конечно, мы можем использовать |
33 |
/// файл ресурса, но использование текстового файла позволяет расширить игру, используя различные списки слов |
34 |
/// </summary> |
35 |
static string[] words = File.ReadAllLines("words.txt"); |
36 |
37 |
/// <summary> |
38 |
/// Объект для отслеживания игры |
39 |
/// </summary> |
40 |
static Game game; |
41 |
42 |
/// <summary> |
43 |
/// Установите это свойство в true для выхода из игры |
44 |
/// </summary> |
45 |
static bool quit = false; |
46 |
47 |
/// <summary> |
48 |
/// Текущий пользовательский ввод |
49 |
/// </summary> |
50 |
static string word = String.Empty; |
51 |
52 |
/// <summary> |
53 |
/// Входная точка установки экрана, инициализации игры и запуск главного цикла |
54 |
/// </summary> |
55 |
static void Main(string[] args) |
56 |
{ |
57 |
// Будьте уверены, что пользователь нажмет Ctrl-C для выхода из игры |
58 |
// Установите Console.TreatControlCAsInput в true если хотите использовать Ctrl-C как допустимое входное значение |
59 |
Console.CancelKeyPress += new ConsoleCancelEventHandler(Console_CancelKeyPress); |
60 |
61 |
Console.CursorVisible = false; |
62 |
63 |
game = new Game(PUZZLE_LENGTH, VOWEL_EVERY, words); |
64 |
game.DrawInititalScreen(); |
65 |
MainLoop(); |
66 |
} |
67 |
68 |
/// <summary> |
69 |
/// Обработка нажатия Ctrl-C |
70 |
/// </summary> |
71 |
static void Console_CancelKeyPress(object sender, ConsoleCancelEventArgs e) |
72 |
{ |
73 |
// К сожалению, в связи с ошибкой в .NET Framework v4.0.30319 вы не можете олаживать это |
74 |
// потому что Visual Studio 2010 выдает ошибку "No Source Available". |
76 |
Console.SetCursorPosition(0, 19); |
77 |
Console.WriteLine("Нажата {0}, выход...", e.SpecialKey); |
78 |
quit = true; |
79 |
e.Cancel = true; // Установка в true позволяет на закрывать программу сразу |
80 |
} |
81 |
82 |
/// <summary> |
83 |
/// Главный цикл игры |
84 |
/// </summary> |
85 |
static void MainLoop() |
86 |
{ |
87 |
int elapsedMilliseconds = 0; |
88 |
int totalMilliseconds = TIME_LIMIT_SECONDS * 1000; |
89 |
const int INTERVAL = 100; |
90 |
91 |
while (elapsedMilliseconds < totalMilliseconds && !quit) |
92 |
{ |
93 |
// Задержка на определенный период |
94 |
Thread.Sleep(INTERVAL); |
95 |
elapsedMilliseconds += INTERVAL; |
96 |
97 |
HandleInput(); |
98 |
99 |
PrintRemainingTime(elapsedMilliseconds, totalMilliseconds); |
100 |
} |
101 |
102 |
Console.SetCursorPosition(0, 20); |
103 |
Console.WriteLine(Environment.NewLine + Environment.NewLine |
104 |
+ "Игра окончена! Вы нашли {0} слов.", game.NumberFound); |
105 |
} |
106 |
107 |
/// <summary> |
108 |
/// Запись оставшегося времени в правый верхний угол экрана |
109 |
/// </summary> |
110 |
/// <param name="elapsedMilliseconds">Пройденное время с начала запуска игры</param> |
111 |
/// <param name="totalMilliseconds">Общее количество милисекудн установленное для игры</param> |
112 |
private static void PrintRemainingTime(int elapsedMilliseconds, int totalMilliseconds) |
113 |
{ |
114 |
int milliSecondsLeft = totalMilliseconds - elapsedMilliseconds; |
115 |
double secondsLeft = (double)milliSecondsLeft / 1000; |
116 |
string timeString = String.Format("{0:00.0} секунд осталось", secondsLeft); |
117 |
118 |
// Сохранение позиции курсора |
119 |
int left = Console.CursorLeft; |
120 |
int top = Console.CursorTop; |
121 |
122 |
// Рисуем время в правом верхнем углу экрана |
123 |
Console.SetCursorPosition(Console.WindowWidth - timeString.Length, 0); |
124 |
Console.ForegroundColor = ConsoleColor.Magenta; |
125 |
Console.Write(timeString); |
126 |
127 |
// Восстановление цвета текста консоли и установка курсора на последнюю позицию |
128 |
Console.ResetColor(); |
129 |
Console.SetCursorPosition(left, top); |
130 |
} |
131 |
132 |
/// <summary> |
133 |
/// Обрабатывать любые нажатия клавиш пользователем |
134 |
/// </summary> |
135 |
static void HandleInput() |
136 |
{ |
137 |
Thread.Sleep(50); |
138 |
if (Console.KeyAvailable) |
139 |
{ |
140 |
ConsoleKeyInfo keyInfo = Console.ReadKey(true); |
141 |
if (keyInfo.Key == ConsoleKey.Backspace) |
142 |
{ |
143 |
if (word.Length > 0) |
144 |
word = word.Substring(0, word.Length - 1); |
145 |
} |
146 |
else if (keyInfo.Key == ConsoleKey.Escape) |
147 |
{ |
148 |
word = String.Empty; |
149 |
} |
150 |
else |
151 |
{ |
152 |
string key = keyInfo.KeyChar.ToString().ToUpper(); |
153 |
if (game.IsValidLetter(key)) |
154 |
{ |
155 |
word = word + key; |
156 |
} |
157 |
} |
158 |
game.CurrentInput = word; |
159 |
game.ProcessInput(); |
160 |
game.UpdateScreen(); |
161 |
} |
162 |
} |
163 |
} |
164 |
} |
Файл Game.cs:
1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
using System.Linq; |
4 |
5 |
namespace WordFinder |
6 |
{ |
7 |
/// <summary> |
8 |
/// Класс Game отслеживает состояние игры и рисует на экране и обновляет его |
9 |
/// Он использует экземпляр класса Puzzle следить за буквами в таблице |
10 |
/// головоломки, а экземпляр WordChecker следить за |
11 |
/// словами и занимается проверкой ответов игрока. |
12 |
/// </summary> |
13 |
class Game |
14 |
{ |
15 |
/// <summary> |
16 |
/// Объект WordChecker проверяет слова |
17 |
/// </summary> |
18 |
private WordChecker wordChecker; |
19 |
20 |
/// <summary> |
21 |
/// Получить количество найденных слов |
22 |
/// </summary> |
23 |
public int NumberFound |
24 |
{ |
25 |
// Объет WordChecker содержит эту информацию |
26 |
get { return wordChecker.NumberFound; } |
27 |
} |
28 |
29 |
/// <summary> |
30 |
/// Объект Puzzle содержит буквы и проверяет слова |
31 |
/// </summary> |
32 |
private Puzzle puzzle; |
33 |
34 |
/// <summary> |
35 |
/// Текущей пользовательский ввод |
36 |
/// </summary> |
37 |
public string CurrentInput { private get; set; } |
38 |
39 |
/// <summary> |
40 |
/// Конструктор класса Game |
41 |
/// </summary> |
42 |
/// <param name="puzzleLength">Количество букв в головоломке</param> |
43 |
/// <param name="vowelEvery">Добавлять гласную каждую n-ю букву</param> |
44 |
/// <param name="validWords">Список проверочных слов</param> |
45 |
public Game(int puzzleLength, int vowelEvery, IEnumerable<string> validWords) |
46 |
{ |
47 |
this.wordChecker = new WordChecker(validWords); |
48 |
this.puzzle = new Puzzle(puzzleLength, vowelEvery); |
49 |
CurrentInput = String.Empty; |
50 |
} |
51 |
52 |
/// <summary> |
53 |
/// Рисуем на экране консоли стартовую заставку |
54 |
/// </summary> |
55 |
public void DrawInititalScreen() |
56 |
{ |
57 |
Console.Clear(); |
58 |
Console.Title = "Word finder"; |
59 |
puzzle.Draw(25, 3); |
60 |
Console.SetCursorPosition(7, 11); |
61 |
Console.Write("--------------------------------------------------------¬"); |
62 |
Console.SetCursorPosition(7, 12); |
63 |
Console.Write("¦"); |
64 |
Console.SetCursorPosition(63, 12); |
65 |
Console.Write("¦"); |
66 |
Console.SetCursorPosition(7, 13); |
67 |
Console.Write("L=======================================================-"); |
68 |
UpdateScreen(); |
69 |
} |
70 |
71 |
/// <summary> |
72 |
/// Обновляем экран |
73 |
/// </summary> |
74 |
public void UpdateScreen() |
75 |
{ |
76 |
// Используем String.PadRight() чтобы убедиться, что желтое поле ввода остается постоянного |
77 |
// размера, вне зависимости от длины слова |
78 |
Console.SetCursorPosition(8, 12); |
79 |
Console.ForegroundColor = ConsoleColor.DarkGray; |
80 |
Console.BackgroundColor = ConsoleColor.Yellow; |
81 |
string message = String.Format("Введите слово #{0}: {1}", |
82 |
wordChecker.NumberFound, CurrentInput); |
83 |
Console.Write(message.PadRight(54)); |
84 |
Console.ResetColor(); |
85 |
86 |
Console.SetCursorPosition(0, 17); |
87 |
Console.Write("Найдено слов: "); |
88 |
foreach (string word in wordChecker.FoundWords) |
89 |
Console.Write("{0} ", word); |
90 |
91 |
Console.SetCursorPosition(7, 14); |
92 |
Console.Write("Наберайте любые слова, которые вы нашли. <ESC> очищает поле."); |
93 |
} |
94 |
95 |
/// <summary> |
96 |
/// Обработка слова при каждом вводе |
97 |
/// </summary> |
98 |
public void ProcessInput() |
99 |
{ |
100 |
wordChecker.CheckAnswer(CurrentInput, puzzle); |
101 |
} |
102 |
103 |
/// <summary> |
104 |
/// Возвращает true, если нажата правильная буква из набора. |
105 |
/// </summary> |
106 |
/// <param name="key">Буква, которая была нажата</param> |
107 |
/// <returns>True если буква гласная или согласная из таблицы</returns> |
108 |
public bool IsValidLetter(string key) |
109 |
{ |
110 |
if (key.Length == 1) |
111 |
{ |
112 |
char c = key.ToCharArray()[0]; |
113 |
return Puzzle.Consonants.Contains(c) || Puzzle.Vowels.Contains(c); |
114 |
} |
115 |
return false; |
116 |
} |
117 |
118 |
} |
119 |
} |
Файл Puzzle.cs:
1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
using System.Linq; |
4 |
5 |
namespace WordFinder |
6 |
{ |
7 |
/// <summary> |
8 |
/// Класс Puzzle содержит таблицу головоломки. Игра использует его для отрисовки |
9 |
/// таблицы на экране, а класс WordFinder используется для проверки игрока, |
10 |
/// ввел ли он букву из таблицы |
11 |
/// </summary> |
12 |
class Puzzle |
13 |
{ |
14 |
/// <summary> |
15 |
/// Randomizer |
16 |
/// </summary> |
17 |
private Random random = new Random(); |
18 |
19 |
/// <summary> |
20 |
/// Согласные (содержит Y) |
21 |
/// </summary> |
22 |
public static readonly char[] Consonants = { 'B', 'C', 'D', 'F', 'G', 'H', 'J', 'K', |
23 |
'L', 'M', 'N', 'P', 'Q', 'R', 'S', 'T', 'V', 'W', 'X', 'Y', 'Z' }; |
24 |
25 |
/// <summary> |
26 |
/// Гласные (содержит Y) |
27 |
/// </summary> |
28 |
public static readonly char[] Vowels = { 'A', 'E', 'I', 'O', 'U', 'Y' }; |
29 |
30 |
/// <summary> |
31 |
/// Резервное поле для букв |
32 |
/// </summary> |
33 |
char[] letters; |
34 |
35 |
/// <summary> |
36 |
/// Получить буквы из головоломки |
37 |
/// </summary> |
38 |
public IEnumerable<char> Letters |
39 |
{ |
40 |
get { return letters; } |
41 |
} |
42 |
43 |
/// <summary> |
44 |
/// Номер буквы в головоломке |
45 |
/// </summary> |
46 |
private int puzzleLength; |
47 |
48 |
/// <summary> |
49 |
/// Конструктор класса Puzzle |
50 |
/// </summary> |
51 |
/// <param name="puzzleLength">Количество букв в головоломке</param> |
52 |
/// <param name="vowelEvery">Каждая n-я буква гласная</param> |
53 |
public Puzzle(int puzzleLength, int vowelEvery) |
54 |
{ |
55 |
this.puzzleLength = puzzleLength; |
56 |
57 |
letters = new char[puzzleLength]; |
58 |
59 |
for (int i = 0; i < puzzleLength; i++) |
60 |
{ |
61 |
if (i % vowelEvery == 0) |
62 |
letters[i] = Vowels[random.Next(Vowels.Length)]; |
63 |
else |
64 |
letters[i] = Consonants[random.Next(Consonants.Length)]; |
65 |
} |
66 |
} |
67 |
68 |
/// <summary> |
69 |
/// Нарисовать головоломку в выбранном месте экрана |
70 |
/// </summary> |
71 |
/// <param name="left">Координата X</param> |
72 |
/// <param name="top">Координата Y</param> |
73 |
public void Draw(int left, int top) |
74 |
{ |
75 |
int oldTop = Console.CursorTop; |
76 |
int oldLeft = Console.CursorLeft; |
77 |
78 |
Console.BackgroundColor = ConsoleColor.Gray; |
79 |
80 |
// Создать случайную головоломку и нарисовать ее |
81 |
for (int i = 0; i < puzzleLength; i++) |
82 |
{ |
83 |
// Используя перемещение курсора рисуем строки в таблице головоломки |
84 |
if (i % Math.Floor(Math.Sqrt(puzzleLength)) == 0) |
85 |
{ |
86 |
Console.CursorTop = top++; |
87 |
Console.CursorLeft = left; |
88 |
} |
89 |
90 |
if (Vowels.Contains(letters[i])) |
91 |
Console.ForegroundColor = ConsoleColor.DarkRed; |
92 |
else |
93 |
Console.ForegroundColor = ConsoleColor.DarkBlue; |
94 |
95 |
Console.Write(" {0} ", letters[i]); |
96 |
} |
97 |
98 |
Console.ResetColor(); |
99 |
100 |
Console.CursorTop = oldTop; |
101 |
Console.CursorLeft = oldLeft; |
102 |
} |
103 |
} |
104 |
} |
Файл WordChecker.cs:
1 |
using System; |
2 |
using System.Collections.Generic; |
3 |
using System.Linq; |
4 |
5 |
namespace WordFinder |
6 |
{ |
7 |
/// <summary> |
8 |
/// Класс WordChecker содержит список правильных слов и проверяет |
9 |
/// буквы введенные пользователем с буквами из таблицы |
10 |
/// </summary> |
11 |
class WordChecker |
12 |
{ |
13 |
/// <summary> |
14 |
/// Список слов для проверки |
15 |
/// </summary> |
16 |
private List<string> words = new List<string>(); |
17 |
18 |
/// <summary> |
19 |
/// Найденные слова |
20 |
/// </summary> |
21 |
private List<string> foundWords = new List<string>(); |
22 |
23 |
/// <summary> |
24 |
/// Возвращает количество найденных слов |
25 |
/// </summary> |
26 |
public int NumberFound |
27 |
{ |
28 |
get { return foundWords.Count; } |
29 |
} |
30 |
31 |
/// <summary> |
32 |
/// Возвращает найденные слова |
33 |
/// </summary> |
34 |
public IEnumerable<string> FoundWords { |
35 |
get |
36 |
{ |
37 |
List<string> value = new List<string>(); |
38 |
foreach (string word in foundWords) |
39 |
{ |
40 |
value.Add(word.ToUpper()); |
41 |
} |
42 |
return value; |
43 |
} |
44 |
} |
45 |
46 |
/// <summary> |
47 |
/// Конструктор WordChecker |
48 |
/// </summary> |
49 |
/// <param name="validWords">Список правильных слов</param> |
50 |
public WordChecker(IEnumerable<string> validWords) |
51 |
{ |
52 |
// Перевести слово в верхний регист и добавить в список |
53 |
foreach(string word in validWords) |
54 |
this.words.Add(word.ToUpper()); |
55 |
} |
56 |
57 |
/// <summary> |
58 |
/// Проверить введенное польвателем слова с головоломной |
59 |
/// </summary> |
60 |
/// <param name="word">Проверяемое слово</param> |
61 |
/// <param name="puzzle">Ссылка на объект головоломки</param> |
62 |
public void CheckAnswer(string word, Puzzle puzzle) |
63 |
{ |
64 |
// Проверяем что слово не пустое, что такого слова еще нет и в нем содержится не менее 4-х букв |
65 |
if (String.IsNullOrEmpty(word) || foundWords.Contains(word) || word.Length < 4) |
66 |
return; |
67 |
68 |
// Переводим слово в верхний регистр -- строка upperCaseWord должна быть уничтожена, |
69 |
// и поэтому нам нужна копия. Мы удаляем каждую найденную букву, пока в слове не останется букв. |
70 |
// Если буквы останутся, то слово считается не верным |
71 |
string upperCaseWord = word.ToUpper(); |
72 |
if (words.Contains(upperCaseWord)) |
73 |
{ |
74 |
// Проверяем, что слово состоит из букв головоломки |
75 |
foreach (char letter in puzzle.Letters) |
76 |
{ |
77 |
// Удаляем букву, если она содержится в головоломке |
78 |
if (upperCaseWord.Contains(letter)) |
79 |
{ |
80 |
// Если слово начинается с буквы, иначе Substring(0, index - 1) выдаст исключение |
81 |
if (upperCaseWord.StartsWith(letter.ToString())) |
82 |
upperCaseWord = upperCaseWord.Substring(1); |
83 |
else |
84 |
{ |
85 |
int index = upperCaseWord.IndexOf(letter); |
86 |
upperCaseWord = upperCaseWord.Substring(0, index - 1) + upperCaseWord.Substring(index + 1); |
87 |
} |
88 |
} |
89 |
} |
90 |
} |
91 |
92 |
// Если из слова удалены все буквы, то считается что слово найдено. |
93 |
// Издаем звуковой сигнал и добавляем слово в список найденных. |
94 |
if (String.IsNullOrEmpty(upperCaseWord)) |
95 |
{ |
96 |
Console.Beep(); |
97 |
foundWords.Add(word); |
98 |
} |
99 |
} |
100 |
} |
101 |
} |