[Fix] UI Logic

This commit is contained in:
2026-06-06 22:33:15 +07:00
parent f4ecf8b6f9
commit fdb22e9213
134 changed files with 5367 additions and 269 deletions
@@ -0,0 +1,69 @@
using System;
namespace Minesweeper.Commands
{
public sealed class GameCommandDispatcher : IGameCommandDispatcher
{
private readonly SelectFieldCommandHandler selectFieldHandler;
private readonly StartGameCommandHandler startGameHandler;
private readonly OpenCellCommandHandler openCellHandler;
private readonly ToggleFlagCommandHandler toggleFlagHandler;
private readonly RestartCommandHandler restartHandler;
private readonly PauseCommandHandler pauseHandler;
private readonly ResumeCommandHandler resumeHandler;
private readonly GoToMenuCommandHandler goToMenuHandler;
public GameCommandDispatcher(
SelectFieldCommandHandler selectFieldHandler,
StartGameCommandHandler startGameHandler,
OpenCellCommandHandler openCellHandler,
ToggleFlagCommandHandler toggleFlagHandler,
RestartCommandHandler restartHandler,
PauseCommandHandler pauseHandler,
ResumeCommandHandler resumeHandler,
GoToMenuCommandHandler goToMenuHandler)
{
this.selectFieldHandler = selectFieldHandler;
this.startGameHandler = startGameHandler;
this.openCellHandler = openCellHandler;
this.toggleFlagHandler = toggleFlagHandler;
this.restartHandler = restartHandler;
this.pauseHandler = pauseHandler;
this.resumeHandler = resumeHandler;
this.goToMenuHandler = goToMenuHandler;
}
public void Dispatch<TCommand>(TCommand command) where TCommand : IGameCommand
{
switch (command)
{
case SelectFieldCommand selectFieldCommand:
selectFieldHandler.Handle(selectFieldCommand);
return;
case StartGameCommand startGameCommand:
startGameHandler.Handle(startGameCommand);
return;
case OpenCellCommand openCellCommand:
openCellHandler.Handle(openCellCommand);
return;
case ToggleFlagCommand toggleFlagCommand:
toggleFlagHandler.Handle(toggleFlagCommand);
return;
case RestartCommand restartCommand:
restartHandler.Handle(restartCommand);
return;
case PauseCommand pauseCommand:
pauseHandler.Handle(pauseCommand);
return;
case ResumeCommand resumeCommand:
resumeHandler.Handle(resumeCommand);
return;
case GoToMenuCommand goToMenuCommand:
goToMenuHandler.Handle(goToMenuCommand);
return;
default:
throw new InvalidOperationException($"No handler registered for command {typeof(TCommand).Name}.");
}
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6383c559964ec3545a7cd911b90586ce
@@ -0,0 +1,239 @@
using Minesweeper.Core;
using Minesweeper.ECS;
namespace Minesweeper.Commands
{
public sealed class SelectFieldCommandHandler : IGameCommandHandler<SelectFieldCommand>
{
private readonly IGameStateService gameStateService;
public SelectFieldCommandHandler(IGameStateService gameStateService)
{
this.gameStateService = gameStateService;
}
public void Handle(SelectFieldCommand command)
{
gameStateService.SetState(GameState.FieldSelection);
}
}
public sealed class StartGameCommandHandler : IGameCommandHandler<StartGameCommand>
{
private readonly IBoardEcsSyncService boardEcsSyncService;
private readonly IBoardService boardService;
private readonly IGamePauseService pauseService;
private readonly IGameStateService gameStateService;
private readonly IGameTimerService timerService;
public StartGameCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
{
this.boardService = boardService;
this.boardEcsSyncService = boardEcsSyncService;
this.pauseService = pauseService;
this.gameStateService = gameStateService;
this.timerService = timerService;
}
public void Handle(StartGameCommand command)
{
pauseService.Resume();
timerService.Reset();
boardService.InitializeEmptyBoard();
gameStateService.SetState(GameState.Preparing);
boardEcsSyncService.SyncBoard(boardService);
boardEcsSyncService.SyncGameState(gameStateService.Current, false);
}
}
public sealed class OpenCellCommandHandler : IGameCommandHandler<OpenCellCommand>
{
private readonly IBoardEcsSyncService boardEcsSyncService;
private readonly IBoardService boardService;
private readonly IGameStateService gameStateService;
private readonly IGamePauseService pauseService;
public OpenCellCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService, IGamePauseService pauseService)
{
this.boardService = boardService;
this.boardEcsSyncService = boardEcsSyncService;
this.gameStateService = gameStateService;
this.pauseService = pauseService;
}
public void Handle(OpenCellCommand command)
{
if (pauseService.IsPaused)
{
return;
}
var state = gameStateService.Current;
if (state != GameState.Preparing && state != GameState.Playing)
{
return;
}
if (state == GameState.Preparing)
{
if (boardService.TryGetCell(command.X, command.Y, out var cell) && cell.IsFlagged)
{
return;
}
if (!boardService.GenerateAfterFirstClick(command.X, command.Y))
{
return;
}
}
var result = boardService.OpenCell(command.X, command.Y);
if (result.Invalid || !result.Changed)
{
return;
}
if (result.HitMine)
{
gameStateService.SetState(GameState.Lost);
}
else if (result.Won)
{
gameStateService.SetState(GameState.Won);
}
else if (state == GameState.Preparing)
{
gameStateService.SetState(GameState.Playing);
}
boardEcsSyncService.SyncBoard(boardService);
boardEcsSyncService.SyncGameState(gameStateService.Current, boardService.IsGenerated);
}
}
public sealed class ToggleFlagCommandHandler : IGameCommandHandler<ToggleFlagCommand>
{
private readonly IBoardEcsSyncService boardEcsSyncService;
private readonly IBoardService boardService;
private readonly IGameStateService gameStateService;
private readonly IGamePauseService pauseService;
public ToggleFlagCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGameStateService gameStateService, IGamePauseService pauseService)
{
this.boardService = boardService;
this.boardEcsSyncService = boardEcsSyncService;
this.gameStateService = gameStateService;
this.pauseService = pauseService;
}
public void Handle(ToggleFlagCommand command)
{
if (pauseService.IsPaused)
{
return;
}
var state = gameStateService.Current;
if (state != GameState.Preparing && state != GameState.Playing)
{
return;
}
var result = boardService.ToggleFlag(command.X, command.Y);
if (result.Invalid || !result.Changed)
{
return;
}
boardEcsSyncService.SyncBoard(boardService);
boardEcsSyncService.SyncGameState(gameStateService.Current, boardService.IsGenerated);
}
}
public sealed class RestartCommandHandler : IGameCommandHandler<RestartCommand>
{
private readonly IBoardEcsSyncService boardEcsSyncService;
private readonly IBoardService boardService;
private readonly IGamePauseService pauseService;
private readonly IGameStateService gameStateService;
private readonly IGameTimerService timerService;
public RestartCommandHandler(IBoardService boardService, IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
{
this.boardService = boardService;
this.boardEcsSyncService = boardEcsSyncService;
this.pauseService = pauseService;
this.gameStateService = gameStateService;
this.timerService = timerService;
}
public void Handle(RestartCommand command)
{
pauseService.Resume();
timerService.Reset();
boardService.InitializeEmptyBoard();
gameStateService.SetState(GameState.Preparing);
boardEcsSyncService.SyncBoard(boardService);
boardEcsSyncService.SyncGameState(gameStateService.Current, false);
}
}
public sealed class PauseCommandHandler : IGameCommandHandler<PauseCommand>
{
private readonly IGamePauseService pauseService;
private readonly IGameStateService gameStateService;
public PauseCommandHandler(IGamePauseService pauseService, IGameStateService gameStateService)
{
this.pauseService = pauseService;
this.gameStateService = gameStateService;
}
public void Handle(PauseCommand command)
{
if (gameStateService.Current == GameState.Playing)
{
pauseService.Pause();
}
}
}
public sealed class ResumeCommandHandler : IGameCommandHandler<ResumeCommand>
{
private readonly IGamePauseService pauseService;
public ResumeCommandHandler(IGamePauseService pauseService)
{
this.pauseService = pauseService;
}
public void Handle(ResumeCommand command)
{
pauseService.Resume();
}
}
public sealed class GoToMenuCommandHandler : IGameCommandHandler<GoToMenuCommand>
{
private readonly IBoardEcsSyncService boardEcsSyncService;
private readonly IGamePauseService pauseService;
private readonly IGameStateService gameStateService;
private readonly IGameTimerService timerService;
public GoToMenuCommandHandler(IBoardEcsSyncService boardEcsSyncService, IGamePauseService pauseService, IGameStateService gameStateService, IGameTimerService timerService)
{
this.boardEcsSyncService = boardEcsSyncService;
this.pauseService = pauseService;
this.gameStateService = gameStateService;
this.timerService = timerService;
}
public void Handle(GoToMenuCommand command)
{
pauseService.Resume();
timerService.Reset();
gameStateService.SetState(GameState.FieldSelection);
boardEcsSyncService.SyncGameState(gameStateService.Current, false);
}
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 31bfefc0901594043aae51cabba89234
+60
View File
@@ -0,0 +1,60 @@
namespace Minesweeper.Commands
{
public readonly struct SelectFieldCommand : IGameCommand
{
public SelectFieldCommand(int width, int height, int minesCount)
{
Width = width;
Height = height;
MinesCount = minesCount;
}
public int Width { get; }
public int Height { get; }
public int MinesCount { get; }
}
public readonly struct StartGameCommand : IGameCommand
{
}
public readonly struct OpenCellCommand : IGameCommand
{
public OpenCellCommand(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
}
public readonly struct ToggleFlagCommand : IGameCommand
{
public ToggleFlagCommand(int x, int y)
{
X = x;
Y = y;
}
public int X { get; }
public int Y { get; }
}
public readonly struct RestartCommand : IGameCommand
{
}
public readonly struct PauseCommand : IGameCommand
{
}
public readonly struct ResumeCommand : IGameCommand
{
}
public readonly struct GoToMenuCommand : IGameCommand
{
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9bd93535958ca574999f8ec6de84baa3
+6
View File
@@ -0,0 +1,6 @@
namespace Minesweeper.Commands
{
public interface IGameCommand
{
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 50cd27fcb4d423e43b2a56cc23badbfb
@@ -0,0 +1,7 @@
namespace Minesweeper.Commands
{
public interface IGameCommandDispatcher
{
void Dispatch<TCommand>(TCommand command) where TCommand : IGameCommand;
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f1c291311029640428d2ea8820fdfeaa
@@ -0,0 +1,7 @@
namespace Minesweeper.Commands
{
public interface IGameCommandHandler<in TCommand> where TCommand : IGameCommand
{
void Handle(TCommand command);
}
}
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e7b5f5892af9c184ba720b2b3f352b32