Minor changes, add GUI (read only atm)

This commit is contained in:
Markus Himmel
2016-08-27 19:50:06 +02:00
parent fb645cbbc5
commit a64674f1a3
5 changed files with 221 additions and 2 deletions

View File

@@ -26,6 +26,8 @@ namespace Morris
public void Notify(IReadOnlyGameState state)
{
Console.Clear();
// Ein mit Leerzeichen initialisiertes 13*13 Jagged Array
char[][] field = Enumerable.Repeat(0, 13).Select(_ => Enumerable.Repeat(' ', 13).ToArray()).ToArray();

12
Morris/GameWindow.xaml Normal file
View File

@@ -0,0 +1,12 @@
<Window x:Class="Morris.GameWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
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"
xmlns:local="clr-namespace:Morris"
mc:Ignorable="d"
Title="Morris" Height="300" Width="300">
<Grid x:Name="grid" Background="#FFD0D0D0">
</Grid>
</Window>

187
Morris/GameWindow.xaml.cs Normal file
View File

@@ -0,0 +1,187 @@
/*
* GameWindow.xaml.cs
* Copyright (c) 2016 Markus Himmel
* This file is distributed under the terms of the MIT license
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace Morris
{
/// <summary>
/// Eine WPF-gestütze Mühle-GUI
/// </summary>
public partial class GameWindow : Window, IGameStateObserver
{
private const int BLOCK_SIZE = 100; // Sollte durch 2 teilbar sein
private const int OFFSET_LEFT = 50;
private const int OFFSET_TOP = 70;
private const int OFFSET_BOTTOM = 90;
private const int OFFSET_RIGHT = 10;
private const int LINE_THICKNESS = 6; // Sollte durch 2 teilbar sein
private const int PIECE_RADIUS = 30;
private const int LEGEND_OFFSET = 30;
private const int LABEL_BUFFER_SIZE = 40;
private Ellipse[] pieces;
private SolidColorBrush primaryColor = new SolidColorBrush(Color.FromRgb(0, 0, 0));
private Label status;
public GameWindow()
{
InitializeComponent();
// Spielfield zeichnen
for (int i = 0; i < GameState.FIELD_SIZE; i++)
{
var pointI = CoordinateTranslator.CoordinatesFromID(i);
foreach (int j in GameState.GetConnected(i).Where(j => j < i))
{
var pointJ = CoordinateTranslator.CoordinatesFromID(j);
// "Fire and Forget": Sobald wir die Objekte zum Grid hinzugefügt haben,
// brauchen wir keine Referenzen mehr zu speichern.
var h = new Rectangle();
h.Fill = primaryColor;
h.Width = BLOCK_SIZE * Math.Abs(pointI[1] - pointJ[1]) + LINE_THICKNESS;
h.Height = BLOCK_SIZE * Math.Abs(pointI[0] - pointJ[0]) + LINE_THICKNESS;
h.HorizontalAlignment = HorizontalAlignment.Left;
h.VerticalAlignment = VerticalAlignment.Top;
h.Margin = new Thickness(
BLOCK_SIZE * Math.Min(pointI[1], pointJ[1]) + BLOCK_SIZE / 2 - LINE_THICKNESS / 2 + OFFSET_LEFT,
BLOCK_SIZE * Math.Min(pointI[0], pointJ[0]) + BLOCK_SIZE / 2 - LINE_THICKNESS / 2 + OFFSET_TOP,
0, 0);
grid.Children.Add(h);
}
}
// Beschriftung links
for (int i = 0; i < 7; i++)
{
Label l = new Label();
l.VerticalContentAlignment = VerticalAlignment.Center;
l.HorizontalAlignment = HorizontalAlignment.Left;
l.VerticalAlignment = VerticalAlignment.Top;
l.Content = (7 - i).ToString();
l.Height = LABEL_BUFFER_SIZE;
l.Margin = new Thickness(OFFSET_LEFT - LEGEND_OFFSET, OFFSET_TOP + i * BLOCK_SIZE + BLOCK_SIZE / 2 - LABEL_BUFFER_SIZE / 2, 0, 0);
l.FontSize = 20;
l.Foreground = primaryColor;
grid.Children.Add(l);
}
// Beschriftung unten
for (int i = 0; i < 7; i++)
{
Label l = new Label();
l.HorizontalContentAlignment = HorizontalAlignment.Center;
l.HorizontalAlignment = HorizontalAlignment.Left;
l.VerticalAlignment = VerticalAlignment.Top;
l.Content = (char)('a' + i);
l.Width = LABEL_BUFFER_SIZE;
l.Margin = new Thickness(OFFSET_LEFT + i * BLOCK_SIZE + BLOCK_SIZE / 2 - LABEL_BUFFER_SIZE / 2, OFFSET_TOP + 7 * BLOCK_SIZE, 0, 0);
l.FontSize = 20;
l.Foreground = primaryColor;
grid.Children.Add(l);
}
// Fenstergröße
Height = OFFSET_TOP + 7 * BLOCK_SIZE + OFFSET_BOTTOM;
Width = OFFSET_LEFT + 7 * BLOCK_SIZE + OFFSET_RIGHT;
// Es gibt nicht für jeden tatsächlichen Spielstein eine Ellipse, die sich bewegt. Stattdessen gibt es eine
// Ellipse auf jedem der 24 Spielfeldpunkte, die je nach Belegung Schwarz, weiß oder transparent ist
pieces = new Ellipse[GameState.FIELD_SIZE];
for (int i = 0; i < GameState.FIELD_SIZE; i++)
{
var point = CoordinateTranslator.CoordinatesFromID(i);
var e = new Ellipse();
e.Fill = null;
e.Width = e.Height = 2 * PIECE_RADIUS;
e.HorizontalAlignment = HorizontalAlignment.Left;
e.VerticalAlignment = VerticalAlignment.Top;
e.Margin = new Thickness(
OFFSET_LEFT + BLOCK_SIZE * point[1] + BLOCK_SIZE / 2 - PIECE_RADIUS,
OFFSET_TOP + BLOCK_SIZE * point[0] + BLOCK_SIZE / 2 - PIECE_RADIUS,
0, 0);
grid.Children.Add(e);
pieces[i] = e;
}
// Statusanzeige
status = new Label();
status.HorizontalContentAlignment = HorizontalAlignment.Center;
status.HorizontalAlignment = HorizontalAlignment.Left;
status.VerticalAlignment = VerticalAlignment.Top;
status.Width = 7 * BLOCK_SIZE + LINE_THICKNESS;
status.Margin = new Thickness(OFFSET_LEFT, 10, 0, 0);
status.FontSize = 40;
grid.Children.Add(status);
}
public void Notify(IReadOnlyGameState state)
{
Dispatcher.Invoke(() =>
{
// Ellipsen einfärben
for (int i = 0; i < GameState.FIELD_SIZE; i++)
{
switch (state.Board[i])
{
case Occupation.Free:
pieces[i].Fill = null;
break;
case Occupation.Black:
pieces[i].Fill = new SolidColorBrush(Colors.Black);
break;
case Occupation.White:
pieces[i].Fill = new SolidColorBrush(Colors.White);
break;
}
}
// Statusanzeige, falls das Spiel vorbei ist
switch (state.Result)
{
case GameResult.BlackVictory:
status.Content = "Schwarz hat gewonnen";
break;
case GameResult.WhiteVictory:
status.Content = "Weiß hat gewonnen";
break;
case GameResult.Draw:
status.Content = "Unentschieden";
break;
}
});
}
}
}

View File

@@ -2,6 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E3CCB2E8-5840-4442-8A66-177F5DF4C4F5}</ProjectGuid>
@@ -33,14 +34,18 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="ConsoleInteraction.cs" />
@@ -49,6 +54,9 @@
<Compile Include="Game.cs" />
<Compile Include="GameResult.cs" />
<Compile Include="GameState.cs" />
<Compile Include="GameWindow.xaml.cs">
<DependentUpon>GameWindow.xaml</DependentUpon>
</Compile>
<Compile Include="RandomBot.cs" />
<Compile Include="IGameStateObserver.cs" />
<Compile Include="IMoveProvider.cs" />
@@ -65,6 +73,12 @@
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<Page Include="GameWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.

View File

@@ -1,4 +1,5 @@
using System;
using System.Windows;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -8,14 +9,17 @@ namespace Morris
{
class Program
{
[STAThread]
static void Main(string[] args)
{
var a = new ConsoleInteraction();
var b = new RandomBot();
var w = new GameWindow();
var g = new Game(b, b);
g.AddObserver(a);
g.Run();
Console.ReadKey();
g.AddObserver(w);
Task.Run(() => g.Run());
new Application().Run(w);
}
}
}