Diskuze: WPF - Hrací pole - Piškvorky
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
sadlomaslox25:17.4.2016 11:15
proc by to neslo?
budto udelas
[][] kde pouzijes nejspis 2 vnorene ItemsControly nebo
[,] nebo [] kde si napises konvertor na pozici a pouzijes Canvas jako
PanelTemplate
sadlomaslox25:17.4.2016 17:15
nejak nechapu kde presne ses zasekl? vice-rozmerne pole normalne nabindujes a zobrazis jako matici v pohode.
No jak to udělat tak, abych nemusel dělat toto. Je to totální porušení DRY a vypadá to hnusně.
<Button x:Name="Button1" Content="" HorizontalAlignment="Left" Height="43" Margin="0" VerticalAlignment="Top" Width="50" Foreground="Purple" FontWeight="Bold" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button2" Content="" Height="43" Foreground="Purple" Margin="0" VerticalAlignment="Top" BorderBrush="{x:Null}" HorizontalAlignment="Left" Width="50" FontWeight="Bold" FontSize="16" Click="Button_Click">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button3" Content="" Foreground="Purple" Height="43" Width="50" BorderBrush="{x:Null}" HorizontalAlignment="Left" VerticalAlignment="Top" FontWeight="Bold" FontSize="16" Margin="0" Click="Button_Click">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button4" Height="43" Margin="0" Foreground="Purple" VerticalAlignment="Top" BorderBrush="{x:Null}" FontWeight="Bold" FontSize="16" Click="Button_Click" Width="50">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button5" Content="" HorizontalAlignment="Right" Height="43" Margin="0" Foreground="Purple" VerticalAlignment="Top" Width="50" FontWeight="Bold" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button6" Content="" HorizontalAlignment="Left" Margin="0" Width="50" FontWeight="Bold" Foreground="Purple" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click" Height="43">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button7" Content="" Margin="0" Foreground="Purple" FontWeight="Bold" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click" HorizontalAlignment="Left" Width="50" Height="43">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button8" Content="" HorizontalAlignment="Right" Margin="0" Width="50" Foreground="Purple" FontWeight="Bold" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click" Height="43">
<Button.Background>
<LinearGradientBrush EndPoint="0.5,1" MappingMode="RelativeToBoundingBox" StartPoint="0.5,0">
<GradientStop Color="#FFA3A1A5" Offset="1"/>
<GradientStop Color="#FF2EAF53"/>
</LinearGradientBrush>
</Button.Background>
</Button>
<Button x:Name="Button9" Content="" HorizontalAlignment="Right" Height="43" Margin="0" Foreground="Purple" VerticalAlignment="Top" Width="50" FontWeight="Bold" FontSize="16" BorderBrush="{x:Null}" Click="Button_Click">
sadlomaslox25:17.4.2016 20:28
xaml
<Grid>
<Grid.Resources>
<local:MultiplicatorConverter x:Key="conv"/>
</Grid.Resources>
<ItemsControl ItemsSource="{Binding Desk}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Content="{Binding Owner}" Width="20" Height="20" Command="{Binding ChangeOwner}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemContainerStyle>
<Style TargetType="ContentPresenter">
<Setter Property="Canvas.Left" Value="{Binding Path=X, Converter={StaticResource conv}, ConverterParameter=20}" />
<Setter Property="Canvas.Top" Value="{Binding Path=Y, Converter={StaticResource conv}, ConverterParameter=20}" />
</Style>
</ItemsControl.ItemContainerStyle>
</ItemsControl>
</Grid>
cs + pomocne tridy
public partial class MainWindow : Window
{
public List<Field> Desk { get; set; }
public MainWindow()
{
InitializeComponent();
Desk = new List<Field>();
for(int x=0;x<20;x++)
for (int y = 0; y < 20; y++)
Desk.Add(new Field {X = x, Y = y});
DataContext = this;
}
}
public enum Owner
{
No,Me,Yu
}
public class Field:INotifyPropertyChanged
{
private Owner _owner;
public int X { get; set; }
public int Y { get; set; }
public Owner Owner
{
get { return _owner; }
set
{
_owner = value;
OnPropertyChanged();
}
}
public ICommand ChangeOwner
{
get { return new RelayCommand(() => Owner = (Owner) (((int) Owner + 1)%3)); }
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
public class RelayCommand:ICommand
{
private readonly Action _a;
public RelayCommand(Action a)
{
_a = a;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
_a();
}
public event EventHandler CanExecuteChanged;
}
public class MultiplicatorConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
int intValue = (int) value;
int multiplicator = System.Convert.ToInt32(parameter);
return intValue*multiplicator;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
tech pomocnych trid tam samozrejme tolik byt nemusi zalezi na implementaci ale tohle je skoro cista MVVM implementace.
Neaktivní uživatel:18.4.2016 1:31
Zkus použít WrapPanel a místo 2D pole budeš mít normální seznam.
Byl jsem v podobné situaci, když jsem si tvořil šachovnicové pole. Vyřešil jsem to takto:
- Vytvořil jsem v designeru grid a rovnoměrně "nasekal" na 8 řádků a 8 sloupců.
- V code behind jsem si pak vytvořil 2 rozměrné pole políček.
- Třída políčko brala v konstruktoru parametry int x a int y což byl vlastně řádek a sloupec gridu.
- Třída políčko pak v konstruktoru vytvořila mimo jiné i button, který měl předdefinované parametry, které byly pro všechny políčka stejné. Jediný parametr, který se měnil, byl row a collumn (což byly parametry konstruktoru x a y).
- Políčka jsem pak vytvářel ve dvou vnořených cyklech (for (int x = 0; x < 8; x++), for (int y = 0; y < 8; y++)), které jsem vkládal do zmiňovaného dvourozměrného pole políček. (polePolíček[x,y] = new Políčko(x, y);).
Kdyby tě tohle řešení zaujalo, tak šachy jsem poměrně nedávno (měsíc z5) nahrál zde na itnetwork i se zdrojovými kódy.
Ondřej Krsička:19.4.2016 20:11
Díky, podívám se na to Třeba se inspiruju i něčím jiným
Ondřej Krsička:19.4.2016 20:12
Díky za na první pohled docela složitý kód, až se tím budu zabývat podrobněji, určitě se něco přiučím
Lukáš Fusek:19.4.2016 21:06
Jsem rád, že to někomu pomůže. Bohužel kód není napsaný a okomentovaný příliš přehledně, takže kdyby si měl jakékoliv otázky, stačí napsat.
Ondřej Krsička:21.4.2016 18:34
Tak jsem to vyřešil takto.
public MainWindow()
{
//I don´t know what is this doing
InitializeComponent();
ParserContext context = new ParserContext();
context.XmlnsDictionary.Add("", "http://schemas.microsoft.com/winfx/2006/xaml/presentation");
context.XmlnsDictionary.Add("x", "http://schemas.microsoft.com/winfx/2006/xaml");
//Definition of Rows and Columns
for (int i = 0; i < 15; i++)
{
myGrid.ColumnDefinitions.Add(new ColumnDefinition());
myGrid.RowDefinitions.Add(new RowDefinition());
}
char[,] game = new char[15, 15];
game[5, 5] = 'V'; //test
//Definition of Buttons
for (int y = 0; y < 15; y++)
{
for (int x = 0; x < 15; x++)
{
string xaml = $"<Button Margin = \"0\" Grid.Row = \"{y}\" Grid.Column = \"{x}\"></Button>";
Button element = (Button)XamlReader.Parse(xaml, context);
element.Content = game[x, y].ToString();
myGrid.Children.Add(element);
}
}
}
- Jak v C# zadám Grid.Column a Grid.Row daného tlačítka?
- Jak mám udělat nějak nemanuálně reakci každého tlačítka, aby po kliknutí změnilo položku v poli game na daných souřadnicích na 'X'?
sadlomaslox25:21.4.2016 19:42
for (int y = 0; y < 15; y++)
{
for (int x = 0; x < 15; x++)
{
int xx = x;
int yy = y;
Button element = new Button();
element.Content = game[x, y].ToString();
Grid.SetColumn(element, x);
Grid.SetRow(element, y);
element.Click += (p, q) =>
{
element.Content = 'V';
game[xx, yy] = 'V';
};
myGrid.Children.Add(element);
}
}
to pole charu a provazani mezi tlacitkem a polem nemas resene moc dobre. ale casem na to prijdes
petr.dar:24.4.2016 22:21
taky zkoušim programovat šachy, ale v c++ v Qt. Zatim jsem na začátku, sranda bude až začnu programovat engine
Zobrazeno 15 zpráv z 15.