如何停止程序在第19次运行时崩溃?

时间:2019-11-10 16:02:49

标签: c#

我正在尝试制作一个程序,该程序可以随机绘制两张纸牌,但是在绘制新纸牌时不会再次绘制这两张相同的纸牌。由于某种原因,在程序的第19次运行时,窗口冻结,我必须停止并重新启动程序。我注意到,每次抽出新卡时,内存使用量都会增加到159MB,然后在第19次抽奖中,内存使用黄色的“指示托管堆垃圾收集开始”回落(不确定是否有意义,我是C#的新手,这是我的第一个GUI程序。

这里是代码和2位信息,据我所知没有评论

  1. 卡存储在名为Resource1的资源文件中
  2. 卡被命名为“ _ [编号1-13] [套装H,C,D,S]”,例如“ _3C”是3个俱乐部
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!";
            }

        }
    }
}

我该怎么做才能阻止程序崩溃?

谢谢!

2 个答案:

答案 0 :(得分:3)

代码冻结的可能原因是:

  1. 您在主Random主循环的每次迭代中都实例化do类,这增加了产生相同序列的伪随机数的可能性,从而产生了相同卡每次迭代;并且,
  2. 您从与结构上精明的方向相反的方向解决问题:您随机生成结果卡,而不是从堆栈中随机生成挑选卡。

然后,由于(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;
}