3

C#、XAML、特に MVVM を学習する目的で、マインスイーパ ゲームのプログラミングを開始しました。私が作成した最初のバージョンは、MVVM の部分がなく、MVVM の方法で XAML で行うのではなく、C# コードでボタンを作成して追加しました。ここで、MVVM パターンをゲームに適用してみます。

地雷原部分を表すボタンを含む独自のユーザー コントロールを作成しました。このコントロールには、いくつかの状態データを格納し、いくつかのコマンドを処理するための ViewModel とモデル クラスもあります。テスト プロジェクトでは、独自のユーザー コントロールを 4 つ作成し、ボタンが 2 x 2 の正方形を形成するグリッドにそれらを配置しようとしました。コード ビハインドでは、ボタンは ObservableCollection オブジェクトに配置されます。このオブジェクトでは、ボタンが次のようにリストされ、インデックスが付けられていると想定しています。

Button1
Button2
Button3
Button4

しかし、プレゼンテーショングリッドでは、ボタンを次のように表示したい

Button1 | Button2
--------+--------
Button3 | Button4

問題は、それを動的に行うにはどうすればよいかということです。私のテストプロジェクトでは4つのボタンでテストしていますが、これを使用したいプロジェクトでは、プレーヤーが選択したゲームの難易度によってボタンの数が異なる場合があります。

2 番目の質問は、ボタンの neigbhours をどのように把握できるかということです。したがって、グリッドが 4 x 5 で、20 個のボタンが含まれているとします。たとえば、隣のボタン番号 2、3、4、7、9、12、13、14 を持つボタン 8 を選択します。

私の質問が十分に明確であることを願っています。

前もって感謝します!

4

3 に答える 3

5

またはに設定されたItemsControlを使用して、コレクションを表示できます。MDSN の例はあまり役に立たないので、ここにいくつかの例があります。ItemsPanelGridUniformGridItemsControl

とプロパティを のプロパティにバインドUniformGridできれば最も簡単ですが、それにはすべてのセルが同じサイズである必要があり、プロパティとがバインディング システムに参加する DependencyProperties であるかどうかを思い出せません。RowsColumnsViewModelRowsColumns

<ItemsControl ItemsSource="{Binding MyCollection}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <UniformGrid Columns="{Binding ColumnCount}" 
                         Rows="{Binding RowCount}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
</ItemsControl>

これがうまくいかない場合は、 を として使用しGrid、およびバインディングを にItemsPanel設定できます。Grid.RowGrid.ColumnItemContainerStyle

これには、そのセルがどの行/列にあるかを示すために、各セルオブジェクトにプロパティが必要ですがObservableCollection、クリックコマンドで隣接するセルなどを決定するためにこれらが必要になると思います。

さらに、 の行/列の数をバインドする組み込みの方法がないため、バインドされた値に基づいてグリッドを動的に構築するいくつかのカスタム添付プロパティGridを使用する傾向があります。RowDefinitionsColumnDefinitions

したがって、グリッドを使用している場合の最終結果は、おそらく次のようになります。

<ItemsControl ItemsSource="{Binding Cells}">
    <!-- ItemsPanelTemplate -->
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <!-- This is assuming you use the attached properties linked above -->
            <Grid local:GridHelpers.RowCount="{Binding Height}"
                  local:GridHelpers.ColumnCount="{Binding Width}" />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>

    <!-- ItemContainerStyle -->
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Grid.Column" 
                    Value="{Binding ColumnIndex}" />
            <Setter Property="Grid.Row" 
                    Value="{Binding RowIndex}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

このようなモデル/ビューモデルで

public class GameViewModel
{
    // These should be full properties w/ property change notification
    // but leaving that out for simplicity right now
    public int Height;
    public int Width;
    public ObservableCollection<CellModel> Cells;
}

public class CellModel
{
    // Same thing, full properties w/ property change notification
    public int ColumnIndex;
    public int RowIndex;
    public bool IsVisible;
    public bool IsMine;
    public int NumberAdjacentMines;
}
于 2012-11-27T15:57:54.900 に答える
1

最近、一種のソフトウェア開発コンテストのために、マインスイーパのゲーム ロジックを解決しました。彼のゲームの主な問題は、アイテムの周りに隣接する地雷と隣接する空のセルを見つけることだと思います。どちらの場合も、各セル (項目) が最大 8 つの項目 (セル) で囲まれていることを考慮する必要があります。4x4 グリッド (マトリックス) を X、Y 座標で定義されたセル C と見なすと、次のセルに囲まれます。

C1 (X-1,Y-1)
C2 (X,Y-1)
C3 (X+1,Y-1)
C4 (X-1,Y)
C5 (X+1,Y)
C6 (X-1,Y+1)
C7 (X,Y+1)
C8 (X+1,Y+1)

つまり、x 軸と y 軸上の点を平行移動することで、アイテムの隣接するセルを見つけることができます。ゲームのプレゼンテーション (フロントエンド) をゲーム ロジック (バックエンド) で分割して、クラス セットを開発しました。
この戦略を実際に使用することで、さまざまな .Net 環境で使用できます。UI 要素やコンポーネントに「ロック」されることはありません。
私のプロジェクトはこちらからダウンロードできます:
https://github.com/alchimya/csharp-minesweeper-sdk

于 2015-06-24T17:37:19.683 に答える
-1

頭のてっぺんから:

List<Button> myButtons = new List<Button>();
Button myFirstButton = new Button(/*make first button*/);
myButtons.Add(myFirstButton);

void addButtonX ()
{//add new button along x axis
    Button tempButt = new Button();        
    Button lastButt = myButtons[myButtons.count - 1];
    tempButt.posX = lastButt.posX + lastButt.sizeX;
    tempButt.posY = lastButt.posY;
    //other code for buttons
    myButtons.Add(tempButt);
}
void addButtonY ()
{//add new button along y axis
    Button tempButt = new Button();
    Button lastButt = myButtons[myButtons.count - 1];
    tempButt.posX = lastButt.posX;
    tempButt.posY = lastButt.posY + lastButt.sizeY;
    //other code for buttons
    myButtons.Add(tempButt);
}

周りのボタンを追跡するには、グリッドの幅がいくつのボタンであるかを知る必要があります。たとえば、グリッドの幅が20ボタンの場合、ボタンは次のようになります。

[B-20-1][B-20][B-20+1]
[B-1]   [B]   [B+1]
[B+20-1][B+20][B+20+1]

ここで、B=ボタンがクリックされました。

もちろん、グリッドから外れる値がないことを確認する必要があります(たとえば、B-20-1は0以上、B + 20 + 1はボタンの数以下です)が、それは非常に簡単です。終わり。

于 2012-11-27T15:30:58.727 に答える