Skip to content

Commit

Permalink
Prepare release
Browse files Browse the repository at this point in the history
  • Loading branch information
ProMix0 committed May 20, 2022
1 parent edd93e6 commit 3bb1895
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 46 deletions.
20 changes: 11 additions & 9 deletions CrossesZeroes/Abstractions/IPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,25 +7,27 @@ namespace CrossesZeroes.Abstractions
/// </summary>
public interface IPlayer
{
/// <summary>
/// Ставит знак хода для игрока (крестик или нолик)
/// </summary>
/// <param name="mark">Вид знака</param>
void Init(CellState mark, ICrossesZeroesField field);

void NotifyFieldChange(Point point);

/// <summary>
/// Метод хода для игрока
/// </summary>
/// <param name="field">Текущее состояние поля</param>
/// <returns>Точка, которая должна быть отмечена в результате хода</returns>
Task<Point> Turn(ICrossesZeroesField field);

Task<bool> IsRepeatWanted();
Task<Point> Turn();

/// <summary>
/// Метод, сообщающий игроку о завершении игры
/// </summary>
/// <param name="victory">Победил ли данный игрок</param>
void ReportEnd(bool victory, ICrossesZeroesField field);
void ReportEnd(bool victory);

/// <summary>
/// Ставит знак хода для игрока (крестик или нолик)
/// </summary>
/// <param name="mark">Вид знака</param>
void Init(CellState mark);
Task<bool> IsRepeatWanted();
}
}
16 changes: 12 additions & 4 deletions CrossesZeroes/Classes/AiPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -30,13 +31,15 @@ public AiPlayer(IOptions<AiPlayerBehaviour> 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<Point> Turn(ICrossesZeroesField field)
public Task<Point> Turn()
{
//Перебор всех клеток в поиске свободных
for (int i = 0; i < field.Height; i++)
Expand All @@ -49,6 +52,11 @@ public Task<Point> Turn(ICrossesZeroesField field)
public Task<bool> IsRepeatWanted() =>
Task.FromResult(behaviour.wantRepeat);

public void NotifyFieldChange(Point point)
{
//throw new NotImplementedException();
}

public class AiPlayerBehaviour
{
public bool wantRepeat;
Expand Down
20 changes: 14 additions & 6 deletions CrossesZeroes/Classes/ConsolePlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,23 @@ namespace CrossesZeroes.Classes
/// </summary>
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<Point> Turn(ICrossesZeroesField field)
public Task<Point> 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");
//Ожидание ввода корректных координат хода
Expand All @@ -48,7 +51,7 @@ public Task<Point> Turn(ICrossesZeroesField field)
}
}

private void PrintField(ICrossesZeroesField field, string header = "")
private void PrintField(string header = "")
{
Console.Clear();

Expand All @@ -74,5 +77,10 @@ public Task<bool> IsRepeatWanted()
Console.WriteLine("Restart? (Y/N)");
return Task.FromResult(Console.ReadKey().Key == ConsoleKey.Y);
}

public void NotifyFieldChange(Point point)
{
PrintField();
}
}
}
30 changes: 18 additions & 12 deletions CrossesZeroes/Classes/CrossesZeroesGame.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -28,11 +28,17 @@ public CrossesZeroesGame(IPlayer player1, IPlayer player2, ICrossesZeroesField f
public async override Task<bool> 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;
Expand All @@ -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;
}
Expand All @@ -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();
}
Expand Down
27 changes: 20 additions & 7 deletions CrossesZeroes/Services/CrossesZeroesLoopService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
44 changes: 36 additions & 8 deletions WpfClient/WpfPlayer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ public class WpfPlayer : IRealPlayer
protected Button[,]? btnMatr = null;
protected TaskCompletionSource<Button>? btnCompletionSource = null;

private ICrossesZeroesField field;

public WpfPlayer()
{
// Create a thread
Expand Down Expand Up @@ -44,15 +46,17 @@ public WpfPlayer()
//Console.WriteLine("Client isn't null");
}

public void ReportEnd(bool victory, ICrossesZeroesField field)
public void ReportEnd(bool victory)
{
Dispatcher.FromThread(windowThread).Invoke(() =>
client!.StateLine.Text = $"You {(victory ? "win" : "lose")}!");
PrintField(field);
//PrintField(field);
}

public void Init(CellState mark)
public void Init(CellState mark, ICrossesZeroesField field)
{
this.field = field;

string markStr = mark switch
{
CellState.Cross => "cross",
Expand All @@ -68,14 +72,17 @@ public void Init(CellState mark)
{
for (int i = 0; i < btnMatr!.GetLength(0); i++)
for (int j = 0; j < btnMatr!.GetLength(1); j++)
{
btnMatr![i, j].Content = ' ';
btnMatr![i, j].IsEnabled = true;
}
});
}

public async Task<CrossesZeroes.Common.Point> Turn(ICrossesZeroesField field)
public async Task<CrossesZeroes.Common.Point> Turn()
{
EnsureGridSize(field.Height, field.Width);
PrintField(field);
//PrintField(field);

btnCompletionSource = new();
Button button = await btnCompletionSource.Task;
Expand Down Expand Up @@ -138,7 +145,11 @@ protected void ButtonClick(object sender, RoutedEventArgs e)
{
if (btnCompletionSource == null) return;

btnCompletionSource.TrySetResult((sender as Button)!);
Button button = (sender as Button)!;

btnCompletionSource.TrySetResult(button);

button.IsEnabled = false;
}

public Task<bool> IsRepeatWanted()
Expand All @@ -147,14 +158,31 @@ public Task<bool> IsRepeatWanted()

Dispatcher.FromThread(windowThread).InvokeAsync(() =>
{
Window dialog = new RepeatDialog();
dialog.Owner = client as Window;
Window dialog = new RepeatDialog
{
Owner = client as Window
};

bool value = dialog.ShowDialog()!.Value;
completion.SetResult(value);
});

return completion.Task;
}

public void NotifyFieldChange(CrossesZeroes.Common.Point point)
{
Dispatcher.FromThread(windowThread).Invoke(() =>
{
int i = point.x, j = point.y;
btnMatr![i, j].Content = field[i, j] switch
{
CellState.Cross => 'X',
CellState.Zero => '0',
_ => ' '
};
btnMatr![i, j].IsEnabled = false;
});
}
}
}

0 comments on commit 3bb1895

Please sign in to comment.