1

App.config ファイルの値で設定されたグリッド サイズを持つ Windows フォーム Tic-Tac-Toe プログラムを作成しています。したがって、値が 9 の場合、グリッドは通常の 3 x 3 であり、25 の場合、5 x 5 などです。

配列の実際のボタンを作成する Gameboard クラスがあります。

public Gameboard(int numberofButtons) //Constructor method that is referencing the App.config for the dimensions value to make the board
{
    buttonArray = new Button[numberofButtons]; //creating an array the size of numberofButtons which is the dimensions value from App.config
    Font font = new Font("Times New Roman", 36.0f); //creates an instance of the Font class
    int sqrtY = (int) Math.Sqrt(numberofButtons);
    int z = 0; //Counter for array

    //Create the buttons for the form
    for (int x = 0; x < sqrtY; x++)
    {
        for (int y = 0; y < sqrtY; y++)
        {
            buttonArray[z] = new Button();
            buttonArray[z].Font = font;
            buttonArray[z].Size = new System.Drawing.Size(100, 100);
            buttonArray[z].Location = new System.Drawing.Point(100*y, 100*x);
            buttonArray[z].Click += new EventHandler(button_click);
            z++; 
        }
    }
}

buttonArray 内の位置の buttonArray.Text の値をチェックするだけで配列内の勝利パターンをチェックしたい場合、どうすればそれを反復できますか?

たとえば、4x4 グリッドでは、水平勝利の勝利ラインは次のようになります。

0,1,2,3
4,5,6,7
8,9,10,11
12,13,14,15

それで

x=0, x<sqrt(dimension), x++
buttonArray[x].Text == "X" <-- to test

これはコード化が不十分で紛らわしいと思いますが、教師が求めたものであるため、1 次元配列でこれを実行しようとしています。buttonArray[]最初に行、次に列、次に対角線をチェックして、値の値をチェックしたい。

フォームにはボタンがないため、フォームが読み込まれると、グリッドに使用されるボタンが読み込まれます。これはコンピューターと対戦することを意図しているため、ボタンをクリックすると .Text が「X」になり、コンピューターは「O」などを入力することになっています。

4

1 に答える 1

2

あなたが指定した基準を分離する方法の例を提供しています。特定の質問には喜んでお答えしますが、これは宿題の質問なので、すべてを提供したくはありません。うまくいけば、これが役に立ちます。

string[] values = buttonArray.Select(b => b.Text).ToArray();


//uses integer divison to separate out rows
string[][] rows = values
    .Select((v, i) => new {index = i, value = v})
    .GroupBy(anon => anon.index/size)
    .Select(grp => grp.Select(anon => anon.value).ToArray())
    .ToArray();

foreach(string[] row in rows)
{
    //Pseudocode
    var winner = CheckAllValuesArePopulatedAndTheSameAKAWinner(row);
    if (winner exists)
        return winner;
}

//uses modulus to separate out columns, basically a transpose
string[][] columns = values
    .Select((v, i) => new { index = i, value = v })
    .GroupBy(anon => anon.index % size)
    .Select(grp => grp.Select(anon => anon.value).ToArray())
    .ToArray();

string[] diagonal1 = values
    .Select((v, i) => new {index = i, value = v})
    .Where(anon => anon.index%(size + 1) == 0)
    .Select(anon => anon.value) //take just the string value, drop the index
    .ToArray();

string[] diagonal2 = values
    .Select((v, i) => new { index = i, value = v })
    .Where(anon => anon.index % (size - 1) == 0)
    .Skip(1) //skip 0 index
    .Take(size) //skip last index
    .Select(anon => anon.value) //take just the string value, drop the index
    .ToArray();

インデックスの例:

//given size and dimension

//run this code once per different size, not on each check (probably move variable to some outer scope)
Dictionary<string, int[]> winningSets = new Dictionary<string, int[]>();
int[] indices = Enumerable.Range(0, dimension).ToArray(); //make array of 0 to (dimension - 1)


for (int rowNum = 0; rowNum < size; ++rowNum) //0 based row index/num
{
    int[] rowIndices = indices
        .Where(i => i / size == rowNum)
        .ToArray();
    winningSets.Add(String.Format("Row Number {0}", rowNum + 1), rowIndices); //use 1 based row index/num for display
}

for (int colNum = 0; colNum < size; ++colNum) //0 based row index/num
{
    int[] colIndices = indices
        .Where(i => i % size == colNum)
        .ToArray();
    winningSets.Add(String.Format("Column Number {0}", colNum + 1), colIndices); //use 1 based column index/num for display
}

int[] diag1 = indices
    .Where(i => i % (size + 1) == 0)
    .ToArray();
winningSets.Add("Diag TR to BL", diag1);

int[] diag2 = indices
    .Where(i => i % (size - 1) == 0)
    .Skip(1) //skip 0 index
    .Take(size) //skip last index
    .ToArray(); 
winningSets.Add("Diag TL to Br", diag2);

//run this for each check
foreach(KeyValuePair<string, int[]> winningSet in winningSets)
{
    //Pseudo
    if (all of winningSet.Value indices are populated and same)
        return winningSet.Name; //Name of winning set, ex will not return multiple winning set which is possible in this game
    //this example does not show who won, but whoever had the last turn is the winner if one is found.
}

値の配列をチェックする方法の例を追加する (行/列/対角線を表す)

    string CheckWinner(string[] setOfValues)
    {
        if (setOfValues.Any(individualValueFromSetOfValues => String.IsNullOrEmpty(individualValueFromSetOfValues))) // some values/cells are not filled in so no winner here
            return null; 
        if (setOfValues.Distinct().Count() == 1) //all data is the same
            return setOfValues.First(); //any value would work, we just checked that they're all the same
        return null; // all values/cells are full but they are not all the same
    }
于 2013-03-01T02:46:52.227 に答える