/
d4nil
/
Konenkov_2413_Course_Work
Обзор
Документация
Войти
/
d4nil
/
Konenkov_2413_Course_Work
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
Game
TapTapDash.Console/Program.cs
428 строк
20 KB
Konenkov Daniel
fix: исправлено окно окончания игры в консольном режиме
09 янв 2026, 22:45
09 янв 2026, 22:45
8fd20bd
Код
Авторство
О чём код?
using System; using TapTapDash.Console.InputHandlers; using TapTapDash.Console.Views; using TapTapDash.Core.Controllers; using TapTapDash.Core.Models; using HowToPlayController = TapTapDash.Core.Controllers.HowToPlayController; using HighScoresController = TapTapDash.Core.Controllers.HighScoresController; using GameController = TapTapDash.Core.Controllers.GameController; using PauseMenuController = TapTapDash.Core.Controllers.PauseMenuController; using GameOverController = TapTapDash.Core.Controllers.GameOverController; namespace TapTapDash.Console; /// <summary> /// Точка входа в консольное приложение /// </summary> class Program { static void Main(string[] args) { // Создаем компоненты MVC для главного меню // Model и Controller из общего модуля Core var model = new MainMenuModel(); var view = new MainMenuView(model); var controller = new MainMenuController(model, view); // Создаем обработчик ввода для консоли var inputHandler = new ConsoleInputHandler(controller); // Используем ManualResetEvent для ожидания завершения приложения var exitEvent = new System.Threading.ManualResetEventSlim(false); // Подписываемся на событие выбора пункта меню controller.OnMenuItemSelected += (menuItem) => { if (menuItem == "Выход") { // Останавливаем обработку ввода inputHandler.StopInputHandling(); exitEvent.Set(); } else if (menuItem == "Как играть") { // Переход на экран "Как играть" ShowHowToPlayScreen(controller, inputHandler); } else if (menuItem == "Рекорды") { // Переход на экран рекордов ShowHighScoresScreen(controller, inputHandler); } else if (menuItem == "Новая игра") { // Запуск новой игры ShowGameScreen(controller, inputHandler); } }; // Инициализируем контроллер controller.Initialize(); // Запускаем обработку ввода inputHandler.StartInputHandling(); // Основной цикл программы - обработка ввода в основном потоке while (!exitEvent.IsSet) { // Обрабатываем ввод (неблокирующая проверка) inputHandler.ProcessInput(); // Небольшая задержка, чтобы не нагружать CPU System.Threading.Thread.Sleep(10); } } /// <summary> /// Показ экрана "Как играть" /// </summary> private static void ShowHowToPlayScreen(MainMenuController mainMenuController, ConsoleInputHandler mainMenuInputHandler) { // Останавливаем обработку ввода главного меню mainMenuInputHandler.StopInputHandling(); // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Создаем компоненты MVC для экрана "Как играть" var howToPlayModel = new HowToPlayModel(); var howToPlayView = new HowToPlayView(howToPlayModel); var howToPlayController = new HowToPlayController(howToPlayModel, howToPlayView); // Создаем обработчик ввода для экрана "Как играть" var howToPlayInputHandler = new HowToPlayInputHandler(howToPlayController); // Используем ManualResetEvent для ожидания нажатия кнопки "Назад" var backEvent = new System.Threading.ManualResetEventSlim(false); // Подписываемся на событие нажатия кнопки "Назад" howToPlayController.OnBackButtonPressed += () => { // Останавливаем обработку ввода экрана "Как играть" howToPlayInputHandler.StopInputHandling(); // Сигнализируем о возврате в главное меню backEvent.Set(); }; // Инициализируем контроллер howToPlayController.Initialize(); // Запускаем обработку ввода howToPlayInputHandler.StartInputHandling(); // Основной цикл - обработка ввода в основном потоке while (!backEvent.IsSet) { // Обрабатываем ввод howToPlayInputHandler.ProcessInput(); // Небольшая задержка, чтобы не нагружать CPU System.Threading.Thread.Sleep(10); } // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Возвращаемся в главное меню mainMenuController.Initialize(); mainMenuInputHandler.StartInputHandling(); } /// <summary> /// Показ экрана рекордов /// </summary> private static void ShowHighScoresScreen(MainMenuController mainMenuController, ConsoleInputHandler mainMenuInputHandler) { // Останавливаем обработку ввода главного меню mainMenuInputHandler.StopInputHandling(); // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Создаем компоненты MVC для экрана рекордов var highScoresModel = new HighScoresModel(); var highScoresView = new HighScoresView(highScoresModel); var highScoresController = new HighScoresController(highScoresModel, highScoresView); // Создаем обработчик ввода для экрана рекордов var highScoresInputHandler = new HighScoresInputHandler(highScoresController); // Используем ManualResetEvent для ожидания нажатия кнопки "Назад" var backEvent = new System.Threading.ManualResetEventSlim(false); // Подписываемся на событие нажатия кнопки "Назад" highScoresController.OnBackButtonPressed += () => { // Останавливаем обработку ввода экрана рекордов highScoresInputHandler.StopInputHandling(); // Сигнализируем о возврате в главное меню backEvent.Set(); }; // Инициализируем контроллер highScoresController.Initialize(); // Запускаем обработку ввода highScoresInputHandler.StartInputHandling(); // Основной цикл - обработка ввода в основном потоке while (!backEvent.IsSet) { // Обрабатываем ввод (неблокирующая проверка) highScoresInputHandler.ProcessInput(); // Небольшая задержка, чтобы не нагружать CPU System.Threading.Thread.Sleep(10); } // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Возвращаемся в главное меню mainMenuController.Initialize(); mainMenuInputHandler.StartInputHandling(); } /// <summary> /// Показ экрана игры /// </summary> private static void ShowGameScreen(MainMenuController mainMenuController, ConsoleInputHandler mainMenuInputHandler) { // Останавливаем обработку ввода главного меню mainMenuInputHandler.StopInputHandling(); // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Создаем компоненты MVC для игры var gameModel = new GameModel(); var gameView = new GameView(gameModel); var gameController = new GameController(gameModel, gameView); // Создаем компоненты MVC для меню паузы var pauseMenuModel = new PauseMenuModel(); var pauseMenuView = new PauseMenuView(pauseMenuModel); var pauseMenuController = new PauseMenuController(pauseMenuModel, pauseMenuView); // Устанавливаем меню паузы в представление игры gameView.SetPauseMenuView(pauseMenuView); // Используем ManualResetEvent для ожидания завершения игры var gameOverEvent = new System.Threading.ManualResetEventSlim(false); // Объявляем переменную для обработчика ввода заранее GameInputHandler? gameInputHandler = null; // Создаем обработчик ввода для игры с прямой ссылкой на событие возврата gameInputHandler = new GameInputHandler(gameController); // Устанавливаем контроллер меню паузы в обработчик ввода gameInputHandler.SetPauseMenuController(pauseMenuController); // Подписываемся на события меню паузы pauseMenuController.OnMenuItemSelected += (menuItem) => { if (menuItem == "Продолжить") { // Продолжаем игру gameController.HandleResume(); } else if (menuItem == "Главное меню") { // Возвращаемся в главное меню gameController.HandleBackToMenu(); } }; gameController.OnBackToMenuPressed += () => { // Останавливаем обработку ввода игры gameInputHandler?.StopInputHandling(); // Останавливаем поток рендеринга gameView.StopRendering(); // Останавливаем игровой цикл gameController.Stop(); // Сигнализируем о возврате в главное меню gameOverEvent.Set(); }; // Переменная для хранения счета при поражении int? gameOverScore = null; // Создаем компоненты MVC для окна поражения заранее (но не инициализируем) GameOverModel? gameOverModel = null; GameOverView? gameOverView = null; GameOverController? gameOverController = null; GameOverInputHandler? gameOverInputHandler = null; bool gameOverUiInitialized = false; // Используем ManualResetEvent для ожидания возврата в главное меню из окна поражения var backToMenuFromGameOverEvent = new System.Threading.ManualResetEventSlim(false); // Подписываемся на событие завершения игры gameController.OnGameOver += (score) => { // Сохраняем счет для обработки в основном потоке gameOverScore = score; // Останавливаем игровой цикл gameController.Stop(); // НЕ останавливаем поток рендеринга сразу - он должен отрисовать окно поражения // Останавливаем обработку ввода игры ПЕРЕД созданием обработчика окна поражения gameInputHandler?.StopInputHandling(); // Сигнализируем о завершении игры для обработки в основном потоке gameOverEvent.Set(); }; // Инициализируем контроллер (запускает игровой цикл) gameController.Initialize(); // Запускаем поток рендеринга gameView.StartRendering(); // Запускаем обработку ввода gameInputHandler.StartInputHandling(); // Основной цикл - обработка ввода в основном потоке while (true) { // Если игра завершилась if (gameOverScore.HasValue) { if (!gameOverUiInitialized) { // Создаем компоненты MVC для окна поражения в основном потоке gameOverModel = new GameOverModel(gameOverScore.Value); gameOverView = new GameOverView(gameOverModel); gameOverController = new GameOverController(gameOverModel, gameOverView); // Устанавливаем окно поражения в представление игры для отображения в RenderLoop gameView.SetGameOverView(gameOverView); // Подписываемся на событие возврата в главное меню из окна поражения gameOverController.OnBackToMenuPressed += () => { gameOverInputHandler?.StopInputHandling(); backToMenuFromGameOverEvent.Set(); gameOverEvent.Set(); // Также сигнализируем основному циклу }; // Инициализируем контроллер окна поражения gameOverController.Initialize(); // Очищаем буфер консоли от накопленных клавиш перед запуском обработчика окна поражения while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Создаем обработчик ввода для окна поражения gameOverInputHandler = new GameOverInputHandler(gameOverController); // Запускаем обработку ввода для окна поражения gameOverInputHandler.StartInputHandling(); gameOverUiInitialized = true; } // Обрабатываем ввод окна поражения, если обработчик создан if (gameOverInputHandler != null) { // Обрабатываем ввод окна поражения gameOverInputHandler.ProcessInput(); // Проверяем, нужно ли выйти из цикла (возврат в главное меню) if (backToMenuFromGameOverEvent.IsSet) { break; } } // Если обработчик еще не создан, просто ждем else { System.Threading.Thread.Sleep(10); } } // Если игра не завершена и не на паузе else if (!gameOverEvent.IsSet) { // Обрабатываем ввод игры gameInputHandler.ProcessInput(); } // Если gameOverEvent установлен, но нет счета, значит возврат в меню из игры else { break; } // Небольшая задержка, чтобы не нагружать CPU System.Threading.Thread.Sleep(10); } // Если игра завершилась, ждем возврата в главное меню из окна поражения if (gameOverScore.HasValue) { // Ожидаем возврата в главное меню из окна поражения backToMenuFromGameOverEvent.Wait(); // Небольшая задержка, чтобы RenderLoop успел отрисовать окно поражения System.Threading.Thread.Sleep(100); // Останавливаем поток рендеринга после отрисовки окна поражения gameView.StopRendering(); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } } // Небольшая задержка, чтобы поток обработки ввода полностью остановился System.Threading.Thread.Sleep(100); // Очищаем буфер консоли от накопленных клавиш while (System.Console.KeyAvailable) { System.Console.ReadKey(true); } // Возвращаемся в главное меню mainMenuController.Initialize(); mainMenuInputHandler.StartInputHandling(); } }