Hej,
W temacie programowania obiektowego - a co za tym idzie też w c# - jestem w miarę nowy. Uczę się go od 3 miesięcy. Wcześniej miałem styczność z różnymi językami, ale zawsze była to zabawa językami nie-obiektowymi.
Stworzyłem aplikację WPF, która wyświetla 2 windy (2xLabel) i ma obok n pięter w postaci Buttonów. Po przyciśnięciu przycisku piętra - "wołamy" windę.
"Algorytm" działania wind nie jest zbyt wyszukany - po prostu jeżeli jakaś winda jest wolna to jedzie do najbliższego zgłoszenia.
Chodzi mi o ocenę kodu mojej aplikacji. Czy idę w ogóle w dobrą stronę, czy robię coś zbyt "łopatologicznie", mało elastycznie (obsługa większej ilości wind w planach ;) ) czy niezgodnie z konwencją.
Zaznaczam, że nie przygotowywałem kodu pod używanie go przez kogoś innego, więc wiem, że można namieszać w nim, jeżeli nie zna się "konwencji" ;)
OK, już się nie tłumaczę. Poniżej kody XAML i C#:
XAML:
<Window x:Class="Windy.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="980" Width="368">
<Grid Name="Widok">
<Label x:Name="winda1Label" Content="Winda 1" HorizontalAlignment="Left" Margin="121,913,0,0" VerticalAlignment="Top"/>
<Button Content="0" HorizontalAlignment="Left" Margin="81,913,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="1" HorizontalAlignment="Left" Margin="81,883,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="2" HorizontalAlignment="Left" Margin="81,853,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="3" HorizontalAlignment="Left" Margin="81,823,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="4" HorizontalAlignment="Left" Margin="81,793,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="5" HorizontalAlignment="Left" Margin="81,763,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="6" HorizontalAlignment="Left" Margin="81,733,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="7" HorizontalAlignment="Left" Margin="81,703,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="8" HorizontalAlignment="Left" Margin="81,673,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="9" HorizontalAlignment="Left" Margin="81,643,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="10" HorizontalAlignment="Left" Margin="81,613,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="11" HorizontalAlignment="Left" Margin="81,583,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="12" HorizontalAlignment="Left" Margin="81,553,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="13" HorizontalAlignment="Left" Margin="81,523,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="14" HorizontalAlignment="Left" Margin="81,493,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="15" HorizontalAlignment="Left" Margin="81,463,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="16" HorizontalAlignment="Left" Margin="81,433,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="17" HorizontalAlignment="Left" Margin="81,403,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="18" HorizontalAlignment="Left" Margin="81,373,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="19" HorizontalAlignment="Left" Margin="81,343,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="20" HorizontalAlignment="Left" Margin="81,313,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="21" HorizontalAlignment="Left" Margin="81,283,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="22" HorizontalAlignment="Left" Margin="81,253,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="23" HorizontalAlignment="Left" Margin="81,223,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="24" HorizontalAlignment="Left" Margin="81,193,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="25" HorizontalAlignment="Left" Margin="81,163,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="26" HorizontalAlignment="Left" Margin="81,133,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="27" HorizontalAlignment="Left" Margin="81,103,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="28" HorizontalAlignment="Left" Margin="81,73,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="29" HorizontalAlignment="Left" Margin="81,43,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Button Content="30" HorizontalAlignment="Left" Margin="81,13,0,0" VerticalAlignment="Top" Click="Button_Click" Width="20"/>
<Label x:Name="winda2Label" Content="Winda 2" HorizontalAlignment="Left" Margin="213,913,0,0" VerticalAlignment="Top"/>
</Grid>
</Window>
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.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;
using System.Windows.Threading;
namespace Windy
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
PanelSterujący panel;
public static Brush DomyślnyKolorPrzycisku;
public MainWindow()
{
// TO DO LIST
// 1. Określenie, która winda będzie szybciej na miejscu - niezależnie od tego, czy jest w drodze, czy nie.
// --- >> 2. Jak naciskamy kilka przycisków na raz to nie musimy robić kolejki, tylko może najlepiej zatrzymać się na kilku piętrach po drodze. << --- DONE
// 3. Zadania dla poszczególnych wind, jeżeli się zatrzymają gdzieś.
// 4. Dodać obsługę większej ilości Wind w PaneluSterującym
InitializeComponent();
var winda1 = new Winda(ref winda1Label);
var winda2 = new Winda(ref winda2Label);
var listaPrzycisków = Widok.Children.OfType<Button>();
var listaPrzycisków2 = listaPrzycisków.ToList<Button>();
DomyślnyKolorPrzycisku = listaPrzycisków2[0].Background;
panel = new PanelSterujący(ref winda1, ref winda2, ref listaPrzycisków2);
}
private void Button_Click(object sender, RoutedEventArgs e)
{
panel.ZawołajWindę(int.Parse(((Button)sender).Content.ToString()));
}
}
public class Winda
{
private BackgroundWorker workerWindy;
public bool Stoi;
public int Piętro;
public int NaKtórePiętro;
private Label ktoraWindaLabel;
public Winda(ref Label label)
{
this.Stoi = true;
this.Piętro = 0;
this.ktoraWindaLabel = label;
}
public void Jedź(int piętro)
{
workerWindy = new BackgroundWorker();
this.Stoi = false;
this.NaKtórePiętro = piętro;
workerWindy.DoWork += workerWindy_Jedź;
workerWindy.RunWorkerAsync();
}
private void workerWindy_Jedź(object sender, DoWorkEventArgs e)
{
int ile = Math.Abs(this.Piętro - this.NaKtórePiętro);
int wKtórąStronę = (NaKtórePiętro - Piętro) / Math.Abs(NaKtórePiętro - Piętro);
for (int i = 0; i < ile; i++)
{
System.Threading.Thread.Sleep(500);
this.Piętro += wKtórąStronę;
zmienUstawienieElementów(true, false, wKtórąStronę * (-30));
}
System.Threading.Thread.Sleep(5000);
zmienUstawienieElementów(false, true);
this.Stoi = true;
PanelSterujący.SprawdźCzyJestJeszczeCośWKolejce();
}
private void zmienUstawienieElementów(bool winda, bool przycisk, int wKtórąStronę = 0)
{
if (winda)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
this.ktoraWindaLabel.Margin = new Thickness(this.ktoraWindaLabel.Margin.Left, this.ktoraWindaLabel.Margin.Top + wKtórąStronę, 0, 0);
}));
}
if (przycisk)
{
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Background, new Action(() =>
{
PanelSterujący.ListaPrzycisków[this.Piętro].Background = MainWindow.DomyślnyKolorPrzycisku;
PanelSterujący.ListaPrzycisków[this.Piętro].IsEnabled = true;
}));
}
}
}
public class PanelSterujący
{
public static Winda Winda1;
public static Winda Winda2;
public static List<Button> ListaPrzycisków { get; set; }
public static List<int> ListaPięterDoObsłużenia { get; set; }
public PanelSterujący(ref Winda winda1, ref Winda winda2, ref List<Button> listaPrzycisków)
{
ListaPrzycisków = listaPrzycisków;
ListaPięterDoObsłużenia = new List<int>();
Winda1 = winda1;
Winda2 = winda2;
}
public static void SprawdźCzyJestJeszczeCośWKolejce()
{
if (ListaPięterDoObsłużenia.Count > 0)
if (Winda1.Stoi || Winda2.Stoi)
wyślijWindę();
}
private static int znajdźNajbliższąWartość(int piętro)
{
var minOdległość = ListaPięterDoObsłużenia.Min(n => Math.Abs(piętro - n));
return ListaPięterDoObsłużenia.First(n => Math.Abs(piętro - n) == minOdległość);
}
private static void wyślijWindę()
{
var ktoraWinda = Winda1;
int najbliższePiętro = 0;
if (Winda1.Stoi && Winda2.Stoi)
{
int najbliższePiętro1 = znajdźNajbliższąWartość(Winda1.Piętro);
int najbliższePiętro2 = znajdźNajbliższąWartość(Winda2.Piętro);
bool pierwszeMniejszeOdDrugiego = najbliższePiętro1 - Winda1.Piętro <= najbliższePiętro2 - Winda2.Piętro;
najbliższePiętro = pierwszeMniejszeOdDrugiego ? najbliższePiętro1 : najbliższePiętro2;
ktoraWinda = pierwszeMniejszeOdDrugiego ? Winda1 : Winda2;
}
else
{
ktoraWinda = (Winda1.Stoi && !Winda2.Stoi) ? Winda1 : Winda2;
najbliższePiętro = znajdźNajbliższąWartość(ktoraWinda.Piętro);
}
ListaPięterDoObsłużenia.Remove(najbliższePiętro);
ktoraWinda.Jedź(najbliższePiętro);
}
public void ZawołajWindę(int piętro)
{
if (!(Winda1.Piętro == piętro && Winda1.Stoi) && !(Winda2.Piętro == piętro && Winda2.Stoi))
{
ListaPięterDoObsłużenia.Add(piętro);
ListaPrzycisków[piętro].IsEnabled = false;
SprawdźCzyJestJeszczeCośWKolejce();
}
}
}
}
dodanie znacznika <code class="xml">
- @furious programming