骰子问题(满堂彩和直选)
本文关键字:满堂彩 问题 | 更新日期: 2023-09-27 18:00:30
我正在做一个骰子游戏。有5个骰子,我有所有的值,我需要确定它们是组成一个完整的房子(一个3个,另一个2个)、小直(1-4、2-6或3-6)还是大直(1-5、2-6)。
也许最好的方法似乎是使用正则表达式。
有人知道我将如何在regex中表示这些规则吗?
或者,如果您能提供更好的解决方案,我将不胜感激
示例:
- 满座=44422或11166或12212等
- 小型直通=12342或54532等
- 大直=12345或52643等
编辑
修改措辞,强调这是我缺乏经验的观点。
我知道如何使用代码来实现这一点,但这似乎是一个冗长的解决方案,我想知道是否有更简单的方法。
我会让所有的数字递减,然后在每个值上做一些线性标准匹配,无论它是在int[]还是字符串中。
我不知道c#,但在脚本语言中,我会选择regexp。对于每一边,计算它在组合中出现的次数,并将结果连接在一起。例如,对于组合12342
,计数器字符串将是121100
。然后将计数器字符串与以下模式进行匹配:
/5/ = Five of a kind /4/ = Four of a kind /20*3|30*2/ = Full house /1{5}/ = Large Straight /[12]{4}/ = Small Straight /3/ = Three of a kind /2[013]*2/ = Two pair /2/ = One pair
您可以始终执行LINQ
聚合查询并计算相同卡片的数量。这将类似于(无法测试):
var query = from card in hand
group card by card into groupedCards
select new { Card = groupedCards.Key, Count = groupedCards.Count() };
这样你就很容易知道你是在处理一个可能的直线(或者什么都没有),一对,三重,等等
我不是LINQ
专家,目前还不能测试这段代码,所以我不确定它是否会按原样编译,但它可能会对您有所帮助,或者让您了解如何处理手头的问题。
例如:
如果count query=5:我们正在处理一个空指针、一个flush或一个straight=>运行特定的flush/straight逻辑。
如果count query=4:我们正在处理一对。
如果count query=3:我们处理的是双对或三重=>如果max count=3,则为三重
如果count query=2:我们正在处理满座/扑克。如果最大计数=4,则扑克
我不会评论如何查找结果,而是评论如何存储结果以供以后查找。
由于您只有46656个可能的组合,并且一个字节可以存储由此产生的手牌强度,因此这个问题比扑克手牌问题容易得多。
您可以有一个查找表,由指针作为索引组成,并与该指针的结果(某些指针可以有多个结果)相关联。每个字节都可以将所有手类型存储为二进制表示(如果不使用short,则希望如此)。
你得到的每个数字(例如66655-满座)都是一个以6为基数(1-6)的数字,将其转换为以10为基数的数字,以在查找表中获得索引。
它将需要大约46656个字节(+CPU对齐),并且可以放入CPU L2缓存。速度将是惊人的,因为你需要做的唯一操作是转换基数,以及二进制或运算来提取手的力量。
你会错过的是一只手真正的力量。66655比66644好。您可以很容易地理解这一点-您需要一个更大的类型来将结果存储到:)
我决定自己尝试一下,但最终没有使用正则表达式——我想,也许由于搜索的简单性,正则表达式会增加比它们节省的更多的复杂性。不过,我对另一个答案使用了类似的逻辑:计算每个数字的数量,并以此为基础进行所有评分:
enum RollScoreType
{
HighDie,
Pair,
TwoPair,
ThreeOfAKind,
SmallStright,
PairSmallStriaght,
FullHouse,
LargeStraight,
FourOfAKind,
FiveOfAKind
}
struct RollScore
{
public RollScoreType type;
public byte highestDie;
public byte nextHighestDie;
public RollScore(RollScoreType type, byte highest, byte next)
{
this.type = type;
this.highestDie = highest;
this.nextHighestDie = next;
}
public override string ToString()
{
return string.Format("{0} {1} {2}", type, highestDie, nextHighestDie);
}
}
static RollScore GetDiceScore(string input)
{
char[] dice = input.ToCharArray();
byte[] diceCount = new byte[6];
for (int i = 0; i < dice.Length; i++)
diceCount[int.Parse(dice[i].ToString())-1]++;
if (Array.IndexOf(diceCount, (byte)5) >= 0)
return new RollScore(RollScoreType.FiveOfAKind, (byte)(Array.IndexOf(diceCount, (byte)5) + 1), 0);
else if (Array.IndexOf(diceCount, (byte)4) >= 0)
return new RollScore(RollScoreType.FourOfAKind, (byte)(Array.IndexOf(diceCount, (byte)4) + 1), (byte)(Array.IndexOf(diceCount, (byte)1) + 1));
else if (Array.IndexOf(diceCount, (byte)3) >= 0)
{
byte three = (byte)(Array.IndexOf(diceCount, (byte)3) + 1);
if (Array.IndexOf(diceCount, (byte)2) >= 0)
{
byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
return new RollScore(RollScoreType.FullHouse, Math.Max(pair, three), Math.Min(pair, three));
}
else
return new RollScore(RollScoreType.ThreeOfAKind, three, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
}
else if (Array.IndexOf(diceCount, (byte)2) >= 0)
{
byte pair = (byte)(Array.IndexOf(diceCount, (byte)2) + 1);
byte highPair = (byte)(Array.LastIndexOf(diceCount, (byte)2) + 1);
if (highPair != pair)
return new RollScore(RollScoreType.TwoPair, highPair, pair);
else
{
byte lowMissingDie = (byte)Array.IndexOf(diceCount, (byte)0);
byte highMissingDie = (byte)Array.LastIndexOf(diceCount, (byte)0);
switch (lowMissingDie)
{
case 0:
if (highMissingDie == 5)
return new RollScore(RollScoreType.PairSmallStriaght, 5, 4);
if (highMissingDie == 1)
return new RollScore(RollScoreType.PairSmallStriaght, 6, 5);
break;
case 4:
return new RollScore(RollScoreType.PairSmallStriaght, 4, 3);
}
return new RollScore(RollScoreType.Pair, pair, (byte)(Array.LastIndexOf(diceCount, (byte)1) + 1));
}
}
byte missingDie = (byte)Array.IndexOf(diceCount, (byte)0);
switch(missingDie)
{
case 0:
return new RollScore(RollScoreType.LargeStraight, 6, 5);
case 1:
return new RollScore(RollScoreType.SmallStright, 6, 5);
case 4:
return new RollScore(RollScoreType.SmallStright, 4, 3);
case 5:
return new RollScore(RollScoreType.LargeStraight, 5, 4);
default:
return new RollScore(RollScoreType.HighDie, 6, (byte)(Array.LastIndexOf(diceCount, (byte)1, 3) + 1));
}
}
令我惊讶的是,我发现在5日滚动中,小直道和大直道的概率相等。这是真的吗!?
编辑:已修复;我看到,当我包括一对小直道时,小直道的概率会显著上升。
当我想起来的时候,一对和一条小直道可能应该使用这对作为最高的骰子,而直道中的最高数字作为下一个最高的骰子(为了[正确地比较两个都是一对和小直道的卷轴)。如果是这样,我会用以下代码替换处理PairSmallStraight的代码块:
switch (lowMissingDie)
{
case 0:
if (highMissingDie == 5)
return new RollScore(RollScoreType.PairSmallStriaght, pair, 5);
if (highMissingDie == 1)
return new RollScore(RollScoreType.PairSmallStriaght, pair, 6);
break;
case 4:
return new RollScore(RollScoreType.PairSmallStriaght, pair, 4);
}
您可以尝试将值放入列表中。这将允许您快速排序您的价值观。如果你加上这些值,你就会得到帮助。111AA=29和222KK=30。只是个主意。
这是我的代码:
public static int CalculateTotalOfSingles (int pipNumber)
{
//
var myScore = 0;
foreach (var myDie in Roll5Player.MyHand.Dice)
{
{ if (myDie.Pips == pipNumber)
myScore+= pipNumber;
}
}
//
return myScore;
}
public static int CalculateDicePips ()
{
//
var myScore = 0;
foreach (var myDie in Roll5Player.MyHand.Dice)
{
{myScore += myDie.Pips;
}
}
//
return myScore;
}
//
//
//
public static int CalculateTotalOfAllSingles (int pipNumber)
{
//
var myScore = 0;
for (int i = 1; i <= 6; i++)
{
myScore += pipNumber;
}
//
return myScore;
}
public static bool CalculateIsNOfaKind (int count)
{
//
for (var index = 1; index <= 6; index++)
{
var cntr = 0;
foreach (var myDie in Roll5Player.MyHand.Dice)
{
if (myDie.Pips == index)
cntr++;
}
//
if (cntr == count)
{
return true;
;
}
}
//
return false;
}
public static int CalculateNOfaKind (int count )
{
//
var myScore = 0;
for (var index = 1; index <= 6; index++)
{
var cntr = 0;
foreach (var myDie in Roll5Player.MyHand.Dice)
{
if (myDie.Pips == index)
cntr++;
}
//
if (cntr >= count)
{ myScore = CalculateDicePips();
return myScore;
;
}
}
//
return myScore;
}
///
public static int CaluclateFullHouse ( )
{
//
var myScore = 0;
var cntr = new int[6];
for (var index = 1; index <= 6; index++)
{
foreach (var myDie in Roll5Player.MyHand.Dice)
{
if (myDie.Pips == index)
cntr[index-1]++;
}
}
//
var boolCondA = false;
var boolCondB = false;
foreach (var i in cntr)
{
if (i == 3)
{boolCondA = true;
break;
}
}
if (boolCondA)
{
foreach (var i in cntr)
{
if (i == 2)
{boolCondB = true;
break;
}
}
}
//
if (boolCondB )
myScore = CalculateDicePips();
//
//
//
return myScore;
}
public static int CaluclateStraights (int straightCount, int score)
{
//
var tempPip = 0;
var myScore = 0;
var isFirstIteration = true;
var cntr = 0;
int[] sortedDice = new int[5];
var sortedDiceLise = new List<int>();
foreach (var myDie in Roll5Player.MyHand.Dice)
{
sortedDiceLise.Add(myDie.Pips);
}
sortedDiceLise.Sort();
foreach (var myDie in sortedDiceLise)
{
//
//
if (!isFirstIteration)
{
if (myDie == tempPip + 1)
cntr++;
}
//
isFirstIteration = false;
tempPip = myDie;
}
if (cntr == straightCount - 1)
{myScore = score;
}
//
//
//
return myScore;
}
public static int CalculateYahtzee ()
{
//
for (var index = 1; index <= 6; index++)
{
var cntr = 0;
foreach (var myDie in Roll5Player.MyHand.Dice)
{
if (myDie.Pips == index)
cntr++;
}
//
if (cntr == 5)
{
return 50;
;
}
}
//
return 0;
}