3 本我 5天前 67次点击
Deck类需要使用类图定义以下成员:
● Card[]类型的私有字段卡片。
● 公共的默认构造函数。
● 公共方法GetCard(),它带有一个int参数卡牌值,并返回一个Card类型的对象。
● 公共方法Shuffle(),它不带参数,返回void。
示例
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace 装备1
{
public class Deck
{
private Card[] 卡片;
public Deck()
{
卡片 = new Card[52];
for (int 花色值 = 0; 花色值 < 4; 花色值++)
{
for (int 数字值 = 1; 数字值 < 14; 数字值++)
{
卡片[花色值 * 13 + 数字值 - 1] = new Card((Suit)花色值,(Rank)数字值);
}
}
}
然后实现GetCard()方法,为指定的索引返回Card对象,或者以与前面相同的方式抛出一个异常:
public Card GetCard(int 卡片值)
{
if (卡片值 >= 0 && 卡片值 <= 51)
return 卡片[卡片值];
else
throw (new System.ArgumentOutOfRangeException("卡片值",卡片值,"值需要介于0和51之间"));
}
最后实现Shuffle()方法。这个方法创建一个临时的扑克牌数组,并把扑克牌从现有的cards数组随机复制到这个数组中。这个函数的主体是一个从0~51的循环,在每次循环时,都会使用.NET Framework中System.Random类的实例生成一个0~51之间的随机数。进行实例化后,这个类的对象使用方法Next(X)生成一个介于0~X之间的随机数。有了一个随机数后,就可以将它用作临时数组中Card对象的索引,以便复制cards数组中的扑克牌。
为记录已赋值的扑克牌,我们还有一个bool变量的数组,在复制每张牌时,把该数组中的值指定为true。在生成随机数时,检查这个数组,看看是否已经把一张牌复制到临时数组中由随机数指定的位置上了,如果已经复制,将生成另一个随机数。
这不是完成该任务的最高效方式,因为生成的许多随机数都可能找不到空位置以复制扑克牌。但它仍能完成任务,而且很简单,因为C#代码的执行速度很快,我们几乎觉察不到延迟。代码如下:
public void Shuffle()
{
Card[] newDeck = new Card[52];
bool[] 分配 = new bool[52];
Random 来源 = new Random();
for (int i = 0; i < 52; i++)
{
int destCard = 0;
bool foundCard = false;
while (foundCard == false)
{
destCard = 来源.Next(52);
if (分配[destCard] == false)
foundCard = true;
}
分配[destCard] = true;
newDeck[destCard] = 卡片[i];
}
newDeck.CopyTo(卡片,0);
}
}
}
这个方法的最后一行使用System.Array类的CopyTo()方法(在创建数组时使用),把newDeck中的每张扑克牌复制回cards中。也就是说,我们使用同一个cards对象中的同一组Card对象,而不是创建新实例。如果改用cards=newDeck,就会用另一个对象替代cards引用的对象实例。如果其他地方的代码仍保留对原cards实例的引用,就会出问题—— 不会洗牌。