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