今天晚上我很无聊,决定创建一个程序来计算"24“游戏中给定场景的所有解决方案。
这个游戏的目标是你试图成为第一个找到某张牌的答案的人。牌上有四个数字,从1到9不等。玩家可以使用减法、加、乘和除法来达到数字24,并且只能使用每个数字一次。
例子: 8,8,5,1可能导致8-5 = 3,3*1 = 3,3*8= 24.
我已经将操作符放入枚举中,所选的数字在方法的开头被放入一个列表中。下面的代码正确地计算解决方案,最后选择唯一的解决方案,并将其放入所显示的公共属性中。
对所有这些问题进行裁决的方法:
private void CalculateSolutions()
{
Solutions.Clear();
var numbers = new List<int>(4) { NumberOne, NumberTwo, NumberThree, NumberFour };
var solutions = new List<OperatorResult>();
foreach (Operator operatorOne in Enum.GetValues(typeof (Operator)))
{
foreach (Operator operatorTwo in Enum.GetValues(typeof (Operator)))
{
foreach (Operator operatorThree in Enum.GetValues(typeof (Operator)))
{
for (var numberOneCounter = 0; numberOneCounter < numbers.Count; numberOneCounter++)
{
var numberOne = numbers[numberOneCounter];
for (var numberTwoCounter = 0; numberTwoCounter < numbers.Count; numberTwoCounter++)
{
if (numberTwoCounter == numberOneCounter)
continue;
var numberTwo = numbers[numberTwoCounter];
for (var numberThreeCounter = 0;
numberThreeCounter < numbers.Count;
numberThreeCounter++)
{
if (numberThreeCounter == numberOneCounter || numberThreeCounter == numberTwoCounter)
continue;
var numberThree = numbers[numberThreeCounter];
for (var numberFourCounter = 0;
numberFourCounter < numbers.Count;
numberFourCounter++)
{
if (numberFourCounter == numberOneCounter ||
numberFourCounter == numberTwoCounter ||
numberFourCounter == numberThreeCounter)
continue;
var numberFour = numbers[numberFourCounter];
var sum = GetTotalSum(numberOne, numberTwo, numberThree, numberFour, operatorOne,
operatorTwo, operatorThree);
if (sum != 24)
continue;
var result = new OperatorResult
{
OperatorOne = operatorOne,
OperatorTwo = operatorTwo,
OperatorThree = operatorThree,
NumberOne = numberOne,
NumberTwo = numberTwo,
NumberThree = numberThree,
NumberFour = numberFour
};
solutions.Add(result);
}
}
}
}
}
}
}
// Select only the unique solutions
foreach (var solution in OperatorResult.GetUniqueSolutions(solutions))
Solutions.Add(solution);
}
枚举:
public enum Operator
{
Multiply = '*',
Subtract = '-',
Add = '+',
Divide = '/'
}
解决方案财产:
public static DependencyProperty SolutionsProperty = DependencyProperty.Register("Solutions",
typeof (ObservableCollection<OperatorResult>), typeof (MainWindow));
public ObservableCollection<OperatorResult> Solutions
{
get { return GetValue(SolutionsProperty) as ObservableCollection<OperatorResult>; }
set { SetValue(SolutionsProperty, value); }
}
OperatorResult类:
public class OperatorResult
{
public Operator OperatorOne { get; set; }
public Operator OperatorTwo { get; set; }
public Operator OperatorThree { get; set; }
public int NumberOne { get; set; }
public int NumberTwo { get; set; }
public int NumberThree { get; set; }
public int NumberFour { get; set; }
/// <summary>
/// Gets the unique solutions.
/// </summary>
/// <param name="solutions">The solutions.</param>
public static IEnumerable<OperatorResult> GetUniqueSolutions(List<OperatorResult> solutions)
{
var uniqueSolutions = new List<OperatorResult>();
foreach (var solution in solutions.Where(solution => uniqueSolutions.Count(p => p.Equals(solution)) == 0))
uniqueSolutions.Add(solution);
return uniqueSolutions;
}
/* Resharper's generated Equals and GetHashCode functions are also present here.
And the equals method does more than just a pure compare.
This equals method should also filter: 6*8/4*2 is duplicate of 6*8*2/4 */
}
正如您所看到的,这不是最漂亮的代码,在循环方面有七个层次。圈复杂度是16,我找不到办法把它降到10以下。
我能做些什么来减少循环的数量吗?其他改善的迹象也很受欢迎!
发布于 2015-03-07 22:21:02
首先,在您的Equals
中实现OperatorResult
public override bool Equals(object obj)
{
return Equals(obj as OperatorResult);
}
public bool Equals(OperatorResult operatorResult)
{
return operatorResult != null &&
operatorResult.OperatorOne == this.OperatorOne &&
operatorResult.OperatorTwo == this.OperatorTwo &&
operatorResult.OperatorThree == this.OperatorThree &&
operatorResult.NumberOne == this.NumberOne &&
operatorResult.NumberTwo == this.NumberTwo &&
operatorResult.NumberThree == this.NumberThree &&
operatorResult.NumberFour == this.NumberFour;
}
public override int GetHashCode()
{
var result = 0;
result = (result * 397) ^ (int)OperatorOne;
result = (result * 397) ^ (int)OperatorTwo;
result = (result * 397) ^ (int)OperatorThree;
result = (result * 397) ^ NumberOne;
result = (result * 397) ^ NumberTwo;
result = (result * 397) ^ NumberThree;
result = (result * 397) ^ NumberFour;
return result;
}
使用它,您不需要GetUniqueSolutions
,只需使用Distinct
即可。
现在,您的代码可以表示为以下linq查询:
void CalculateSolutions()
{
var numbers = new List<int>(4) { 8, 8, 5, 1 };
var solutions =
(from operatorOne in (IEnumerable<Operator>)Enum.GetValues(typeof(Operator))
from operatorTwo in (IEnumerable<Operator>)Enum.GetValues(typeof(Operator))
from operatorThree in (IEnumerable<Operator>)Enum.GetValues(typeof(Operator))
from numberOne in numbers
from numberTwo in GetRemainingNumbers(numbers, numberOne)
from numberThree in GetRemainingNumbers(numbers, numberOne, numberTwo)
from numberFour in GetRemainingNumbers(numbers, numberOne, numberTwo, numberThree)
where GetTotalSum(numberOne, numberTwo, numberThree, numberFour,
operatorOne, operatorTwo, operatorThree) == 24
select new OperatorResult
{
OperatorOne = operatorOne,
OperatorTwo = operatorTwo,
OperatorThree = operatorThree,
NumberOne = numberOne,
NumberTwo = numberTwo,
NumberThree = numberThree,
NumberFour = numberFour,
}).Distinct();
}
IEnumerable<int> GetRemainingNumbers(IEnumerable<int> numbers, params int[] usedNumbers)
{
var result = numbers.ToList();
foreach (var number in usedNumbers)
{
result.Remove(number);
}
return result;
}
https://codereview.stackexchange.com/questions/83515
复制相似问题