Zapisywanie i wczytywanie pola
This commit is contained in:
parent
093b590ee4
commit
9b0313201b
@ -5,7 +5,6 @@
|
|||||||
<e p="C:\Users\Kacper\.Rider2019.2\system\resharper-host\local\Transient\ReSharperHost\v192\SolutionCaches\_Life.1627287830.00" t="ExcludeRecursive" />
|
<e p="C:\Users\Kacper\.Rider2019.2\system\resharper-host\local\Transient\ReSharperHost\v192\SolutionCaches\_Life.1627287830.00" t="ExcludeRecursive" />
|
||||||
<e p="C:\Users\Kacper\Studies\dotnet\Life" t="IncludeFlat">
|
<e p="C:\Users\Kacper\Studies\dotnet\Life" t="IncludeFlat">
|
||||||
<e p="Life" t="IncludeRecursive">
|
<e p="Life" t="IncludeRecursive">
|
||||||
<e p="Annotations.cs" t="Include" />
|
|
||||||
<e p="App.xaml" t="Include" />
|
<e p="App.xaml" t="Include" />
|
||||||
<e p="App.xaml.cs" t="Include" />
|
<e p="App.xaml.cs" t="Include" />
|
||||||
<e p="Automaton" t="Include">
|
<e p="Automaton" t="Include">
|
||||||
|
1162
Life/Annotations.cs
1162
Life/Annotations.cs
File diff suppressed because it is too large
Load Diff
@ -4,6 +4,15 @@
|
|||||||
xmlns:local="clr-namespace:Life"
|
xmlns:local="clr-namespace:Life"
|
||||||
StartupUri="MainWindow.xaml">
|
StartupUri="MainWindow.xaml">
|
||||||
<Application.Resources>
|
<Application.Resources>
|
||||||
|
<Style x:Key="Header" TargetType="TextBlock">
|
||||||
|
<Setter Property="FontSize" Value="16" />
|
||||||
|
<Setter Property="FontWeight" Value="Medium"/>
|
||||||
|
<Setter Property="Margin" Value="0 0 0 0"/>
|
||||||
|
</Style>
|
||||||
|
<Style x:Key="Value" TargetType="TextBlock">
|
||||||
|
<Setter Property="FontSize" Value="24" />
|
||||||
|
<Setter Property="FontWeight" Value="Black"/>
|
||||||
|
<Setter Property="Margin" Value="18 0 0 0"></Setter>
|
||||||
|
</Style>
|
||||||
</Application.Resources>
|
</Application.Resources>
|
||||||
</Application>
|
</Application>
|
||||||
|
@ -1,15 +1,15 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.ComponentModel;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.Serialization;
|
||||||
using Life.Annotations;
|
|
||||||
using Life.Misc;
|
using Life.Misc;
|
||||||
|
|
||||||
namespace Life.Automaton
|
namespace Life.Automaton
|
||||||
{
|
{
|
||||||
public abstract class BasicField : IField, INotifyPropertyChanged
|
[Serializable]
|
||||||
|
public abstract class BasicField : IField, IDeserializationCallback
|
||||||
{
|
{
|
||||||
|
[NonSerialized]
|
||||||
List<IObserver<IField>> _observers = new List<IObserver<IField>>();
|
List<IObserver<IField>> _observers = new List<IObserver<IField>>();
|
||||||
|
|
||||||
protected BasicField(int width, int height)
|
protected BasicField(int width, int height)
|
||||||
@ -29,7 +29,7 @@ namespace Life.Automaton
|
|||||||
public Cell this[int x, int y]
|
public Cell this[int x, int y]
|
||||||
{
|
{
|
||||||
get => _cells[x, y];
|
get => _cells[x, y];
|
||||||
set
|
private set
|
||||||
{
|
{
|
||||||
_cells[x, y] = value;
|
_cells[x, y] = value;
|
||||||
_observers.ForEach(observer => observer.OnNext(this));
|
_observers.ForEach(observer => observer.OnNext(this));
|
||||||
@ -43,7 +43,8 @@ namespace Life.Automaton
|
|||||||
public void Transform(Rule transform)
|
public void Transform(Rule transform)
|
||||||
{
|
{
|
||||||
_cells = transform(this);
|
_cells = transform(this);
|
||||||
_observers.ForEach(observer => observer.OnNext(this));
|
|
||||||
|
Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Notify()
|
public void Notify()
|
||||||
@ -51,19 +52,16 @@ namespace Life.Automaton
|
|||||||
_observers.ForEach(observer => observer.OnNext(this));
|
_observers.ForEach(observer => observer.OnNext(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
|
||||||
{
|
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
|
||||||
}
|
|
||||||
|
|
||||||
public IDisposable Subscribe(IObserver<IField> observer)
|
public IDisposable Subscribe(IObserver<IField> observer)
|
||||||
{
|
{
|
||||||
_observers.Add(observer);
|
_observers.Add(observer);
|
||||||
|
|
||||||
return new DelegateUnsubscriber(() => _observers.Remove(observer));
|
return new DelegateUnsubscriber(() => _observers.Remove(observer));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void OnDeserialization(object sender)
|
||||||
|
{
|
||||||
|
_observers = new List<IObserver<IField>>();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,7 +1,9 @@
|
|||||||
using Life.Misc;
|
using System;
|
||||||
|
using Life.Misc;
|
||||||
|
|
||||||
namespace Life.Automaton
|
namespace Life.Automaton
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public class Cell
|
public class Cell
|
||||||
{
|
{
|
||||||
public bool IsAlive { get; set; }
|
public bool IsAlive { get; set; }
|
||||||
|
@ -1,12 +1,16 @@
|
|||||||
using System.Linq;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
|
||||||
namespace Life.Automaton
|
namespace Life.Automaton
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public class GameOfLife : IAutomaton
|
public class GameOfLife : IAutomaton
|
||||||
{
|
{
|
||||||
public GameOfLife(int width, int height)
|
public GameOfLife(int width, int height)
|
||||||
{
|
{
|
||||||
Initialize(new MooreField(width, height));
|
Field = new MooreField(width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Rule MakeRule(string born, string survive)
|
public static Rule MakeRule(string born, string survive)
|
||||||
@ -41,15 +45,15 @@ namespace Life.Automaton
|
|||||||
|
|
||||||
public IField Field { get; private set; }
|
public IField Field { get; private set; }
|
||||||
|
|
||||||
public void Initialize(IField field)
|
|
||||||
{
|
|
||||||
Field = field;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Advance()
|
public void Advance()
|
||||||
{
|
{
|
||||||
Field.Transform(Rule);
|
Field.Transform(Rule);
|
||||||
Iteration++;
|
Iteration++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void ReplaceField(IField field)
|
||||||
|
{
|
||||||
|
Field = field;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,11 +1,14 @@
|
|||||||
namespace Life.Automaton
|
using System;
|
||||||
|
|
||||||
|
namespace Life.Automaton
|
||||||
{
|
{
|
||||||
public interface IAutomaton
|
public interface IAutomaton
|
||||||
{
|
{
|
||||||
int Iteration { get; }
|
int Iteration { get; }
|
||||||
IField Field { get; }
|
IField Field { get; }
|
||||||
|
|
||||||
void Initialize(IField field);
|
|
||||||
void Advance();
|
void Advance();
|
||||||
|
|
||||||
|
void ReplaceField(IField field);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -10,7 +10,7 @@ namespace Life.Automaton
|
|||||||
{
|
{
|
||||||
Size Size { get; }
|
Size Size { get; }
|
||||||
|
|
||||||
Cell this[int x, int y] { get; set; }
|
Cell this[int x, int y] { get; }
|
||||||
|
|
||||||
IEnumerable<Cell> Cells { get; }
|
IEnumerable<Cell> Cells { get; }
|
||||||
|
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
using System.Collections.Generic;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Life.Automaton
|
namespace Life.Automaton
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public class MooreField : BasicField
|
public class MooreField : BasicField
|
||||||
{
|
{
|
||||||
public MooreField(int width, int height) : base(width, height)
|
public MooreField(int width, int height) : base(width, height)
|
||||||
|
@ -7,33 +7,48 @@
|
|||||||
xmlns:vm="clr-namespace:Life.ViewModel"
|
xmlns:vm="clr-namespace:Life.ViewModel"
|
||||||
mc:Ignorable="d"
|
mc:Ignorable="d"
|
||||||
Title="MainWindow" Height="450" Width="800" d:DataContext="{d:DesignInstance vm:AutomatonViewModel}">
|
Title="MainWindow" Height="450" Width="800" d:DataContext="{d:DesignInstance vm:AutomatonViewModel}">
|
||||||
<Grid>
|
<Window.InputBindings>
|
||||||
<Grid.ColumnDefinitions>
|
<KeyBinding Key="O" Modifiers="Control" Command="{Binding LoadCommand}"/>
|
||||||
<ColumnDefinition Width="2*" MinWidth="400"/>
|
<KeyBinding Key="S" Modifiers="Control" Command="{Binding SaveCommand}"/>
|
||||||
<ColumnDefinition Width="3"/>
|
</Window.InputBindings>
|
||||||
<ColumnDefinition Width="1*" MinWidth="300" MaxWidth="400"/>
|
<DockPanel>
|
||||||
</Grid.ColumnDefinitions>
|
<Menu DockPanel.Dock="Top">
|
||||||
|
<MenuItem Command="{Binding LoadCommand}" Header="Load" />
|
||||||
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
<MenuItem Command="{Binding SaveCommand}" Header="Save" />
|
||||||
<local:AutomatonField Field="{Binding Field}" Size="{Binding Size}" Separation="3" ClickCommand="{Binding CellClicked}"/>
|
</Menu>
|
||||||
</ScrollViewer>
|
<Grid>
|
||||||
|
<Grid.ColumnDefinitions>
|
||||||
<GridSplitter Grid.Column="1" Width="3" ResizeDirection="Columns" ResizeBehavior="PreviousAndNext"/>
|
<ColumnDefinition Width="2*" MinWidth="400"/>
|
||||||
<Grid Margin="8" Grid.Column="2">
|
<ColumnDefinition Width="3"/>
|
||||||
<Grid.RowDefinitions>
|
<ColumnDefinition Width="1*" MinWidth="300" MaxWidth="400"/>
|
||||||
<RowDefinition Height="3*"/>
|
</Grid.ColumnDefinitions>
|
||||||
<RowDefinition Height="1*"/>
|
|
||||||
</Grid.RowDefinitions>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
<ScrollViewer HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
|
||||||
<TextBlock Text="{Binding Field.Size.Width}"/>
|
<local:AutomatonField Field="{Binding Field}" Size="{Binding Size}" Separation="3" ClickCommand="{Binding CellClicked}"/>
|
||||||
<TextBlock Text=" x "/>
|
</ScrollViewer>
|
||||||
<TextBlock Text="{Binding Field.Size.Height}"/>
|
|
||||||
</StackPanel>
|
|
||||||
|
|
||||||
<StackPanel Orientation="Vertical" Grid.Row="1" VerticalAlignment="Bottom">
|
<GridSplitter Grid.Column="1" Width="3" ResizeDirection="Columns" ResizeBehavior="PreviousAndNext"/>
|
||||||
<Button VerticalAlignment="Stretch" Command="{Binding StepCommand}">Step</Button>
|
|
||||||
|
<StackPanel Orientation="Vertical" Margin="8" Grid.Column="2" HorizontalAlignment="Stretch">
|
||||||
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Style="{StaticResource Header}" VerticalAlignment="Center">Iteracja</TextBlock>
|
||||||
|
<TextBlock Style="{StaticResource Value}" Text="{Binding Iteration}" VerticalAlignment="Stretch"/>
|
||||||
|
<Button VerticalAlignment="Center" Command="{Binding StepCommand}" HorizontalAlignment="Right">
|
||||||
|
<TextBlock Margin="4">krok</TextBlock>
|
||||||
|
</Button>
|
||||||
|
</DockPanel>
|
||||||
|
<DockPanel HorizontalAlignment="Stretch">
|
||||||
|
<TextBlock Style="{StaticResource Header}" VerticalAlignment="Center">Rozmiar</TextBlock>
|
||||||
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="center" VerticalAlignment="Center">
|
||||||
|
<TextBox Text="{Binding Field.Size.Width, Mode=OneWay}"/>
|
||||||
|
<TextBlock Text=" x "/>
|
||||||
|
<TextBox Text="{Binding Field.Size.Height, Mode=OneWay}"/>
|
||||||
|
</StackPanel>
|
||||||
|
<Button VerticalAlignment="Center" Command="{Binding StepCommand}" HorizontalAlignment="Right">
|
||||||
|
<TextBlock Margin="4">Zapisz</TextBlock>
|
||||||
|
</Button>
|
||||||
|
</DockPanel>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</DockPanel>
|
||||||
</Window>
|
</Window>
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Windows;
|
using System.Windows;
|
||||||
|
using System.Windows.Input;
|
||||||
using Life.Automaton;
|
using Life.Automaton;
|
||||||
using Life.ViewModel;
|
using Life.ViewModel;
|
||||||
|
|
||||||
@ -24,5 +25,9 @@ namespace Life
|
|||||||
|
|
||||||
InitializeComponent();
|
InitializeComponent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void CommandBinding_OnExecuted(object sender, ExecutedRoutedEventArgs e)
|
||||||
|
{
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,5 +1,8 @@
|
|||||||
namespace Life.Misc
|
using System;
|
||||||
|
|
||||||
|
namespace Life.Misc
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public struct Position
|
public struct Position
|
||||||
{
|
{
|
||||||
public Position(int x, int y)
|
public Position(int x, int y)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
namespace Life.Misc
|
using System;
|
||||||
|
|
||||||
|
namespace Life.Misc
|
||||||
{
|
{
|
||||||
|
[Serializable]
|
||||||
public struct Size
|
public struct Size
|
||||||
{
|
{
|
||||||
public int Width { get; }
|
public int Width { get; }
|
||||||
|
@ -1,16 +1,20 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Runtime.Serialization;
|
||||||
|
using System.Runtime.Serialization.Formatters.Binary;
|
||||||
using System.Windows.Input;
|
using System.Windows.Input;
|
||||||
using Life.Automaton;
|
using Life.Automaton;
|
||||||
using Life.Misc;
|
using Life.Misc;
|
||||||
|
using Microsoft.Win32;
|
||||||
|
|
||||||
namespace Life.ViewModel
|
namespace Life.ViewModel
|
||||||
{
|
{
|
||||||
public class AutomatonViewModel : BaseViewModel
|
public class AutomatonViewModel : BaseViewModel
|
||||||
{
|
{
|
||||||
|
|
||||||
private int _size;
|
private int _size;
|
||||||
private int _separation;
|
private int _separation;
|
||||||
private IAutomaton _automaton;
|
private IAutomaton _automaton;
|
||||||
|
private IFormatter _formatter = new BinaryFormatter();
|
||||||
|
|
||||||
public int Size
|
public int Size
|
||||||
{
|
{
|
||||||
@ -31,7 +35,7 @@ namespace Life.ViewModel
|
|||||||
OnPropertyChanged(nameof(Separation));
|
OnPropertyChanged(nameof(Separation));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IAutomaton Automaton
|
public IAutomaton Automaton
|
||||||
{
|
{
|
||||||
get => _automaton;
|
get => _automaton;
|
||||||
@ -51,14 +55,26 @@ namespace Life.ViewModel
|
|||||||
Action = HandleCellClick
|
Action = HandleCellClick
|
||||||
};
|
};
|
||||||
|
|
||||||
|
public ICommand LoadCommand => new DelegateCommand<object>
|
||||||
|
{
|
||||||
|
Action = HandleLoadCommand
|
||||||
|
};
|
||||||
|
|
||||||
|
public ICommand SaveCommand => new DelegateCommand<object>
|
||||||
|
{
|
||||||
|
Action = HandleSaveCommand
|
||||||
|
};
|
||||||
|
|
||||||
public ICommand StepCommand => new DelegateCommand<object>
|
public ICommand StepCommand => new DelegateCommand<object>
|
||||||
{
|
{
|
||||||
Action = Step
|
Action = Step
|
||||||
};
|
};
|
||||||
|
|
||||||
private void Step(object param)
|
private void Step(object param)
|
||||||
{
|
{
|
||||||
Automaton.Advance();
|
Automaton.Advance();
|
||||||
|
|
||||||
|
OnPropertyChanged(nameof(Iteration));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void HandleCellClick(Position position)
|
private void HandleCellClick(Position position)
|
||||||
@ -66,5 +82,31 @@ namespace Life.ViewModel
|
|||||||
Field[position.X, position.Y].IsAlive = !Field[position.X, position.Y].IsAlive;
|
Field[position.X, position.Y].IsAlive = !Field[position.X, position.Y].IsAlive;
|
||||||
Field.Notify();
|
Field.Notify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleLoadCommand(object _)
|
||||||
|
{
|
||||||
|
OpenFileDialog dialog = new OpenFileDialog();
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
using var file = dialog.OpenFile();
|
||||||
|
var field = _formatter.Deserialize(file) as IField;
|
||||||
|
|
||||||
|
Automaton.ReplaceField(field);
|
||||||
|
|
||||||
|
OnPropertyChanged(nameof(Field));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void HandleSaveCommand(object _)
|
||||||
|
{
|
||||||
|
SaveFileDialog dialog = new SaveFileDialog();
|
||||||
|
|
||||||
|
if (dialog.ShowDialog() == true)
|
||||||
|
{
|
||||||
|
using var file = dialog.OpenFile();
|
||||||
|
_formatter.Serialize(file, Field);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -1,6 +1,5 @@
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
using Life.Annotations;
|
|
||||||
|
|
||||||
namespace Life.ViewModel
|
namespace Life.ViewModel
|
||||||
{
|
{
|
||||||
@ -8,7 +7,6 @@ namespace Life.ViewModel
|
|||||||
{
|
{
|
||||||
public event PropertyChangedEventHandler PropertyChanged;
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
[NotifyPropertyChangedInvocator]
|
|
||||||
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
{
|
{
|
||||||
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
Loading…
Reference in New Issue
Block a user