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) public void Notify(IReadOnlyGameState state)
{ {
Console.Clear();
// Ein mit Leerzeichen initialisiertes 13*13 Jagged Array // Ein mit Leerzeichen initialisiertes 13*13 Jagged Array
char[][] field = Enumerable.Repeat(0, 13).Select(_ => Enumerable.Repeat(' ', 13).ToArray()).ToArray(); 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"> <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')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E3CCB2E8-5840-4442-8A66-177F5DF4C4F5}</ProjectGuid> <ProjectGuid>{E3CCB2E8-5840-4442-8A66-177F5DF4C4F5}</ProjectGuid>
@@ -33,14 +34,18 @@
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" /> <Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" /> <Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" /> <Reference Include="System.Data" />
<Reference Include="System.Net.Http" /> <Reference Include="System.Net.Http" />
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ConsoleInteraction.cs" /> <Compile Include="ConsoleInteraction.cs" />
@@ -49,6 +54,9 @@
<Compile Include="Game.cs" /> <Compile Include="Game.cs" />
<Compile Include="GameResult.cs" /> <Compile Include="GameResult.cs" />
<Compile Include="GameState.cs" /> <Compile Include="GameState.cs" />
<Compile Include="GameWindow.xaml.cs">
<DependentUpon>GameWindow.xaml</DependentUpon>
</Compile>
<Compile Include="RandomBot.cs" /> <Compile Include="RandomBot.cs" />
<Compile Include="IGameStateObserver.cs" /> <Compile Include="IGameStateObserver.cs" />
<Compile Include="IMoveProvider.cs" /> <Compile Include="IMoveProvider.cs" />
@@ -65,6 +73,12 @@
<ItemGroup> <ItemGroup>
<None Include="App.config" /> <None Include="App.config" />
</ItemGroup> </ItemGroup>
<ItemGroup>
<Page Include="GameWindow.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- 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. Other similar extension points exist, see Microsoft.Common.targets.

View File

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