Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
288 views
in Technique[技术] by (71.8m points)

.net - 2 in a row c# program game

here is the game board just to give you an idea of how it looks like (this board will be expanded to a 7x6)

what i want to do is detect a winner when 2 colors are in a row similar to the game "conmect four" taking into account diagonal combos too. BUT i want to do this with out using brute-force enumeration..

this the code that goes behind the program i have made I'm not asking for solution i just need a bit of help on an effective algorithm

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;
                }
            }
        }
    }
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

First, for efficiency and sanity, I'd keep the state of my board in a 2D array.

Second, for detecting win states, given that you start the game with a (presumably) empty board, you can only get into a win state when a button changes state. And if the button changing state puts you into a win state, then that button must be involved in that win state (i.e. it must be part of you line).

So...you don't need to brute-force the whole board. You only need to determine if the button that just changed state is part of a line. In other words, look only at the buttons to above, below, to the left and to the right (and maybe diagonal, your question wasn't clear if you included diagonals) to see if they are the same color as the one you changed. If any one of them is, then this is a win state. This is where using a 2D array will make you life much easier. If the button at (x, y) is changed, then you only need to check (x-1, y), (x+1, y), (x, y-1) and (x, y+1), (and maybe diagonals) making sure to do appropriate boundary checks, of course.

Extending this to 3, 4 or more in a row isn't much more difficult, except you need to remember you might be in the middle of a row rather than one end or the other.

Unoptimized Pseudo Code for 2 in a row (note, I've switched to compass points to avoid up-left, up-right, etc because I feel it gets a bit unwieldy):

// 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;
}

If you are doing more than 2, I'd think about a recursive function to count the number of matching cells to the left, right, up, down, and diagnoals

// 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]);
 }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...