我很无聊所以我决定尝试&制作一个我自己的Yahtzee游戏,与实际游戏一样精确的规则,只是想测试我的编程技巧(这还不是很令人惊讶)。
下面张贴的代码用于检查直道(小型和大型)。 我确定你可以亲眼看到,但万一你不这样做,它就像这样:
所有5个骰子的值都放在List中,然后使用List<T>.Sort()
方法对其进行排序。
现在它们应按升序排列在列表中(例如1,2,3,4,5)。
为了找出它是否是一个大直线,我只是使用一个int,如果检测到一个小直线,它会增加1的值,然后由于我的&#找到一个大直线34;大直=小直* 2&#34;逻辑,可能有缺陷,但似乎对我有意义:)。
这很有效,但并非总是如你所知,如果我在中间某处有重复值,这段代码就不会起作用,例如1,2,3,3,4,6。这一系列的数字仍然应该给我一个小的直线,但它不会。
现在我的实际问题是:如何修改此代码,以便它始终能够检测到小代码和小代码。大直道?
List<int> valList = new List<int>();
foreach (Dice d in dList)
{
valList.Add(d.Value);
}
valList.Sort();
txtSmall.Text = "0";
txtLarge.Text = "0";
int straight = 0;
if (valList[0] == valList[1] - 1 && valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1)
straight++;
if (valList[1] == valList[2] - 1 && valList[2] == valList[3] - 1 && valList[3] == valList[4] - 1)
straight++;
switch (straight)
{
case 1:
if (txtSmall.IsEnabled)
txtSmall.Text = "30";
break;
case 2:
if (txtSmall.IsEnabled)
txtSmall.Text = "30";
if (txtLarge.IsEnabled)
txtLarge.Text = "40";
break;
}
PS:万一你需要知道我的Dice
课程是什么,这里是(虽然我不明白你为什么需要它):
class Dice
{
private static CryptoRandom r = new CryptoRandom();
public static int uBound = 1;
public static int lBound = 7;
public string Path { get; set; }
private int value;
public int Value
{
get { return value; }
}
private bool locked;
public bool Locked
{
get { return locked; }
}
public Dice(int lowerBound = 1, int upperBound = 6)
{
uBound = upperBound + 1;
lBound = lowerBound;
this.Roll();
this.locked = false;
}
public void Roll()
{
this.value = r.Next(lBound, uBound);
}
public void Lock()
{
this.locked = true;
}
public void Unlock()
{
this.locked = false;
}
}
PPS:如果有更好的方法来检测这些内容,请随时分享,但也请尝试回答我的问题:)。
答案 0 :(得分:2)
一种非常简单的方法是在排序之前调用Distinct
,这会删除所有重复项:
List<int> allDice = new List<int>() { 1, 2, 3, 3, 4, 6 };
IEnumerable<int> uniqueDice = allDice.Distinct();
IEnumerable<int> sortedDice = uniqueDice.Sort(x => x);
//etc.
否则,您的方法是合理的。没有什么能够迅速成为寻找小直道的更好方法。
答案 1 :(得分:2)
如果性能不是问题,我正确理解问题,我会尝试这样的事情:
var count = dList.Count; //6
var straights = dList.Select(dice => dice.Value)
.Distinct() //5,3,1,6,4
.OrderBy(dice => dice.Value) //1,3,4,5,6
.Select(dice => dice.Value + (count--)) //7,8,8,8,8
.GroupBy(n => n) //[7,{7}],[8,{8,8,8,8}]
.OrderByDecending(group => group.Count());
var longestStraight = straights.First().Count(); //4
答案 2 :(得分:1)
这是另一种方法,只是为了好玩:
/// <summary>
/// Determines if the dice passed in contain a strait
/// </summary>
/// <param name="dice">The dice to test</param>
/// <returns>0 if there are no straits, 1 if there is a small strait,
/// or 2 if it contains both a large and small strait</returns>
private static int ContainsStrait(IEnumerable<int> dice)
{
var uniqueDice = dice.Distinct().ToList();
if (uniqueDice.Count < 4) return 0;
uniqueDice.Sort();
int consecutiveNumbers = 1;
int lastValue = -1;
foreach (var uniqueDie in uniqueDice)
{
if (uniqueDie == lastValue + 1)
{
consecutiveNumbers++;
}
else
{
consecutiveNumbers = 1;
}
lastValue = uniqueDie;
}
return (consecutiveNumbers > 4) ? 2 : (consecutiveNumbers > 3) ? 1 : 0;
}
测试它:
private static void Main()
{
var rolls = new List<List<int>>
{
{new List<int> {3, 3, 3, 3, 3, 3}},
{new List<int> {1, 2, 3, 4, 3, 2}},
{new List<int> {2, 2, 3, 4, 5, 2}},
{new List<int> {3, 3, 3, 4, 5, 6}},
{new List<int> {1, 2, 3, 4, 5, 2}},
{new List<int> {2, 2, 3, 4, 5, 6}}
};
foreach (var roll in rolls)
{
int result = ContainsStrait(roll);
Console.WriteLine("The roll: {0} does {1}contain a small strait {2} a large strait",
string.Join(", ", roll),
result > 0 ? "" : "not ",
result == 2 ? "and" : result == 1 ? "but not" : "or");
}
}