找到满足谓词的硬币组合的算法?

时间:2017-09-28 16:31:10

标签: c# algorithm combinations

我有以下内容:

颜色:红色,蓝色和绿色

字母:从A到Z

现在假设我可以用上面的两个形成硬币,每个硬币都有一种颜色作为背景颜色和其中一个字母。

硬币的背景颜色为红色,蓝色或绿色,每种颜色可以预定的硬币上的字母,每种颜色都需要特定数量的字母。

红色背景硬币将具有:S,D,A,C,Y,U,L,J,O

蓝色背景硬币将具有:F,T,V,M,K

绿色背景硬币将具有:G,X,B,H,E,Z,W,P,Q,R,N,I

解释

想象一下,我们有一个3x3网格来放置硬币,它可以用一维数组表示:List<>硬币的元素从0到8。

宾果游戏:宾果游戏就像井字游戏中的胜利条件一样,宾果游戏可以出现一种颜色。例如:

grid and bingo

问题

用户将输入宾果和他们想要的字母,例如,用户可以输入:

  • Bingos:Red and Green
  • 字母:D,A,C,G,Q,R,J,T,I

如果有解决方案,程序应该生成解决方案,例如上面的解决方案:

example solution

我如何实现这一目标?用户的条件是动态的,他们可以要求任何颜色的宾果游戏,他们会列出他们想要的字母。

1 个答案:

答案 0 :(得分:-1)

以下是您要做的事情清单:

  • 帮自己一个忙了解代码而不是简单地复制/粘贴
  • 实施对角线检查
  • 调整谓词的有效性以满足您的需求
  • 修复所有可能的错误
  • 奖励积分,如果您可以将其扩展到每列/行/对角线有效性报告
  • 测试,测试,测试! (仅测试基本情况)
  • 举办派对:)

<强>颜色

public enum CoinColor
{
    Red,
    Green,
    Blue
}

<强>信

public enum CoinLetter
{
    A,
    B,
    C,
    D,
    E,
    F,
    G,
    H,
    I,
    J,
    K,
    L,
    M,
    N,
    O,
    P,
    Q,
    R,
    S,
    T,
    U,
    V,
    W,
    X,
    Y,
    Z
}

<强>硬币

public sealed class Coin
{
    internal Coin(CoinColor color, CoinLetter letter)
    {
        Color = color;
        Letter = letter;
    }

    public CoinColor Color { get; }
    public CoinLetter Letter { get; }

    private bool Equals(Coin other)
    {
        return Color == other.Color && Letter == other.Letter;
    }

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        if (ReferenceEquals(this, obj)) return true;
        if (obj.GetType() != GetType()) return false;
        return Equals((Coin) obj);
    }

    public override int GetHashCode()
    {
        unchecked
        {
            return ((int) Color * 397) ^ (int) Letter;
        }
    }

    public static bool operator ==(Coin left, Coin right)
    {
        return Equals(left, right);
    }

    public static bool operator !=(Coin left, Coin right)
    {
        return !Equals(left, right);
    }

    public override string ToString()
    {
        return $"{nameof(Color)}: {Color}, {nameof(Letter)}: {Letter}";
    }
}

<强>辅助

public static class Coins
{
    public static Coin[][] All => new[]
    {
        AllRed,
        AllGreen,
        AllBlue
    };

    public static Coin[] AllRed { get; } =
    {
        RedS, RedD, RedA, RedC, RedY, RedU, RedL, RedJ, RedO
    };

    public static Coin[] AllGreen { get; } =
    {
        GreenG, GreenX, GreenB, GreenH, GreenE, GreenZ, GreenW, GreenP, GreenQ, GreenR, GreenN, GreenI
    };

    public static Coin[] AllBlue { get; } =
    {
        BlueF, BlueT, BlueV, BlueM, BlueK
    };

    public static Coin RedA => new Coin(CoinColor.Red, CoinLetter.A);
    public static Coin RedC => new Coin(CoinColor.Red, CoinLetter.C);
    public static Coin RedD => new Coin(CoinColor.Red, CoinLetter.D);
    public static Coin RedJ => new Coin(CoinColor.Red, CoinLetter.J);
    public static Coin RedL => new Coin(CoinColor.Red, CoinLetter.L);
    public static Coin RedO => new Coin(CoinColor.Red, CoinLetter.O);
    public static Coin RedS => new Coin(CoinColor.Red, CoinLetter.S);
    public static Coin RedU => new Coin(CoinColor.Red, CoinLetter.U);
    public static Coin RedY => new Coin(CoinColor.Red, CoinLetter.Y);
    public static Coin GreenB => new Coin(CoinColor.Green, CoinLetter.B);
    public static Coin GreenE => new Coin(CoinColor.Green, CoinLetter.E);
    public static Coin GreenG => new Coin(CoinColor.Green, CoinLetter.G);
    public static Coin GreenH => new Coin(CoinColor.Green, CoinLetter.H);
    public static Coin GreenI => new Coin(CoinColor.Green, CoinLetter.I);
    public static Coin GreenN => new Coin(CoinColor.Green, CoinLetter.N);
    public static Coin GreenP => new Coin(CoinColor.Green, CoinLetter.P);
    public static Coin GreenQ => new Coin(CoinColor.Green, CoinLetter.Q);
    public static Coin GreenR => new Coin(CoinColor.Green, CoinLetter.R);
    public static Coin GreenW => new Coin(CoinColor.Green, CoinLetter.W);
    public static Coin GreenX => new Coin(CoinColor.Green, CoinLetter.X);
    public static Coin GreenZ => new Coin(CoinColor.Green, CoinLetter.Z);
    public static Coin BlueF => new Coin(CoinColor.Blue, CoinLetter.F);
    public static Coin BlueK => new Coin(CoinColor.Blue, CoinLetter.K);
    public static Coin BlueM => new Coin(CoinColor.Blue, CoinLetter.M);
    public static Coin BlueT => new Coin(CoinColor.Blue, CoinLetter.T);
    public static Coin BlueV => new Coin(CoinColor.Blue, CoinLetter.V);
}

<强>游戏

public class Game
{
    public Game() : this(new Coin[GridWidth, GridHeight])
    {
    }

    public Game(Coin[,] grid)
    {
        if (grid == null)
            throw new ArgumentNullException(nameof(grid));

        if (grid.GetUpperBound(0) != GridWidth - 1)
            throw new ArgumentOutOfRangeException(nameof(grid));

        if (grid.GetUpperBound(1) != GridHeight - 1)
            throw new ArgumentOutOfRangeException(nameof(grid));

        Grid = grid;
    }

    private static int GridWidth { get; } = 3;
    private static int GridHeight { get; } = 3;
    private static int GridExtent => 3;
    private Coin[,] Grid { get; }

    public Coin GetCoin(int col, int row)
    {
        Check(col, row);

        var coin = Grid[col, row];

        return coin;
    }

    public void SetCoin(Coin coin, int col, int row)
    {
        Check(col, row);

        Grid[col, row] = coin;
    }

    public bool Check()
    {
        for (var col = 0; col < GridWidth; col++)
            if (CheckCol(col))
                return true;

        for (var row = 0; row < GridHeight; row++)
            if (CheckRow(row))
                return true;

        return false;
    }

    private bool CheckCol(int col)
    {
        CheckColIndex(col);

        var coins = new Coin[GridHeight];

        for (var row = 0; row < GridHeight; row++)
            coins[row] = GetCoin(col, row);

        var check = Check(coins);

        return check;
    }

    private bool CheckRow(int row)
    {
        CheckRowIndex(row);

        var coins = new Coin[GridWidth];

        for (var column = 0; column < GridWidth; column++)
            coins[column] = GetCoin(column, row);

        var check = Check(coins);

        return check;
    }

    private bool Check(Coin[] coins)
    {
        if (coins == null)
            throw new ArgumentNullException(nameof(coins));

        var any = Coins.All.Any(s => s.Where(coins.Contains).Distinct().Count() == GridExtent);

        return any;
    }

    private static void Check(int col, int row)
    {
        CheckColIndex(col);
        CheckRowIndex(row);
    }

    private static void CheckColIndex(int col)
    {
        if (col < 0 || col >= GridWidth)
            throw new ArgumentOutOfRangeException(nameof(col));
    }

    private static void CheckRowIndex(int row)
    {
        if (row < 0 || row >= GridHeight)
            throw new ArgumentOutOfRangeException(nameof(row));
    }
}

<强>测试

internal class Test
{
    public Test()
    {
        var allGood = new[,]
        {
            {Coins.RedS, Coins.RedD, Coins.RedA},
            {Coins.GreenG, Coins.GreenX, Coins.GreenB},
            {Coins.BlueF, Coins.BlueT, Coins.BlueV}
        };

        var allFalse = new[,]
        {
            {Coins.RedS, Coins.RedS, Coins.RedA},
            {Coins.GreenG, Coins.GreenG, Coins.GreenB},
            {Coins.BlueF, Coins.BlueF, Coins.BlueV}
        };

        foreach (var grid in new[] {allGood, allFalse})
        {
            var game = new Game(grid);

            var check = game.Check();

            Console.WriteLine(check);
        }
    }
}