From 3bb18952ddb76098a009d5edecc6cfa2389dc55e Mon Sep 17 00:00:00 2001 From: ProMix0 Date: Fri, 20 May 2022 22:02:47 +0700 Subject: [PATCH] Prepare release --- CrossesZeroes/Abstractions/IPlayer.cs | 20 +++++---- CrossesZeroes/Classes/AiPlayer.cs | 16 +++++-- CrossesZeroes/Classes/ConsolePlayer.cs | 20 ++++++--- CrossesZeroes/Classes/CrossesZeroesGame.cs | 30 ++++++++----- .../Services/CrossesZeroesLoopService.cs | 27 +++++++++--- WpfClient/WpfPlayer.cs | 44 +++++++++++++++---- 6 files changed, 111 insertions(+), 46 deletions(-) diff --git a/CrossesZeroes/Abstractions/IPlayer.cs b/CrossesZeroes/Abstractions/IPlayer.cs index 04c3d67..5188c85 100644 --- a/CrossesZeroes/Abstractions/IPlayer.cs +++ b/CrossesZeroes/Abstractions/IPlayer.cs @@ -7,25 +7,27 @@ namespace CrossesZeroes.Abstractions /// public interface IPlayer { + /// + /// Ставит знак хода для игрока (крестик или нолик) + /// + /// Вид знака + void Init(CellState mark, ICrossesZeroesField field); + + void NotifyFieldChange(Point point); + /// /// Метод хода для игрока /// /// Текущее состояние поля /// Точка, которая должна быть отмечена в результате хода - Task Turn(ICrossesZeroesField field); - - Task IsRepeatWanted(); + Task Turn(); /// /// Метод, сообщающий игроку о завершении игры /// /// Победил ли данный игрок - void ReportEnd(bool victory, ICrossesZeroesField field); + void ReportEnd(bool victory); - /// - /// Ставит знак хода для игрока (крестик или нолик) - /// - /// Вид знака - void Init(CellState mark); + Task IsRepeatWanted(); } } \ No newline at end of file diff --git a/CrossesZeroes/Classes/AiPlayer.cs b/CrossesZeroes/Classes/AiPlayer.cs index 2d16ae5..2c4ef54 100644 --- a/CrossesZeroes/Classes/AiPlayer.cs +++ b/CrossesZeroes/Classes/AiPlayer.cs @@ -15,6 +15,7 @@ namespace CrossesZeroes.Classes public class AiPlayer : IAiPlayer { private readonly AiPlayerBehaviour behaviour; + private ICrossesZeroesField field; public AiPlayer() : this(Options.Create(new AiPlayerBehaviour() @@ -30,13 +31,15 @@ public AiPlayer(IOptions behaviour) this.behaviour = behaviour.Value; } - public void ReportEnd(bool victory, ICrossesZeroesField field) + public void ReportEnd(bool victory) { } - public void Init(CellState mark) - { } + public void Init(CellState mark, ICrossesZeroesField field) + { + this.field = field; + } - public Task Turn(ICrossesZeroesField field) + public Task Turn() { //Перебор всех клеток в поиске свободных for (int i = 0; i < field.Height; i++) @@ -49,6 +52,11 @@ public Task Turn(ICrossesZeroesField field) public Task IsRepeatWanted() => Task.FromResult(behaviour.wantRepeat); + public void NotifyFieldChange(Point point) + { + //throw new NotImplementedException(); + } + public class AiPlayerBehaviour { public bool wantRepeat; diff --git a/CrossesZeroes/Classes/ConsolePlayer.cs b/CrossesZeroes/Classes/ConsolePlayer.cs index 6f4721b..35733a8 100644 --- a/CrossesZeroes/Classes/ConsolePlayer.cs +++ b/CrossesZeroes/Classes/ConsolePlayer.cs @@ -13,20 +13,23 @@ namespace CrossesZeroes.Classes /// public class ConsolePlayer : IRealPlayer { - public void ReportEnd(bool victory, ICrossesZeroesField field) + private ICrossesZeroesField field; + + public void ReportEnd(bool victory) { - PrintField(field, victory ? "You win!" : "You lose..."); + PrintField(victory ? "You win!" : "You lose..."); } private CellState mark; - public void Init(CellState mark) + public void Init(CellState mark,ICrossesZeroesField field) { this.mark = mark; + this.field = field; } - public Task Turn(ICrossesZeroesField field) + public Task Turn() { - PrintField(field, mark == CellState.Cross ? "You are cross!" : "You are zero!"); + PrintField(mark == CellState.Cross ? "You are cross!" : "You are zero!"); Console.WriteLine($"Enter turn coords (zero-based)\nMust be from 0 to {field.Height - 1} and from 0 to {field.Width - 1}\nAlso must be empty"); //Ожидание ввода корректных координат хода @@ -48,7 +51,7 @@ public Task Turn(ICrossesZeroesField field) } } - private void PrintField(ICrossesZeroesField field, string header = "") + private void PrintField(string header = "") { Console.Clear(); @@ -74,5 +77,10 @@ public Task IsRepeatWanted() Console.WriteLine("Restart? (Y/N)"); return Task.FromResult(Console.ReadKey().Key == ConsoleKey.Y); } + + public void NotifyFieldChange(Point point) + { + PrintField(); + } } } diff --git a/CrossesZeroes/Classes/CrossesZeroesGame.cs b/CrossesZeroes/Classes/CrossesZeroesGame.cs index b57fafb..89972da 100644 --- a/CrossesZeroes/Classes/CrossesZeroesGame.cs +++ b/CrossesZeroes/Classes/CrossesZeroesGame.cs @@ -18,8 +18,8 @@ public CrossesZeroesGame(IPlayer player1, IPlayer player2, ICrossesZeroesField f ///Вызов конструктора базового класса с параметрами : base(player1, player2, field) { - cross.Init(CellState.Cross); - zero.Init(CellState.Zero); + cross.Init(CellState.Cross, field.AsReadonly()); + zero.Init(CellState.Zero, field.AsReadonly()); } private bool gameCompleted = false; @@ -28,11 +28,17 @@ public CrossesZeroesGame(IPlayer player1, IPlayer player2, ICrossesZeroesField f public async override Task Turn() { if (gameCompleted) return false; - field.Set(await cross.Turn(field.AsReadonly()), CellState.Cross); + Point turnResult = await cross.Turn(); + field.Set(turnResult, CellState.Cross); + zero.NotifyFieldChange(turnResult); + cross.NotifyFieldChange(turnResult); CheckWin(); if (gameCompleted) return false; - field.Set(await zero.Turn(field.AsReadonly()), CellState.Zero); + turnResult = await zero.Turn(); + field.Set(turnResult, CellState.Zero); + cross.NotifyFieldChange(turnResult); + zero.NotifyFieldChange(turnResult); CheckWin(); return true; @@ -45,18 +51,18 @@ void CheckWin() switch (winner) { case CellState.Empty: - cross.ReportEnd(false, field); - zero.ReportEnd(false, field); + cross.ReportEnd(false); + zero.ReportEnd(false); gameCompleted = true; break; case CellState.Cross: - cross.ReportEnd(true, field); - zero.ReportEnd(false, field); + cross.ReportEnd(true); + zero.ReportEnd(false); gameCompleted = true; break; case CellState.Zero: - cross.ReportEnd(false, field); - zero.ReportEnd(true, field); + cross.ReportEnd(false); + zero.ReportEnd(true); gameCompleted = true; break; } @@ -71,8 +77,8 @@ public override void Restart() //Смена знака игроков (zero, cross) = (cross, zero); - cross.Init(CellState.Cross); - zero.Init(CellState.Zero); + cross.Init(CellState.Cross, field.AsReadonly()); + zero.Init(CellState.Zero, field.AsReadonly()); field.Clear(); } diff --git a/CrossesZeroes/Services/CrossesZeroesLoopService.cs b/CrossesZeroes/Services/CrossesZeroesLoopService.cs index 327c2ee..cd8d1ac 100644 --- a/CrossesZeroes/Services/CrossesZeroesLoopService.cs +++ b/CrossesZeroes/Services/CrossesZeroesLoopService.cs @@ -22,18 +22,31 @@ public CrossesZeroesLoopService(CrossesZeroesAbstract game, IHostLifetime lifeti protected async override Task ExecuteAsync(CancellationToken token) { - while (!token.IsCancellationRequested) + try { - while (!token.IsCancellationRequested && await game.Turn()) - token.ThrowIfCancellationRequested(); + while (!token.IsCancellationRequested) + { + while (!token.IsCancellationRequested && await game.Turn()) + token.ThrowIfCancellationRequested(); - bool restart = await game.IsRestartWanted(); - if (!restart) break; + bool restart = await game.IsRestartWanted(); + if (!restart) break; - game.Restart(); + game.Restart(); + } + + await lifetime.StopAsync(token); } + catch (Exception ex) + { + Console.WriteLine(ex.GetType()); + Console.WriteLine(); - await lifetime.StopAsync(token); + Console.WriteLine(ex.Message); + Console.WriteLine(); + + Console.WriteLine(ex.StackTrace); + } } } } diff --git a/WpfClient/WpfPlayer.cs b/WpfClient/WpfPlayer.cs index 9f4bd7d..1a09f76 100644 --- a/WpfClient/WpfPlayer.cs +++ b/WpfClient/WpfPlayer.cs @@ -17,6 +17,8 @@ public class WpfPlayer : IRealPlayer protected Button[,]? btnMatr = null; protected TaskCompletionSource