3

これは、グリッドのサイズを任意の数(3x3 4x4 8x8など)にできる三目並べゲーム用です。

フォームが読み込まれると、メソッドはグリッドサイズを読み取り、1次元のボタン配列内のその数のボタンをフォームに入力します。配列はbuttonArrayと呼ばれます。

1次元のbuttonArrayを使用し、LINQを使用しない場合、buttonArrayのボタンの.Text値を比較して、CheckWinner()関数のボタンが「X」または「O」であるかどうかを確認するにはどうすればよいですか。

ボタングリッドが作成された後、ボタンクリック用のイベントハンドラーがあります。

private void button_click(object sender, EventArgs e)
    {
        Button b = (Button)sender;
        b.Text = "X";
        b.Enabled = false;
        CheckWinner(buttonArray);
} 

次に、CheckWinner関数を呼び出して、配列buttonArrayを渡します。

繰り返しになりますが、LINQを使用せずに値をチェック/比較するための基本的な方法を探しています。グリッドの各辺の長さがわかっている場合、水平方向のウィンラインの場合、.Textプロパティとして「X」を使用して連続して多数のボタンを探していると言えます。

したがって、5x5のグリッドがあり、buttonArrayに25個のボタンがある場合、グリッドの0インデックスから始まる5つごとに.Text値が「X」であるかどうかを確認し、5が連続している場合はメッセージを出力するにはどうすればよいですか。同じ、この場合は「X」です。

for (int z = 0; z < root; z++) //increments the column to start on
        {
            vCount = 0; //Starts the win counter at zero when moving to the next column
            for (int i = z; i < arrLength; i=i+root) //starts at the first column and increments it by root to test the next button in the column
            {
                string bText = buttonArray[i].Text;
                if (bText == "X")
                    vCount++;
                if (vCount == root)
                {
                    MessageBox.Show("Vertical row winner found !");
                    break;
                }
            }
        }//end of vertical column test

私はそのような垂直線テストをしましたか?しかし、私はそれらを1つに結合する方が良いと思います。

4

3 に答える 3

2

であるかどうか を確認したいと仮定しButton.Text == "X" ます every element of a horizontal row。以下は非常に基本的な方法です...

public void CheckWinner(Buttons[] buttonArray)
{
    int arrLength = buttonArray.Length; 
    int hCount = 0;
    //int vCount = 0;
    int root = (int)Math.Sqrt(Convert.ToDouble(arrLength));  

    for (int i = 0; i < arrLength ; i++)
    { 
        string bText = buttonArray[i].Text;

        hCount = i % root == 0? 0 : hCount;

        if(bText == "X") 
            hCount++;

        if(hCount == root) 
        {
            Console.WriteLine("Horizontal row winner found !");
            break;
        }
    }

}

垂直および/または水平の勝者を確認するには:

public void CheckWinner(Buttons[] buttonArray)
{
    int arrLength = buttonArray.Length; 
    int hCount = 0;
    Int vCount = 0;
    int root = (int)Math.Sqrt(Convert.ToDouble(arrLength));  

    for (int i = 0;  i < root;  i++)
    {
        hCount = 0;
        vCount = 0;
        for(int j = 0;  j < root; j++)
        {
           if(buttonArray[ (i * root) + j ].Text == "X")
              hCount++;

           if(buttonArray[ i + (root * j) ].Text == "X")
              vCount++;
        }

        if( hCount + vCount == 2 * root)
        {
           Console.WriteLine("Horizontal and Virtical winner found !");
           break;
        } 
        else if ( hCount == root )
        { 
           Console.WriteLine("Horizontal winner found !");
           break;
        }
        else if ( vCount == root )
        { 
           Console.WriteLine("Virtical winner found !");
           break;
        }

    }
}
于 2013-03-01T19:01:26.653 に答える
2

他のすべての回答も同様に機能するように見えますが、オプションをリングに投入します。私のは基本的な実装です。各行に沿って単純に進み、各行に同じ値があるかどうかを確認します。これの垂直バージョンは、2 つの for ループを再配置するのと同じくらい簡単で、対角線はそれほど難しくありません。

この質問の主なトリックは、配列の行と列の理解と、1D 配列のみが与えられた場合に 2D 配列を模倣する方法を示すことだと私には思えます。

水平の場合:

string CheckWinnerHorizontal(Button[] buttonArray) {
    int N = (int)Math.Sqrt(buttonArray.Length);
    for (int row = 0; row < N; ++row)
    {
        string winner = "";
        for (int col = 0; col < N; ++col)
        {
            string value = buttonArray[row * N + col].Text;
            if (winner == "") { winner = value; }
            else if (winner != value) { winner = "none"; }
        }
        if (winner != "none" && winner != "")
        {
            return winner;
        }
    }
    return "";
于 2013-03-01T19:13:06.860 に答える
1

確かに、あなたはこれを試してみることができます - ここでは by-rows を行います。by-cols は非常に似ているはずです:

(編集 - ああ、明らかに私は読むことができません...しかし、他の人にとっては有用な答えであり続けるかもしれません...私はすでにOPに注意を払っていなかったことを証明したので、それを拡張して記入させてください垂直/対角...)

(LINQPad 対応)

void Main()
{
    // Quickish and very dirty way to generate the grid
    var lineLength = 3;
    var rnd = new Random();
    var gridSrc = 
        from r in Enumerable.Range(0, lineLength)
        from c in Enumerable.Range(0, lineLength)
        select new { Row = r, Col = c, Text = rnd.Next(0,2) > 0 ? "X" : "O" };
    var grid = gridSrc.ToArray();

    // ok, now for the query
    var horizontalWinners =
        // need the cell and it's index - this is one way to do that
        from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell))
        let idx = cellTuple.Item1
        let cell = cellTuple.Item2
        // figure out which row its in
        let row = idx / lineLength
        // figure out which column its in
        let col = idx % lineLength
        // for rows, group by row #
        group cell by row into byRow
        // only count if all cells in that row are same
        where byRow.All(rowCell => rowCell.Text == "X") 
             || byRow.All(rowCell => rowCell.Text == "O")
        // tell us what row (and who won)
        select new { byRow.Key, byRow.First().Text };

var verticalWinners =
    from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell))
    let idx = cellTuple.Item1
    let cell = cellTuple.Item2
    let row = idx / lineLength
    let col = idx % lineLength
    group cell by col into byCol
    where byCol.All(colCell => colCell.Text == "X") 
                 || byCol.All(colCell => colCell.Text == "O")
    select new { byCol.Key, byCol.First().Text };

var topLeftBottomRightDiagonalWinners =
    from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell))
    let idx = cellTuple.Item1
    let cell = cellTuple.Item2
    let row = idx / lineLength
    let col = idx % lineLength
    let fwdSlash = (row == col)
    group cell by fwdSlash into byDiag
    where byDiag.Key && byDiag.All(d => d.Text == byDiag.First().Text)
    select new { 
                 Text = byDiag.First().Text, 
                 Pos = string.Join("", byDiag.Select(c => Tuple.Create(c.Col, c.Row).ToString())) 
            };

var topRightBottomLeftDiagonalWinners =
    from cellTuple in grid.Select((cell, idx) => Tuple.Create(idx, cell))
    let idx = cellTuple.Item1
    let cell = cellTuple.Item2
    let row = idx / lineLength
    let col = idx % lineLength
    let backSlash = (row + col) == (lineLength - 1)
    group cell by backSlash into byDiag     
    where byDiag.Key && byDiag.All(d => d.Text == byDiag.First().Text)
    select new { 
               Text = byDiag.First().Text, 
               Pos = string.Join("", byDiag.Select(c => Tuple.Create(c.Col, c.Row).ToString())) 
            };

for(int r=0;r<lineLength;r++)
{
    for(int c=0;c<lineLength;c++)
    {
        Console.Write(grid[r*lineLength+c].Text + " ");
    }
    Console.WriteLine();
}
foreach(var row in horizontalWinners)
{
    Console.WriteLine("{0} wins on row {1}", row.Text, row.Key);
}
foreach(var col in verticalWinners)
{
    Console.WriteLine("{0} wins on col {1}", col.Text, col.Key);
}
foreach (var diag in topLeftBottomRightDiagonalWinners
                .Concat(topRightBottomLeftDiagonalWinners)) 
{
    Console.WriteLine("{0} wins on diagonal {1}", diag.Text, diag.Pos);     
}
}
于 2013-03-01T19:01:17.640 に答える