简体   繁体   中英

Simplest and possibly most efficient way to check for data in a line in an array

I'm making a Connect 4 Console game in C#. I have all the application set up and working correctly except the hasGameBeenWon() function. The function is called in the Main do...while loop and returns false when the game has not been won.

    static bool gameHasEnded(int currentTurn)
    {
        int currentTurnPiece;

        if (currentTurn.Equals(1))
        {
            currentTurnPiece = BLUE;
        }
        else if (currentTurn.Equals(2))
        {
            currentTurnPiece = RED;
        }

        return false;
    }

(obviously, this code is incomplete)

...Is how it current looks, the currentTurn var is int value of the current player's turn (it can be either 1 or 2). BLUE and RED are constants that are assigned the values of 1 and 2 that are converted into Blue and Red colours on the board when the application prints to the console.

Now I'm stuck on how to check if the game has been won efficiently and as simple as possible. The board is stored in an Array called board , I need to check to see if there is a set of 4 same-values going up/down, left/right and also diagonal in all directions. The checking up/down and left/right is not that hard, but the diagonal I thought maybe a little slow in having to check every single time.

Is there anyway I could speed up checking the entire board or possibly skip checking the entire board altogether and possibly searching just the relevant areas?

I'm going to assume that board is just some 2-D array of enum Cell {NONE, BLUE, RED} values with width and height and that you want to "connect N " (where in your example N is 4 ).

A simple vector class:

class Vec
{
    public int i;
    public int j;
    public Vec(int i, int j) { this.i = i; this.j = j; }
}

The types of patterns/templates that describe a win:

var winTemplates = new List<List<Vec>>
{
    Enumerable.Range(0, N).Select(x => new Vec(x, 0)).ToList(),
    Enumerable.Range(0, N).Select(x => new Vec(0, x)).ToList(),
    Enumerable.Range(0, N).Select(x => new Vec(x, x)).ToList(),
    Enumerable.Range(0, N).Select(x => new Vec(N - x - 1, x)).ToList()
};

Is there a (Cell, List<Vec>) tuple describing a win at position p ?

Func<Vec, Tuple<Cell, List<Vec>>> getWin = p => winTemplates
    .SelectMany(winTemplate => winTemplate
        .Select(q => new Vec(p.i + q.i, p.j + q.j))
        .GroupBy(v => board[v.i, v.j])
        .Where(g => g.Key != Cell.NONE && g.Count() == N)
        .Select(g => Tuple.Create(g.Key, g.ToList())))
    .FirstOrDefault();

Is there a win anywhere on the board?

Func<Tuple<Cell, List<Vec>>> findWin = () => Enumerable.Range(0, height - N)
    .SelectMany(i => Enumerable.Range(0, width - N).Select(j => new Vec(i, j)))
    .Select(p => getWin(p))
    .FirstOrDefault();

This is just browser code, so it may have typos. If you need more help understanding it, let me know in a comment.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM