首页 > 解决方案 > 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

  1. Cards are stored in a resource file called Resource1
  2. 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!

标签: c#

解决方案


您的代码冻结的可能原因是:

  1. Random您在主循环的每次迭代中都实例化该类do,这增加了产生相同伪随机数序列的概率,因此每次迭代都会产生相同的卡片;和,
  2. 您从与架构精通的相反方向解决问题:您随机生成结果卡片,而不是从堆栈中随机挑选卡片。

然后,由于(1),do循环不断生成相同的牌,并且结合(2)它永远不会(或仅在一些不平凡的迭代次数之后)找到未绘制的牌。

让我建议您根据以下内容重写代码:

  • 有一个实例 Random作为类的字段
  • 有一个List<string> availableCards领域,并在一开始
  • 将绘图卡构造为从 中移除项目availableCards并将它们放置到List<string> drawnCards
  • 使用Random实例生成索引availableCards不是卡片本身

进一步可能的改进:

  • 使用属性而不是字段
  • 业务逻辑(即卡片栈的管理、绘制卡片)分解成一个单独的类,与用户界面(表单类)解耦
  • 数据与逻辑分离——有一个单独的数据类来封装一堆卡片和单独的业务逻辑类来管理绘图卡

推荐阅读