Код клиента
MainWindow.xaml
<Window x:Class="XO.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="XO" Height="350" Width="525" ResizeMode="NoResize">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="250"/>
<ColumnDefinition Width="250"/>
</Grid.ColumnDefinitions>
<Border Name="cellMatrix" Grid.Column="0" BorderBrush="DeepSkyBlue" BorderThickness="3" CornerRadius="22" IsEnabled="False">
<Grid Name="grid">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Background="WhiteSmoke" Grid.Row="0" Grid.Column="0" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas0_0" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="1" Grid.Column="0" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas1_0" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="2" Grid.Column="0" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas2_0" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="0" Grid.Column="1" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas0_1" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="1" Grid.Column="1" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas1_1" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="2" Grid.Column="1" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas2_1" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="0" Grid.Column="2" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas0_2" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="1" Grid.Column="2" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas1_2" Height="90" Width="60"/>
</Button>
<Button Background="WhiteSmoke" Grid.Row="2" Grid.Column="2" BorderBrush="DeepSkyBlue" BorderThickness="3" Click="Cell_Click">
<Canvas Name="canvas2_2" Height="90" Width="60"/>
</Button>
</Grid>
</Border>
<StackPanel Grid.Column="1" Orientation="Vertical">
<Button Name="connectButton" Margin="0, 25, 0, 0" Height="25" Width="150" Content="Connect" Click="ConnectButton_Click"/>
<GroupBox Height="210" Margin="0, 20, 0, 0" Width="200">
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Orientation="Vertical">
<Label Content="You are owner of: " FontSize="10" VerticalAlignment="Center"/>
<TextBlock Name="gameStuffTextBlock" FontSize="50" VerticalAlignment="Center" HorizontalAlignment="Center"/>
</StackPanel>
<StackPanel Grid.Row="1" Orientation="Vertical">
<Label Content="Game status: " FontSize="10" VerticalAlignment="Center"/>
<TextBlock Name="gameStatusTextBlock" FontSize="20" VerticalAlignment="Center" HorizontalAlignment="Center" TextWrapping="Wrap"/>
</StackPanel>
</Grid>
</GroupBox>
</StackPanel>
</Grid>
</Window>
IView.cs
using System;
using Enums;
namespace XO
{
public interface IView
{
void SetCellStuff(Int32 cellRow, Int32 cellColumn, StuffType stuff);
void FreezeCellMatrix();
void UnfreezeCellMatrix();
void SetOwnerStuff(StuffType stuff);
void SetGameStatus(string status);
bool ConnectAbilityIsEnabled { get; set; }
}
}
IPresenter.cs
using System;
namespace XO
{
internal interface IPresenter
{
void Connect();
void ProgressMade(Int32 row, Int32 column);
}
}
MainWindow.xaml.cs
using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Shapes;
using Enums;
namespace XO
{
public partial class MainWindow : Window, IView
{
private IPresenter presenter;
public MainWindow()
{
InitializeComponent();
presenter = new TcpGamePresenter(this);
}
private void Cell_Click(object sender, RoutedEventArgs e)
{
var canvas = (Canvas)((Button)sender).Content;
presenter.ProgressMade(Int32.Parse(canvas.Name.Substring(6, 1)), Int32.Parse(canvas.Name.Substring(8, 1))); // OH FORGIVE ME GOD!!!!
}
private void ConnectButton_Click(object sender, RoutedEventArgs e)
{
presenter.Connect();
}
public void FreezeCellMatrix()
{
Dispatcher.BeginInvoke(new ThreadStart(delegate { cellMatrix.IsEnabled = false; }));
}
public void UnfreezeCellMatrix()
{
Dispatcher.BeginInvoke(new ThreadStart(delegate { cellMatrix.IsEnabled = true; }));
}
public void SetOwnerStuff(StuffType stuff)
{
Dispatcher.BeginInvoke(new ThreadStart(delegate { gameStuffTextBlock.Text = stuff.ToString(); }));
}
public void SetGameStatus(string status)
{
Dispatcher.BeginInvoke(new ThreadStart(delegate { gameStatusTextBlock.Text = status; }));
}
public bool ConnectAbilityIsEnabled
{
get
{
return connectButton.IsEnabled;
}
set
{
connectButton.IsEnabled = value;
}
}
public void SetCellStuff(int cellRow, int cellColumn, StuffType stuff)
{
Dispatcher.BeginInvoke(new ThreadStart(delegate
{
var button = grid.Children[cellColumn * grid.RowDefinitions.Count + cellRow] as Button;
var canvas = (Canvas)button.Content;
switch (stuff)
{
case StuffType.None:
canvas.Children.Clear();
button.IsEnabled = true;
break;
case StuffType.X:
PutXToCanvas(canvas);
button.IsEnabled = false;
break;
case StuffType.O:
PutOToCanvas(canvas);
button.IsEnabled = false;
break;
}
}));
}
private void PutXToCanvas(Canvas canvas)
{
var l1 = new Line();
var l2 = new Line();
l1.StrokeThickness = l2.StrokeThickness = 5;
l1.Stroke = l2.Stroke = Brushes.Black;
l1.X1 = l1.Y1 = l2.X2 = l2.Y1 = 10;
l2.X1 = l1.X2 = canvas.ActualWidth - 10;
l2.Y2 = l1.Y2 = canvas.ActualHeight - 10;
canvas.Children.Add(l1);
canvas.Children.Add(l2);
}
private void PutOToCanvas(Canvas canvas)
{
var o = new Ellipse();
o.Stroke = Brushes.Black;
o.StrokeThickness = 5;
o.Height = 80;
o.Width = 60;
o.Margin = new Thickness(0, 5, 0, 0);
canvas.Children.Add(o);
}
}
}
Presenter.cs
using System;
using System.IO;
using System.Net.Sockets;
using System.Threading;
using Enums;
namespace XO
{
public class TcpGamePresenter : IPresenter
{
private IView view;
private TcpClient client;
private StreamReader sr;
private StreamWriter sw;
private StuffType stuff, opponentStuff;
public TcpGamePresenter(IView view)
{
this.view = view;
}
public void Connect()
{
view.ConnectAbilityIsEnabled = false;
client = new TcpClient();
client.Connect("192.168.0.101", 3307);
var ns = client.GetStream();
sr = new StreamReader(ns);
sw = new StreamWriter(ns);
sw.AutoFlush = true;
ThreadPool.QueueUserWorkItem(x =>
{
while (ExecuteCommand(sr.ReadLine())) ;
sr.Close();
sw.Close();
ns.Close();
client.Close();
});
}
public void ProgressMade(int row, int column)
{
sw.WriteLine(String.Format("{0}/{1}/{2}", ((Byte)Commands.Progress).ToString(), row, column));
view.SetCellStuff(row, column, stuff);
view.FreezeCellMatrix();
view.SetGameStatus("Waiting for opponent");
}
private Boolean ExecuteCommand(String command)
{
switch ((Commands)Byte.Parse(command.Substring(0, 1))) // OH FORGIVE ME GOD AGAIN!!
{
case Commands.Connect:
ConnectHandler(command.Substring(2));
break;
case Commands.YourMove:
YourMoveHandler();
break;
case Commands.Progress:
ProgresstHandler(command.Substring(2));
break;
case Commands.Message:
MessageHandler(command.Substring(2));
return false;
}
return true;
}
private void ConnectHandler(String command)
{
String stuffSign = command.ToLower();
if (stuffSign == "x")
{
stuff = StuffType.X;
opponentStuff = StuffType.O;
}
else if (stuffSign == "o")
{
stuff = StuffType.O;
opponentStuff = StuffType.X;
}
view.SetOwnerStuff(stuff);
view.SetGameStatus("Waiting for opponent");
}
private void YourMoveHandler()
{
view.SetGameStatus("Your move");
view.UnfreezeCellMatrix();
}
private void ProgresstHandler(String command)
{
var values = command.Split('/');
view.SetCellStuff(Int32.Parse(values[0]), Int32.Parse(values[1]), opponentStuff);
YourMoveHandler();
}
private void MessageHandler(String message)
{
view.SetGameStatus(message);
view.FreezeCellMatrix();
}
}
}
Внешний вид созданных приложений
Серверное и клиентское приложения на основе потоковых сокетов
Серверное и клиентское приложения на основе дэйтаграмм
Клиентское и верверное приложения для игровой системы
Вид сервера - пустая консоль, на которую не выводится никакой информации.
Вид клиента