5

これは、ゲーム ボードがどのように見えるかを示すためのものです (このボードは 7x6 に拡張されます)。

私がやりたいのは、斜めのコンボも考慮して、ゲーム「conmect four」に似た2色が連続しているときに勝者を検出することです。しかし、ブルートフォース列挙を使用せずにこれを行いたい..

これは私が作成したプログラムの背後にあるコードです 解決策を求めているわけではありません 効果的なアルゴリズムについて少し助けが必要です

namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {

        private Button[] btns;
        private Button[] btns2;

        public Form1()
        {
            InitializeComponent();

            btns = new Button[] { button2, button3 };
            btns2 = new Button[] { button4, button5 };


        }

        private void Form1_Load(object sender, EventArgs e)
        {

            foreach (var btn in btns)
            {
                btn.Enabled = false;
                btn.BackColor = Color.LightCyan;
            }

            foreach (var btn in btns2)
            {
                btn.Enabled = false;
                btn.BackColor = Color.LightCyan;
            }
        }
        public int state;
        int cc = 0;
        private void button1_Click(object sender, EventArgs e)
        {
            foreach (var btn in btns)
            {
                  {
                    if (!btn.Enabled)
                    {
                        btn.Enabled = true;

                        if (cc == 0)
                        {
                            cc = 1;
                            btn.BackColor = Color.Red;
                        }
                        else
                        {
                            cc = 0;
                            btn.BackColor = Color.Yellow;
                        }
                        return;
                    }

                }
            }       
        }

        private void button6_Click(object sender, EventArgs e)
        {
            foreach (var btn in btns2)
            {
                if (!btn.Enabled)
                {
                    btn.Enabled = true;

                    if (cc == 0)
                    {
                        cc = 1;
                        btn.BackColor = Color.Red;
                    }
                    else
                    {
                        cc = 0;
                        btn.BackColor = Color.Yellow;

                    }

                    return;
                }
            }
        }
    }
}
4

2 に答える 2

10

まず、効率と健全性のために、ボードの状態を 2D 配列に保持します。

次に、勝利状態を検出するために、(おそらく) 空のボードでゲームを開始すると、ボタンの状態が変化したときにのみ勝利状態に入ることができます。そして、ボタンの状態が変化して勝利状態になった場合、そのボタンはその勝利状態に関与している必要があります (つまり、ボタンはあなたのラインの一部である必要があります)。

だから...ボード全体をブルートフォースする必要はありません。状態を変更したばかりのボタンが線の一部であるかどうかを判断するだけで済みます。つまり、上、下、左、右のボタンのみを見て (対角線を含めた場合、質問が明確ではなかった可能性があります)、変更した色と同じ色であるかどうかを確認します。 . それらのいずれかがそうである場合、これは勝利状態です。ここで、2D 配列を使用すると、作業がずっと楽になります。( x , y )のボタンが変更された場合、 ( x-1 , y )、( x+1y )、( xy-1 ) および ( xy+1 )のみを確認する必要があります。)、(そしておそらく対角線)、もちろん適切な境界チェックを確実に行います。

これを連続して 3 つ、4 つ、またはそれ以上に拡張することはそれほど難しくありません。

連続する 2 つの最適化されていない疑似コード (注: 少し扱いに​​くいと感じるので、左上、右上などを避けるためにコンパス ポイントに切り替えました):

// cell is the cell that last changes, it has an x and y property and a color property
// board is a member variable, a 2D array of cells. Note [0,0] is the upper-left (NW) corner of the board.
// boardHeight and boardWidth are member variable with the dimensions of the board
// board[boardWidth-1, boardHeight-1] is the lower-right (SE) corner of the board
// returns true for a win, false otherwise
function checkWin(cell) returns bool {
    // check west
    if (cell.x > 0 && board[cell.x - 1, cell.y].color == cell.color)
        return true;
    // check northwest
    if (cell.x > 0 && cell.y > 0 && board[cell.x-1, cell.y-1].color == cell.color)
        return true;
    // check north
    if (cell.y > 0 && board[cell.x, cell.y-1].color == cell.color)
        return true;
    // check northeast
    if (cell.y > 0 && cell.x < boardWidth && board[cell.x+1, cell.y-1].color == cell.color)
        return true;
    // checking the other directions is left as an exercise for the reader, hopefully you get the point
    return false;
}

あなたが2つ以上をしているなら、左、右、上、下、および診断に一致するセルの数を数える再帰関数について考えます

// k is the number of cells in a row for a win
function checkWin(cell) returns bool {
    // check west / east
    int count = checkWest(cell);
    if (count > k)
         return true;
    count += checkEast(cell);
    if (count > k)
         return true;
    // check nw / se
    count = checkNW(cell);
    if (count > k)
         return true;
    count += checkSE(cell);
    if (count > k)
         return true;
    // and so on, checking N/S and NE/SW
    return false;
}

function checkWest(cell) returns int {
    // base case, check the boundaries!
    if (cell.x == 0)
        return 0;
    // base case, the cell next to this one doesn't match
    if (board[cell.x-1,cell.y].color != cell.color)
        return 0;
    // recursion, check the next cell in the line
    return 1 + checkWest(board[cell.x-1,cell.y]);
 }
于 2012-10-29T19:10:19.617 に答える
1

n by mボードと連続勝利コンボの場合k:

int n, m, k;
byte[,] color = new byte[n, m]; // for two colors, a 0 would correspond to blue, 1 would be red, or however you like

for (int i = 0; i <= n - k; i++) // don't check all the way to the right because there's no room to win
{
    for (int j = 0; j <= m - k; j++) // don't check all the way down because there's no room to win
    {
        // Check here for a win. Check for a win to the right, down right, and down
    }
}
于 2012-10-29T19:10:53.233 に答える