2010-04-02 49 views
2

如何爲簡單遊戲創建棋盤,看起來像棋,但用戶可以動態更改列數和行數?在單元格中,我可以插入典當符號,如小圖像或橢圓形或帶填充的矩形。該板應該可以添加和刪除單元格中的棋子,並將單元格從一個單元格移動到另一個單元格。在WPF中創建遊戲事件支持板

我的第一個想法是Grid。我這樣做是在後面的代碼,但它傷害到實施運行事件或一切創造板:/

 int size = 12; 
     Grid board = new Grid(); 
     board.ShowGridLines = true; 
     for (int i = 0; i < size;i++) 
     { 
      board.ColumnDefinitions.Add(new ColumnDefinition()); 
      board.RowDefinitions.Add(new RowDefinition()); 
     } 

     //komputer 
     Rectangle ai = new Rectangle(); 
     ai.Height = 20; 
     ai.Width = 20; 
     ai.AllowDrop = true; 
     ai.Fill = Brushes.Orange; 
     Grid.SetRow(ai, 0); 
     Grid.SetColumn(ai,0); 
     //człowiek 
     Rectangle hum = new Rectangle(); 
     hum.Height = 20; 
     hum.Width = 20; 
     hum.AllowDrop = true; 
     hum.Fill = Brushes.Green; 
     Grid.SetRow(hum,size); 
     Grid.SetColumn(hum,size); 
     board.Children.Add(ai); 
     board.Children.Add(hum); 
     this.Content = board; 
  • 這是一個辦法做到在XAML這個動態山口和行的變化?
  • 這是更好的方式來實現該董事會創建和實施從一個單元格移動典當事件?

回答

2

你仍然必須使用代碼隱藏改變GridRowDefinitionsColumnDefinitions性能在這個例子中,因爲他們不依賴特性。但是所有其餘的邏輯都可以在視圖模型類中處理。

的XAML:

<Window x:Class="GameBoard.Window1" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:GameBoard="clr-namespace:GameBoard" 
     Title="Window1" 
     SizeToContent="WidthAndHeight"> 
    <Grid Margin="50"> 
     <Grid.Resources> 

      <!-- This template presents the Piece object. Note that you can't set 
       the Grid.Row and Grid.Column properties on this Rectangle - well, 
       you *can*, but the Grid won't see them. See the Style below. --> 
      <DataTemplate DataType="{x:Type GameBoard:Piece}"> 
       <Rectangle Fill="{Binding Fill}" 
          Width="50" 
          Height="50" /> 
      </DataTemplate> 

      <!-- When the ItemsControl creates its items, it wraps each item in a 
       ContentPresenter. You have to set Grid.Row and Grid.Column 
       on this ContentPresenter in order for the Grid to see them. --> 
      <Style TargetType="{x:Type ContentPresenter}"> 
       <Setter Property="Grid.Row" 
         Value="{Binding Row}" /> 
       <Setter Property="Grid.Column" 
         Value="{Binding Column}" /> 
      </Style> 

     </Grid.Resources> 
     <Border BorderBrush="Black" 
       BorderThickness="1"> 
      <ItemsControl x:Name="Board" 
          ItemsSource="{Binding}"> 
       <ItemsControl.ItemsPanel> 
        <ItemsPanelTemplate> 
         <Grid> 
          <Grid.RowDefinitions> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
           <RowDefinition Height="50" /> 
          </Grid.RowDefinitions> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
           <ColumnDefinition Width="50" /> 
          </Grid.ColumnDefinitions> 
         </Grid> 
        </ItemsPanelTemplate> 
       </ItemsControl.ItemsPanel> 
      </ItemsControl> 
     </Border> 
    </Grid> 
</Window> 

Piece類 - 很明顯,你需要實現對和Column性能INotifyPropertyChanged來處理不斷變化的內容有關。

public class Piece 
{ 
    public int Column { get; set; } 
    public Brush Fill { get; set; } 
    public int Row { get; set; } 
} 

填充板:

public Window1() 
    { 
     InitializeComponent(); 

     ObservableCollection<Piece> pieces = new ObservableCollection<Piece>(); 
     pieces.Add(
      new Piece {Row = 0, Column = 0, Fill = new SolidColorBrush(Colors.BlanchedAlmond)}); 
     pieces.Add(
      new Piece {Row = 7, Column = 7, Fill = new SolidColorBrush(Colors.RosyBrown)}); 
     pieces.Add(
      new Piece { Row = 3, Column = 4, Fill = new SolidColorBrush(Colors.BlueViolet) }); 
     pieces.Add(
      new Piece { Row = 5, Column = 4, Fill = new SolidColorBrush(Colors.Orange) }); 

     Board.DataContext = pieces; 
    } 

我使用的ItemsControl包含在本例中的碎片。您可以改用ListBox - 這樣很好,因爲它可以讓您免費選擇物品。請注意,如果您這樣做,則必須將StyleTargetType更改爲ListBoxItem,因爲這是ListBox包裝其項目元素而不是ContentPresenter

編輯:

我前一段寫了這個答案,它有一個問題。

指定Grid.RowGrid.Column屬性使用應用於由網格生成的項目容器的樣式是正確的。找出物品容器是ContentPresenter,並且爲該類型創建默認樣式不是。 (在這種情況下它可以可靠地工作,但在很多情況下它不會)。

您仍然應該創建一個樣式,但它應該被分配到ItemsControlItemContainerStyle。此樣式會自動應用於控件爲其項目生成的任何容器元素 - 因此,如果您使用的ItemsControlListBox,它將應用於ListBoxItem,如果它是TabControl,它將應用於TabItem,等等。

+0

現在我決定在XAML中聲明的列和行的常量號。我實現INotifyPropertyChanged和我幾乎理解你的想法...但如何實現移動件?我認爲我通過鼠標單擊它,然後選擇其他單元格,它應該改變位置(接口實現幫助我改變行和列)。如何找到選定的位置在指定的單元格? – netmajor 2010-04-02 23:42:32

+0

有很多方法可以做到。可能最簡單:創建一個類似Piece類的Cell類,爲每個單元格創建一個Cell類,並在添加Piece對象之前將它們添加到「ItemsSource」。這些棋子在Z順序中比單元格稍後顯示,因此它們將顯示(並通過鼠標點擊來選擇)。如果您使用的是ListBox,SelectedItem將(如果不是null)始終是Piece或Cell。 – 2010-04-03 00:07:24

+0

好的,我明白你的意思了,就像是在空單元格類或Piece之間切換。 但是對於我來說,知道棋子對新位置的實際位置很重要,因爲如果它近距棋子會多倍,其他棋子就會移動。那麼如何從鼠標向下的事件位置(列,行)獲得新的棋子移動?... – netmajor 2010-04-03 00:39:51