我正在尝试制作一个程序,该程序可以随机绘制两张纸牌,但是在绘制新纸牌时不会再次绘制这两张相同的纸牌。由于某种原因,在程序的第19次运行时,窗口冻结,我必须停止并重新启动程序。我注意到,每次抽出新卡时,内存使用量都会增加到159MB,然后在第19次抽奖中,内存使用黄色的“指示托管堆垃圾收集开始”回落(不确定是否有意义,我是C#的新手,这是我的第一个GUI程序。
这里是代码和2位信息,据我所知没有评论
namespace Card_Dealer
{
public partial class Form1 : Form
{
public string[] drawncards = new string[52];
public Form1()
{
InitializeComponent();
}
public string randomCard()
{
bool valid = false;
string cardc = "";
int i = 1;
string convertedcards = "";
do
{
cardc = "_";
Random random = new Random();
cardc += random.Next(1, 13);
int suit = random.Next(1, 4);
switch (suit)
{
case 1: cardc += "H"; break;
case 2: cardc += "C"; break;
case 3: cardc += "D"; break;
case 4: cardc += "S"; break;
}
cardc += "";
foreach (var x in drawncards.Select((value, index) => new { value, index }))
{
if (cardc == x.value)
{
valid = false;
break;
}
else if (x.value == null)
{
valid = true;
drawncards[x.index] = cardc;
foreach (string el in drawncards) { convertedcards += el + " "; }
label1.Text = convertedcards;
return cardc;
}
}
} while (valid == false);
return "";
}
private void button1_Click(object sender, EventArgs e)
{
if (drawncards.Contains(null))
{
string cardc = randomCard();
object O = Resource1.ResourceManager.GetObject(cardc);
card1.Image = (Image)O;
card1.Image = new Bitmap(card1.Image, new Size(345, 528));
string cardc2 = randomCard();
object J = Resource1.ResourceManager.GetObject(cardc2);
card2.Image = (Image)J;
card2.Image = new Bitmap(card2.Image, new Size(345, 528));
}
else
{
label1.Text ="All Cards Drawn!";
}
}
}
}
我该怎么做才能阻止程序崩溃?
谢谢!
答案 0 :(得分:3)
代码冻结的可能原因是:
Random
主循环的每次迭代中都实例化do
类,这增加了产生相同序列的伪随机数的可能性,从而产生了相同卡每次迭代;并且,然后,由于(1),do
循环会继续生成相同的卡,并且与(2)结合使用,它永远不会(或仅在一些不重要的迭代次数之后)找到未绘制的卡。
让我建议您根据以下内容重写代码:
Random
实例作为类的字段List<string> availableCards
字段availableCards
中删除项目并将其放置到List<string> drawnCards
Random
实例而不是卡片本身来生成{em> indexes 到availableCards
中进一步的改进:
答案 1 :(得分:0)
我不确定是什么导致您的程序崩溃,我能够进行一个类和单元测试,该类和单元测试的功能基本上相同,但是没有UI组件。
我确实发现的一个问题是,当遍历drawcards数组时,即使这些项目为null,您仍将空白附加到标签上。您可以像这样修改foreach来过滤掉这些空项目
foreach (string el in drawncards.Where(card => card != null))
我个人将使用列表而不是数组,并且仅在抽出卡片后将项目添加到列表中。
抱歉,这不是一个完整的答案,我会以评论的形式发布,但我没有这样做的权利。
编辑:
我还将修改循环的主体,以使它不会在标签项之间添加空格,除非已经添加了至少一项:
foreach (string el in drawncards.Where(card => card != null))
{
if (!string.IsNullOrWhiteSpace(convertedcards))
convertedcards += " ";
convertedcards += el;
}