c# - How to stop program crashing on 19th run?
问题描述
I'm trying to make a program that draws two random cards but will not draw those two same cards again when new cards are drawn. For some reason, on the 19th run of the program, the window freezes and I have to stop and restart the program. I've noticed that every time new cards are drawn the memory use increases up to 159MBs and then on the 19th draw, it drops back down with a yellow "Indicates start of a managed heap garbage collection" (not sure if this is relevant, I'm relatively new to C# and this is my first GUI program).
Here is the code and 2 bits of info as I know there are no comments
- Cards are stored in a resource file called Resource1
- Cards are named "_[number 1-13][suit H, C, D, S]" e.g. "_3C" is 3 of clubs
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!";
}
}
}
}
What should I do to stop the program from crashing?
Thanks!
解决方案
您的代码冻结的可能原因是:
Random
您在主循环的每次迭代中都实例化该类do
,这增加了产生相同伪随机数序列的概率,因此每次迭代都会产生相同的卡片;和,- 您从与架构精通的相反方向解决问题:您随机生成结果卡片,而不是从堆栈中随机挑选卡片。
然后,由于(1),do
循环不断生成相同的牌,并且结合(2)它永远不会(或仅在一些不平凡的迭代次数之后)找到未绘制的牌。
让我建议您根据以下内容重写代码:
- 有一个实例
Random
作为类的字段 - 有一个
List<string> availableCards
领域,并在一开始 - 将绘图卡构造为从 中移除项目
availableCards
并将它们放置到List<string> drawnCards
- 使用
Random
实例生成索引而availableCards
不是卡片本身
进一步可能的改进:
- 使用属性而不是字段
- 将业务逻辑(即卡片栈的管理、绘制卡片)分解成一个单独的类,与用户界面(表单类)解耦
- 数据与逻辑分离——有一个单独的数据类来封装一堆卡片和单独的业务逻辑类来管理绘图卡
推荐阅读
- swift - 如何将导航栏后退按钮图像设置为默认符号?
- spring-boot - spring boot 在 URL 中定义的名称为“WDSDataSource”的无效 bean 定义“
- android - 如何使用同一个应用制作抽屉式导航和底部导航?
- javascript - 如何在 React 中渲染具有特定道具的组件(对象)数组?
- c# - 泛型传递类型参数
- python - 如何在这个范围内打印奇数,即使增加 2 也能得到所有的数字?
- java - 将字符串解析为 JsonObject
- mongodb - 在 mongodb 中与 $sum 聚合
- vue.js - 如何在单击期间将多个参数从父组件传递给子组件
- android - 自定义 Drawable 作为 CardView 背景