一个简单的Yahtzee游戏(译文)
By robot-v1.0
本文链接 https://www.kyfws.com/games/a-simple-yahtzee-game-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 8 分钟阅读 - 3714 个词 阅读量 0一个简单的Yahtzee游戏(译文)
原文地址:https://www.codeproject.com/Articles/8657/A-Simple-Yahtzee-Game
原文作者:Mike Kitchen
译文由本站 robot-v1.0 翻译
前言
An article on creating a simple dice game with C#.
有关使用C#创建简单骰子游戏的文章.
介绍(Introduction)
这是Yahtzee的简单版本,其中包括高分表.请享用.(This is a simple version of Yahtzee that includes a high score table. Enjoy.)
背景(Background)
这是我为CodeProject撰写的第二篇文章,因此希望你们中的一些人觉得它有用或至少很有趣.(This is my second article that I have written for CodeProject, so I hope some of you find it useful or at least fun.) 有一天,我的女儿问我是否可以为电脑购买Yahtzee.我想而不是买东西,为什么不写呢.她已经对其Beta版进行了很好的测试,因此希望在此过程中消除大多数错误.这花了我一段时间,如果您想了解我如何到达程序的历史,可以在(One day, my daughter asked me if we could get Yahtzee for the computer. I thought instead of buying something, why not write it. She has beta tested it quite well, so hopefully most of the bugs have been ironed out in the process. This has took me a while to write, and if you want to see the history of how I got to where the program is now, you can see this on) 我的网站(my website) .(.)
规则(The Rules)
可以从以下网站下载Yahtzee游戏的完整规则(The full rules for the Yahtzee game can be downloaded from) 孩之宝的网站(Hasbro’s website) .(.) 此版本的游戏将只允许一个Yahtzee奖励,并且不包含小丑规则.(This version of the game will only allow one Yahtzee bonus, and does not include the Joker rules.)
游戏(The Game)
该程序由四种形式和两个相当有用的类组成,它们可以完成大部分工作.这些类中的一个完成了您在表单顶部看到的骰子的所有工作,而另一个完成了所有的工作检查分数.(The program is made up of four forms and two rather useful classes that do most of the work. One of these classes does all of the work for the dice that you see at the top of the form, whilst the other does all of the work checking scores.)
骰子(The Dice)
的(The) dice
类继承自(class inherits from) System.Windows.Forms.UserControl
这样可以更轻松地绘制对象.控件知道如何绘制自身以及下一个要绘制的数字.后者是使用(so that it is easier to do the drawing of the object. The control knows how to draw itself and also what the next number to draw is. The latter is done using the) Random
类,最初会带来一些问题,例如如何确保两个或多个骰子没有使用相同的种子进行初始化.我通过使用以下方法实现了这一目标:(class, which originally posed some problems, like how do you make sure that two or more dice are not initialized with the same seed. I achieved this by using the following method:)
public void InitializeRandomRoll( int nSeed )
{
DateTime aTime = new DateTime(1000);
aTime = DateTime.Now;
nSeed += (int)(aTime.Millisecond);
RandomPick = new Random(nSeed);
}
而且由于初始种子总是不同的,所以主要形式具有其自己的随机数生成器,并使用下一个数字作为上述方法的种子.(And since the initial seed is always different, the main form has its own random number generator, and seeds the method above with the next number.) Yahtzee的另一个问题是,每转一圈,您都会掷骰子3次.第一次,您掷出所有五个骰子.然后,选择一些骰子,并将它们放在一边.将其他的放回杯子中并再次滚动.从第二轮开始,您可能会或可能不会将其中一些骰子放在一边,然后将剩下的任何骰子第三次掷出.(Another problem in Yahtzee is, each turn you roll the dice three times. The first time, you roll all five dice. You then select some of the dice and keep them to one side. The others you put back in the cup and roll again. From the second roll, you may or may not keep some of these dice to one side, and roll whatever dice are left a third time.) 我们需要能够保持一个骰子,以便在按下滚动按钮时它不会滚动.因此,我们添加了一个变量来保存骰子的状态.(We need to be able to hold a dice, so that it does not roll when the roll button is pressed. So, we add a variable to hold the state of the dice.)
private bool m_bHoldState = false;
public bool HoldState
{
get { return m_bHoldState; }
set { m_bHoldState = value; }
}
现在,我们需要确保如果持有骰子,它不会滚动.这只是添加一个(Now, we need to make sure that if the dice is held, it does not get rolled. This is simply a matter of adding an) if
声明(statement to the) Roll()
方法.(method.)
public void Roll()
{
// If the dice is not held, roll it
if( !HoldState )
{
RollNumber = RandomPick.Next(1,7);
this.Invalidate();
}
}
最后,如果不握住骰子,则以黑色绘制骰子;如果握住骰子,则以红色绘制.以下方法在给定点绘制一个点:(Finally, the dice is drawn in black if the dice is not held, and in red if it is. The following method draws a single dot at a given point:)
public void DrawDot( Graphics g, Point p )
{
SolidBrush myBrush;
if( HoldState )
{
myBrush = new SolidBrush( Color.Red );
}
else
{
myBrush = new SolidBrush( Color.Black );
}
g.FillEllipse( myBrush, p.X, p.Y, dotWidth, dotWidth );
myBrush.Dispose();
}
其余的骰子代码很容易理解.(The rest of the dice code is pretty easy to follow.)
计算分数(Calculating The Score)
为了计算分数,创建了一个类.该课程有许多计算个人分数的功能,还可以记录总分数,上下分数.(To calculate the scores, a class was created. The class has many functions that calculate the individual scores, it also keeps a tally of the total, upper and lower scores.) 下面显示了用于在需要相同数字时将五个骰子的总得分相加的算法.具有相同编号的所有骰子的总数将返回到表单,如果没有一个与所需的骰子相同,则为零.(The algorithm used to add up the total scores of five dice when the same number is needed is shown below. The total of all of the dice that have the same number is returned to the form, or zero if none of the dice are the same as that needed.)
public int AddUpDice( int DieNumber, Dice[] myDice )
{
int Sum = 0;
for( int i = 0; i < 5; i++ )
{
if( myDice[i].RollNumber == DieNumber )
{
Sum += DieNumber;
}
}
return Sum;
}
三种算法和四种算法非常相似.它们基于以上算法,但是不知道一种类型的三个或四个是哪个数字.因此,使用两个循环来确定三个或四个骰子确实相同.(The algorithms for Three of a Kind and Four of a Kind are very similar. They are based on the above algorithm, but do not know which number that the three or four of a kind are meant to be. So, two loops are used to determine if indeed three or four of the dice are the same.)
public int CalculateThreeOfAKind( Dice[] myDice )
{
int Sum = 0;
bool ThreeOfAKind = false;
for( int i = 1; i <= 6; i++ )
{
int Count = 0;
for( int j = 0; j < 5; j++ )
{
if( myDice[j].RollNumber == i )
Count++;
if( Count > 2 )
ThreeOfAKind = true;
}
}
if( ThreeOfAKind )
{
for( int k = 0; k < 5; k++ )
{
Sum += myDice[k].RollNumber;
}
}
return Sum;
}
计算满座人数的算法比上一个稍微复杂一些.该依据基于以下事实:如果将骰子编号按升序排序,则前两个骰子将相同,而后三个骰子将相同,但是第二个和第三个骰子必须不同.或者,前三个骰子相同,而后两个骰子相同,但是第三个和第四个骰子必须不同.这可以简单地完成(The algorithm for calculating a Full House is slightly more complicated than the previous one. The basis relies on the fact that if we sort the dice numbers into ascending order, then the first two dice will be the same and the last three dice will be the same, but the second and third dice must be different. Alternatively, the first three dice will be the same and the last two dice will be the same, but the third and fourth dice must be different. This can be done in a simple) if
声明.(statement.)
而不是返回骰子的总和,我们返回的是固定分数25.(Instead of returning the sum of the dice, we return a fixed score, which is 25.)
public int CalculateFullHouse( Dice[] myDice )
{
int Sum = 0;
int[] i = new int[5];
i[0] = myDice[0].RollNumber;
i[1] = myDice[1].RollNumber;
i[2] = myDice[2].RollNumber;
i[3] = myDice[3].RollNumber;
i[4] = myDice[4].RollNumber;
Array.Sort(i);
if( (((i[0] == i[1]) && (i[1] == i[2])) && // Three of a Kind
(i[3] == i[4]) && // Two of a Kind
(i[2] != i[3])) ||
((i[0] == i[1]) && // Two of a Kind
((i[2] == i[3]) && (i[3] == i[4])) && // Three of a Kind
(i[1] != i[2])) )
{
Sum = 25;
}
return Sum;
}
用于计算大笔直的算法与计算满屋子的算法相似,但是简单得多.的基础(The algorithm for calculating a Large Straight is similar to that of calculating a Full House, but much simpler. The basis for the) if
陈述是,对五个骰子进行排序时,它们将包含数字1\2\3\4和5,或者数字2\3\4\5和6.没有其他组合是可接受的.(statement is that when sorted, the five dice will contain the numbers 1, 2, 3, 4 and 5, or the numbers 2, 3, 4, 5 and 6. No other combination is acceptable.)
同样,我们返回固定分数40,而不是返回骰子的总和.(Again, instead of returning the sum of the dice, we return a fixed score, which is 40.)
public int CalculateLargeStraight( Dice[] myDice )
{
int Sum = 0;
int[] i = new int[5];
i[0] = myDice[0].RollNumber;
i[1] = myDice[1].RollNumber;
i[2] = myDice[2].RollNumber;
i[3] = myDice[3].RollNumber;
i[4] = myDice[4].RollNumber;
Array.Sort(i);
if( ((i[0] == 1) &&
(i[1] == 2) &&
(i[2] == 3) &&
(i[3] == 4) &&
(i[4] == 5)) ||
((i[0] == 2) &&
(i[1] == 3) &&
(i[2] == 4) &&
(i[3] == 5) &&
(i[4] == 6)) )
{
Sum = 40;
}
return Sum;
}
计算小直线度的算法比大直线度算法更复杂.的基础(The algorithm for calculating a Small Straight is more complicated than the Large Straight algorithm. The basis for the) if
陈述是,四个骰子必须包含按数字顺序且没有空格的数字.当两个数字相同时会出现问题.通过将相同的数字移到数组的末尾并忽略它,可以解决此问题.(statement is that four dice must contain numbers that are in a numerical sequence, with no gaps. A problem arises when two of the numbers are the same. This is solved, by moving the number that is the same to the end of the array and ignoring it.)
同样,我们返回固定分数30,而不是返回骰子的总和.(Again, instead of returning the sum of the dice, we return a fixed score, which is 30.)
public int CalculateSmallStraight( Dice[] myDice )
{
int Sum = 0;
int[] i = new int[5];
i[0] = myDice[0].RollNumber;
i[1] = myDice[1].RollNumber;
i[2] = myDice[2].RollNumber;
i[3] = myDice[3].RollNumber;
i[4] = myDice[4].RollNumber;
Array.Sort(i);
// Problem can arise hear, if there is more than one of the same number, so
// we must move any doubles to the end
for( int j = 0; j < 4; j++ )
{
int temp = 0;
if( i[j] == i[j+1] )
{
temp = i[j];
for( int k = j; k < 4; k++ )
{
i[k] = i[k+1];
}
i[4] = temp;
}
}
if( ((i[0] == 1) && (i[1] == 2) && (i[2] == 3) && (i[3] == 4)) ||
((i[0] == 2) && (i[1] == 3) && (i[2] == 4) && (i[3] == 5)) ||
((i[0] == 3) && (i[1] == 4) && (i[2] == 5) && (i[3] == 6)) ||
((i[1] == 1) && (i[2] == 2) && (i[3] == 3) && (i[4] == 4)) ||
((i[1] == 2) && (i[2] == 3) && (i[3] == 4) && (i[4] == 5)) ||
((i[1] == 3) && (i[2] == 4) && (i[3] == 5) && (i[4] == 6)) )
{
Sum = 30;
}
return Sum;
}
Yahtzee的算法与"三种"和"四种"相同.同样,我们返回固定分数50,而不是返回骰子的总和.(The algorithm for Yahtzee is the same as for Three of a Kind and Four of a Kind. Again, instead of returning the sum of the dice, we return a fixed score, which is 50.)
public int CalculateYahtzee( Dice[] myDice )
{
int Sum = 0;
for( int i = 1; i <= 6; i++ )
{
int Count = 0;
for( int j = 0; j < 5; j++ )
{
if( myDice[j].RollNumber == i )
Count++;
if( Count > 4 )
Sum = 50;
}
}
return Sum;
}
在计算Chance分数时,我们实际上不需要做任何检查,我们只需要将骰子加起来并作为数字返回即可.(We do not really need to do any checking when calculating the Chance score, we simply add up the dice and return it as a number.)
public int AddUpChance( Dice[] myDice )
{
int Sum = 0;
for( int i = 0; i < 5; i++ )
{
Sum += myDice[i].RollNumber;
}
return Sum;
}
计算分数(Counting the scores)
因此,当我们知道比赛结束时,我们会统计分配的分数.由于只有14个可能的分数,因此我们知道何时停止.分数计数保存在以下变量中:(So that we know when the game is over, we keep count of how many scores have been allocated. As there are only fourteen possible scores, we know when to stop. The score count is kept in the following variable:)
private int ScoreCount = 0;
分配每个分数后,(After each score is allocated, the) Reset
方法检查游戏是否结束.(method checks to see if the game is over.)
if( ScoreCount == 14 )
{
DialogResult result;
// Displays the MessageBox.
result = MessageBox.Show( "Your Score is " + TotalScore.Text + ".
Would You like to play again?",
"End Of Game",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question );
if( result == DialogResult.Yes )
{
// Reset Everything
. . .
}
else
{
this.Close();
}
}
玩的开心!(Enjoy the game!)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C# Win2K WinXP Windows .NET .NET1.0 Visual-Studio Dev 新闻 翻译