diff --git a/TicTacToe/Cell.axaml b/TicTacToe/Cell.axaml
index f01d175..46686be 100644
--- a/TicTacToe/Cell.axaml
+++ b/TicTacToe/Cell.axaml
@@ -5,6 +5,10 @@
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="TicTacToe.Cell"
BorderThickness="2"
- BorderBrush="White">
- X
+ BorderBrush="White"
+ FontSize="40">
+
diff --git a/TicTacToe/Cell.axaml.cs b/TicTacToe/Cell.axaml.cs
index d18fb3f..6429fc5 100644
--- a/TicTacToe/Cell.axaml.cs
+++ b/TicTacToe/Cell.axaml.cs
@@ -1,11 +1,26 @@
-using Avalonia.Controls;
+using System.Net.Mime;
+using Avalonia.Controls;
+using Avalonia.Interactivity;
+using Avalonia.Media;
namespace TicTacToe;
public partial class Cell : UserControl
{
+ public required Game Game;
+
public Cell()
{
InitializeComponent();
}
+
+ private void Text_OnClick(object? sender, RoutedEventArgs e)
+ {
+ if(Text.Content != null)
+ return;
+ Text.Content = Game.CurrentPlayerSign;
+ Game.Turn(GetValue(Grid.RowProperty), GetValue(Grid.ColumnProperty));
+ IsEnabled = false;
+ Foreground = Brushes.White;
+ }
}
\ No newline at end of file
diff --git a/TicTacToe/Game.cs b/TicTacToe/Game.cs
new file mode 100644
index 0000000..23c4c6a
--- /dev/null
+++ b/TicTacToe/Game.cs
@@ -0,0 +1,135 @@
+using System;
+using System.Collections;
+
+namespace TicTacToe;
+
+public class Game
+{
+ /* 0 1 2 ...
+ * 0 [ ][ ][ ]
+ * 1 [ ][ ][ ]
+ * 2 [ ][ ][ ]
+ * ...
+ */
+ public char[][] GameField => _gameField;
+ public char CurrentPlayerSign => _players[_nextPlayerIndex];
+
+ public event Action? PlayerWon;
+
+ private char[][] _gameField;
+ private char[] _players = { 'X', '0' };
+ private int _nextPlayerIndex = 0;
+ private int _winSequenceLength;
+ private int _sideLength;
+
+ public Game(int gameFieldSideSize, int winSequenceLength)
+ {
+ _winSequenceLength = winSequenceLength;
+ _sideLength = gameFieldSideSize;
+ _gameField = new char[gameFieldSideSize][];
+ for (int y = 0; y < gameFieldSideSize; y++)
+ {
+ _gameField[y] = new char[gameFieldSideSize];
+ for (int x = 0; x < gameFieldSideSize; x++)
+ _gameField[y][x] = '\0';
+ }
+ }
+
+ public void Turn(int cell_row, int cell_col)
+ {
+ if (_gameField[cell_row][cell_col] != '\0')
+ throw new Exception("the cell was already used");
+ _gameField[cell_row][cell_col] = CurrentPlayerSign;
+ if (CheckWinCombination(cell_row, cell_col))
+ {
+ PlayerWon?.Invoke(CurrentPlayerSign);
+ return;
+ }
+
+ _nextPlayerIndex++;
+ if (_nextPlayerIndex >= _players.Length)
+ _nextPlayerIndex = 0;
+ }
+
+ private bool CheckWinCombination(int cell_row, int cell_col)
+ {
+ int sequenceLength = 0;
+ // up
+ for (int row = cell_row; row > -1; row--)
+ {
+ if(_gameField[row][cell_col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ // down
+ sequenceLength--;
+ for (int row = cell_row; row < _sideLength; row++)
+ {
+ if(_gameField[row][cell_col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ sequenceLength = 0;
+
+ // left
+ for (int col = cell_col; col > -1; col--)
+ {
+ if(_gameField[cell_row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ // right
+ sequenceLength--;
+ for (int col = cell_col; col < _sideLength; col++)
+ {
+ if(_gameField[cell_row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ sequenceLength = 0;
+
+ // up-left
+ for (int row = cell_row, col = cell_col; row > -1 && col > -1; row--, col--)
+ {
+ if(_gameField[row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ // down-right
+ sequenceLength--;
+ for (int row = cell_row, col = cell_col; col < _sideLength && row < _sideLength; row++, col++)
+ {
+ if(_gameField[row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ sequenceLength = 0;
+
+
+ // up-right
+ for (int row = cell_row, col = cell_col; row > -1 && col < _sideLength; row--, col++)
+ {
+ if(_gameField[row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+ // down-left
+ sequenceLength--;
+ for (int row = cell_row, col = cell_col; col > -1 && row < _sideLength; row++, col--)
+ {
+ if(_gameField[row][col] != CurrentPlayerSign)
+ break;
+ if (++sequenceLength == _winSequenceLength)
+ return true;
+ }
+
+ return false;
+ }
+}
\ No newline at end of file
diff --git a/TicTacToe/MainWindow.axaml b/TicTacToe/MainWindow.axaml
index bc01056..e7bbb76 100644
--- a/TicTacToe/MainWindow.axaml
+++ b/TicTacToe/MainWindow.axaml
@@ -2,17 +2,23 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
+ mc:Ignorable="d"
x:Class="TicTacToe.MainWindow"
Title="TicTacToe"
- FontSize="20">
+ FontSize="20"
+ Width="600"
+ Height="600"
+ d:DesignHeight="600"
+ d:DesignWidth="600">
40 *
-
+
+
diff --git a/TicTacToe/MainWindow.axaml.cs b/TicTacToe/MainWindow.axaml.cs
index 0a6d1af..c0a5782 100644
--- a/TicTacToe/MainWindow.axaml.cs
+++ b/TicTacToe/MainWindow.axaml.cs
@@ -6,15 +6,35 @@ namespace TicTacToe;
public partial class MainWindow : Window
{
+ private Game _game = new(3, 3);
+
public MainWindow()
{
InitializeComponent();
+ DrawGame();
+ _game.PlayerWon += ShowWin;
}
-
private void RestartButton_OnClick(object? sender, RoutedEventArgs e)
{
int size = Convert.ToInt32(SizeTextBox.Text);
+ _game = new Game(size, size);
+ _game.PlayerWon += ShowWin;
+ DrawGame();
+ }
+
+ private void ShowWin(char playerChar)
+ {
+ GameGrid.IsVisible = false;
+ WinPanel.IsVisible = true;
+ WinText.Text = $"Player {playerChar} won!!1!";
+ }
+
+ private void DrawGame()
+ {
+ GameGrid.IsVisible = true;
+ WinPanel.IsVisible = false;
+ int size = _game.GameField.Length;
GameGrid.Children.Clear();
GameGrid.RowDefinitions = new RowDefinitions();
for(int y=0; y