Game
This commit is contained in:
parent
1dbe2e1bb6
commit
7b345ba39c
@ -5,6 +5,10 @@
|
|||||||
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
|
||||||
x:Class="TicTacToe.Cell"
|
x:Class="TicTacToe.Cell"
|
||||||
BorderThickness="2"
|
BorderThickness="2"
|
||||||
BorderBrush="White">
|
BorderBrush="White"
|
||||||
<TextBlock TextAlignment="Center" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="40">X</TextBlock>
|
FontSize="40">
|
||||||
|
<Button Name="Text" Click="Text_OnClick"
|
||||||
|
HorizontalContentAlignment="Center" VerticalContentAlignment="Center"
|
||||||
|
HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
|
||||||
|
</Button>
|
||||||
</UserControl>
|
</UserControl>
|
||||||
|
|||||||
@ -1,11 +1,26 @@
|
|||||||
using Avalonia.Controls;
|
using System.Net.Mime;
|
||||||
|
using Avalonia.Controls;
|
||||||
|
using Avalonia.Interactivity;
|
||||||
|
using Avalonia.Media;
|
||||||
|
|
||||||
namespace TicTacToe;
|
namespace TicTacToe;
|
||||||
|
|
||||||
public partial class Cell : UserControl
|
public partial class Cell : UserControl
|
||||||
{
|
{
|
||||||
|
public required Game Game;
|
||||||
|
|
||||||
public Cell()
|
public Cell()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
135
TicTacToe/Game.cs
Normal file
135
TicTacToe/Game.cs
Normal file
@ -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<char>? 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -2,17 +2,23 @@
|
|||||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
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"
|
x:Class="TicTacToe.MainWindow"
|
||||||
Title="TicTacToe"
|
Title="TicTacToe"
|
||||||
FontSize="20">
|
FontSize="20"
|
||||||
|
Width="600"
|
||||||
|
Height="600"
|
||||||
|
d:DesignHeight="600"
|
||||||
|
d:DesignWidth="600">
|
||||||
<Grid>
|
<Grid>
|
||||||
<Grid.RowDefinitions>40 *</Grid.RowDefinitions>
|
<Grid.RowDefinitions>40 *</Grid.RowDefinitions>
|
||||||
<StackPanel Orientation="Horizontal" Spacing="20">
|
<StackPanel Orientation="Horizontal" Spacing="20">
|
||||||
<Label Target="SizeTextBox" VerticalContentAlignment="Center">Size:</Label>
|
<Label Target="SizeTextBox" VerticalContentAlignment="Center">Size:</Label>
|
||||||
<TextBox Name="SizeTextBox"></TextBox>
|
<TextBox Name="SizeTextBox" Width="60"></TextBox>
|
||||||
<Button Click="RestartButton_OnClick">Restart</Button>
|
<Button Click="RestartButton_OnClick">Restart</Button>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Grid Grid.Row="1" Name="GameGrid"></Grid>
|
<Grid Grid.Row="1" Name="GameGrid"></Grid>
|
||||||
|
<StackPanel Grid.Row="1" Name="WinPanel" IsEnabled="False"
|
||||||
|
HorizontalAlignment="Center" VerticalAlignment="Center"><TextBlock Name="WinText"></TextBlock></StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Window>
|
</Window>
|
||||||
|
|||||||
@ -6,15 +6,35 @@ namespace TicTacToe;
|
|||||||
|
|
||||||
public partial class MainWindow : Window
|
public partial class MainWindow : Window
|
||||||
{
|
{
|
||||||
|
private Game _game = new(3, 3);
|
||||||
|
|
||||||
public MainWindow()
|
public MainWindow()
|
||||||
{
|
{
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
|
DrawGame();
|
||||||
|
_game.PlayerWon += ShowWin;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void RestartButton_OnClick(object? sender, RoutedEventArgs e)
|
private void RestartButton_OnClick(object? sender, RoutedEventArgs e)
|
||||||
{
|
{
|
||||||
int size = Convert.ToInt32(SizeTextBox.Text);
|
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.Children.Clear();
|
||||||
GameGrid.RowDefinitions = new RowDefinitions();
|
GameGrid.RowDefinitions = new RowDefinitions();
|
||||||
for(int y=0; y<size; y++)
|
for(int y=0; y<size; y++)
|
||||||
@ -25,11 +45,17 @@ public partial class MainWindow : Window
|
|||||||
for(int y=0; y<size; y++)
|
for(int y=0; y<size; y++)
|
||||||
for (int x = 0; x < size; x++)
|
for (int x = 0; x < size; x++)
|
||||||
{
|
{
|
||||||
var c = new Cell();
|
var cellView = new Cell
|
||||||
c.SetValue(Grid.ColumnProperty, x);
|
{
|
||||||
c.SetValue(Grid.RowProperty, y);
|
Game = _game
|
||||||
GameGrid.Children.Add(c);
|
};
|
||||||
|
cellView.SetValue(Grid.ColumnProperty, x);
|
||||||
|
cellView.SetValue(Grid.RowProperty, y);
|
||||||
|
char cellValue = _game.GameField[y][x];
|
||||||
|
if (cellValue != '\0')
|
||||||
|
cellView.Text.Content = cellValue.ToString();
|
||||||
|
GameGrid.Children.Add(cellView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
Loading…
Reference in New Issue
Block a user