contingiouscrayon
contingiouscrayon

Reputation: 15

My application on Windows Forms goes into break when I try to call these functions

I have files on my computer containing all cards within a deck. What I want to do is generate all 54 numbers and give 7 of them to the user in the form of buttons so they can play these cards, another 7 cards to the computer, and the remaining cards stored in a queue for either of them to press to get more if needed. But the error I am facing is generating the 7 random numbers that need to be stored for the user to get.

This is the code I am referring to:

I believe this part of the code calls the SetButtonImage to begin to compile on load.

public FmClassic()
        {
            InitializeComponent();

            SetButtonImage();
        }

This is SetButtonImage gathering the images from within my computer as well as calling another function to generate the random numbers.

private void SetButtonImage()
        {
            Stack<int> ShuffleOnTime = ShuffleOneTime();
            string Cards = String.Join("\n", ShuffleOnTime);
            button1.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(0, Cards.IndexOf(Environment.NewLine))}.png");
            button2.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(1, Cards.IndexOf(Environment.NewLine))}.png");
            button3.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(2, Cards.IndexOf(Environment.NewLine))}.png");
            button4.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(3, Cards.IndexOf(Environment.NewLine))}.png");
            button5.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(4, Cards.IndexOf(Environment.NewLine))}.png");
            button6.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(5, Cards.IndexOf(Environment.NewLine))}.png");
            button7.Image = Image.FromFile($"C:\\filepath\\{Cards.Substring(6, Cards.IndexOf(Environment.NewLine))}.png");

        }

This is then called to ensure they are random and not called twice with the hash table as well as converting to a string which I think is better for when searching for files.

public Stack<int> ShuffleOneTime()
        {
            Random random = new Random();
            Stack<int> generatednumbers = new Stack<int>();
            Stack<int> randomNumbers = GenerateRandomNumber(random, generatednumbers);

            return randomNumbers;
        }

This helps generate the numbers and return it back to the other function.

Stack<int> GenerateRandomNumber(Random random, Stack<int> generatednumbers)
        {
            //Queue<int> Cards = new Queue<int>();
            //Queue<string> realNumbers = new Queue<string>();
            int randomNumber;
            do
            {
                randomNumber = random.Next(1, 54);
                generatednumbers.Push(randomNumber);
                if (generatednumbers.Count >= 2)
                {
                    int Compare1 = generatednumbers.Pop();
                    int Compare2 = generatednumbers.Pop();
                    if (Compare1 == Compare2)
                    {
                        generatednumbers.Push(Compare1);
                    }
                }

            } while (generatednumbers.Count != 53);
            //string number = generatednumbers.ToString();
            //realNumbers.Enqueue(number);
            return generatednumbers;
        }

I have tried making it a string rather than an integer to help find it but it won't work. The filenames for the cards are all 1.jpg, 2.jpg etc so I don't know why there is an error. Everything compiles but then my screen freezes for 60 seconds and them inputs this error:

Managed Debugging Assistant 'ContextSwitchDeadlock' : 'The CLR has been unable to transition from COM context 0xa73c68 to COM context 0xa73bb0 for 60 seconds.

Upvotes: 1

Views: 189

Answers (1)

dr.null
dr.null

Reputation: 4695

So, you have 53 images in some folder, and you want to shuffle and pick. You can simplify this task since the file names are the numbers range that you want to generate and shuffle.

Create a method that generates shuffled numbers of a given range.

private readonly Random rnd = new Random();

// https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle
private int[] GenerateShuffledNumbers(int start, int count)
{
    var numbers = Enumerable.Range(start, count).ToArray();

    for (int i = 0; i < numbers.Length; i++)
    {
        var j = i + (int)(rnd.NextDouble() * (numbers.Length - i));
        (numbers[i], numbers[j]) = (numbers[j], numbers[i]);
    }

    return numbers;
}

All what you need to have in the SetButtonImage method is:

private void SetButtonImage()
{
    var dir = @"The Images Directory Path";
    var buttons = new[]
    {
        button1, button2, button3, button4,
        button5, button6, button7
    };
    var numbers = GenerateShuffledNumbers(1, 53);

    for (int i = 0; i < buttons.Length; i++)
    {
        // jpg or png? Append the right extension.
        var imgFile = Path.Combine(dir, $"{numbers[i]}.jpg");
        buttons[i].Image?.Dispose();
        buttons[i].Image = Image.FromStream(new MemoryStream(File.ReadAllBytes(imgFile)), true, false);
    }
}

Note, the numbers array contains all the 53 numbers, you can take a range:

var someNumbers = numbers.Take(7);

... you can skip and take:

// Take the first 7...
var set1 = numbers.Take(7);
// Take the next 7...
var set2 = numbers.Skip(7).Take(7);
// Skip the first 14 and take the rest...
var set3 = numbers.Skip(14);

All of which return IEnumerable<int>. Call .ToList() or .ToArray() if needed.

If you need to create a Stack<int> or Queue<int>, both have a constructor overload that takes IEnumerable<T>.

var stack = new Stack<int>(numbers);
var queue = new Queue<int>(numbers);

Upvotes: 1

Related Questions