使用LINQ在C#中使用MasterMind评分算法

Fre*_*d K 18 c# linq

我正在寻找一种优雅的方法来计算C#中MasterMind游戏的猜测得分,最好是使用LINQ.

在MasterMind中,代码生成器使用数字1到6生成4位数的密码.可以多次使用数字.例如,密码是:

int[] secret = { 1, 2, 3, 1 };
Run Code Online (Sandbox Code Playgroud)

代码破解者试图通过猜测来破解密码.在这个例子中,猜测是:

int[] guess  = { 1, 1, 2, 2 };
Run Code Online (Sandbox Code Playgroud)

(代码和猜测现在都存储在一个数组中,但其他集合类型也可以).

然后,代码制作者通过宣布"黑人"和"白人"的数量来"评分"这个猜测.从猜测的每个数字中奖励黑色,其在值和位置都是正确的.对于放置在错误位置的每个正确数字,将获得白色.在该示例中,得分为1黑色(对于位置1中的"1")和2个白色(对于位置2和3中的"1"和"2").

回到问题:我正在寻找一种优雅的方法来计算C#中的猜测分数,最好使用LINQ.到目前为止,我已经提出了一个计算黑人数量的声明:

int blacks = new int[] { 0, 1, 2, 3 }.Count(i => (guess[i] == secret[i]));
Run Code Online (Sandbox Code Playgroud)

我打算按照白色数量是匹配总数(3)减去黑色数量的方式进行.所以我尝试过:

int whites = guess.Intersect(secret).Count() - blacks;
Run Code Online (Sandbox Code Playgroud)

但是,唉,IEnumerable.Intersect()产生{1,2}而不是{1,1,2},因为它只查看不同的数字.所以它计算白色= 1而不是2.

除了使用"C"样式的嵌套循环之外,我无法想出另一种计算"白人"的方法.你能?最好使用LINQ - 我喜欢使用LINQ在代码中表示算法的方式.执行速度不是真正的问题.

Eni*_*ity 11

var black = guess
        .Zip(secret, (g, s) => g == s)
        .Count(z => z);

var white = guess
        .Intersect(secret)
        .Sum(c =>
            System.Math.Min(
                secret.Count(x => x == c),
                guess.Count(x => x == c))) - black;
Run Code Online (Sandbox Code Playgroud)

鉴于:

int[] secret = { 1, 2, 3, 1 };
int[] guess  = { 1, 1, 2, 2 };
Run Code Online (Sandbox Code Playgroud)

然后:

black == 1 && white == 2
Run Code Online (Sandbox Code Playgroud)