如何在运行时创建大量按钮? [英] How can I create a large number of buttons on runtime?

查看:84
本文介绍了如何在运行时创建大量按钮?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试将游戏开发为练习。



在运行时,我需要程序以总共63个按钮开始(生成优先问题),随机排列。



到目前为止,我正在尝试使用的代码,我得到一个 StackOverflowException



以下是我的一些代码:



I'm trying to develop a game as an exercise.

On runtime, I need the program to start with a total of 63 buttons (with the generated problem as a priority), randomly arranged.

So far, with the code I'm trying, I get a StackOverflowException.

Here are some bits of my code:

private void TimedMode_Load(object sender, EventArgs e)
{
    totalButtons = 0;
    nTotal = 63;

    while (totalButtons < nTotal)
    {
        createRandom();
    }

    tmr3sec.Enabled = true;
    tmr3sec.Start();
}




void createRandom()
        {
            //nProb initialized to 0
            //problem initialized to ""
            nProb = Convert.ToInt32(rnd_nProb.Next(7));
            problem = items[Convert.ToInt32(rnd_prob.Next(1))];

            createProblem();
        }

        void setItems(int val)
        {
            switch (problem)
            {
                case "Donut":
                    donutCount += val;
                    break;

                case "Pencil":
                    pencilCount += val;
                    break;
            }
        }
        void createProblem()
        {
            //check if creating the new buttons will
            //result in an excess number of buttons
            if ((totalButtons + nProb) <= nTotal)      
                                                     
            {
                Random random = new Random();

                switch (problem)
                {
                    case "Donut":
                        donut[0] = Image.FromFile(GUILoc + "ChocoDonut_Hori.png");
                        donut[1] = Image.FromFile(GUILoc + "ChocoDonut_Verti.png");
                        donut[2] = Image.FromFile(GUILoc + "PinkDonut_Hori.png");
                        donut[3] = Image.FromFile(GUILoc + "PinkDonut_Verti.png");

                        //set value of probCount to the value of donutCount 
                        //to check later if 
                        //there are enough donuts
                        probCount = donutCount;
                        returnPic = donut[Convert.ToInt32(random.Next(donut.Length - 1))];
                        break;


                    case "Pencil":
                        pencil[0] = Image.FromFile(GUILoc + "GreenPencil_Down.png");
                        pencil[1] = Image.FromFile(GUILoc + "GreenPencil_Up.png");
                        pencil[2] = Image.FromFile(GUILoc + "PinkPencil_Down.png");
                        pencil[3] = Image.FromFile(GUILoc + "PinkPencil_Up.png");
                        probCount = pencilCount;
                        returnPic = pencil[Convert.ToInt32(random.Next(pencil.Length - 1))];
                        break;

                }

                //If for example the problem is donut, the nProb is 5, 
                //but there are 6 donuts already in the panel, 
                //then just create a new problem
                //Note that I am still deliberating this part, 
                //maybe you can share your thoughts?
                if (nProb <= probCount)
                {
                    createRandom();
                }
 
                //If buttons are insufficient, and will not be excess, 
                //create the buttons
                else 
                {
                    createButton();
                    totalButtons += nProb;
                }


            }

            else //If there are excess buttons
            {
                //For example, totalButtons = 59. Random # is 6. 59 + 6 = 65
                //It should not exceed 63.
                int total2 = nTotal - totalButtons;
                //nProb = (63 - 59) = 4
                nProb = total2;
                totalButtons += nProb;
                setItems(nProb); //increase the count of the item
                createButton();

            }

            dispProb = problem;
            dispProbNo = nProb;

        }




void createButton()
 {

     int k = 0;

       while (k < nProb)
       {
         btn = new Button();

         setPic = returnPic;

         btn.Image = setPic;
         btn.Name = "btn_" + problem + k.ToString();
         btn.Tag = problem;
         Size size = new Size(70, 70);
         btn.FlatStyle = FlatStyle.Flat;
         btn.BackColor = Color.Transparent;
         btn.FlatAppearance.BorderSize = 0;
         btn.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
         btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
         btn.FlatAppearance.MouseDownBackColor = Color.Transparent;
         btn.Size = size;
         setLoc(btn);
         k++;

     }
 }







        void setLoc(Button bttn)
        {
            //if there is no need to generate a new random location
            //if true, it means there is already a position
            //no need to generate a new number

            //cellPosition initialized to false
            if (cellPosition == false) 
            {
                createRandomPos();              
            }
        
            else
            {

            }

            if (panDoodles.GetControlFromPosition(randcol, randrow) == null) //if cell is available
            {
                cellPos = new TableLayoutPanelCellPosition(randcol, randrow);
                panDoodles.SetCellPosition(bttn, cellPos);
                cellPosition = false;
            }

            else //if cell is occupied
            {
                createRandomPos();
                setLoc(bttn);
            }
            
            panDoodles.Controls.Add(bttn);
        }


void createRandomPos()
{
    randrow = Convert.ToInt32(rand_row.Next(0, 9));
    randcol = Convert.ToInt32(rand_col.Next(0, 7));

}







请原谅我的代码结构! :)我仍然在C#周围找到我的方式。

我有一个7x9网格,所以总共有63个按钮。我知道,这是一个很大的数字,但这就是为什么我来这里问我将如何有效地做到这一点。





什么这将是最好的方法吗?




Pardon the structure of my code! :) I'm still finding my way around C#.
I have a 7x9 grid, so that's a total of 63 buttons. A big number, I know, but that's why I came here to ask how I will be able to do that efficiently.


What would be the best approach to do this?

推荐答案

最佳方法?不要......那是很多按钮...



但如果必须,我首先要看看<$ c $的实际价值c> totalButtons 使用调试器,假设你在两个地方更新它:

Best approach? Don't...that's a lot of buttons...

But if you must, I'd start by looking at the actual value of totalButtons using the debugger, given that you update it in two places:
totalButtons += totalProb;
...
totalButtons += nProb;

因为这是你的循环终止条件......你需要知道它发生了什么。



所以使用调试器,并在中放置一个断点,同时循环。跳过方法调用并查看值发生了什么。因为如果循环中的任何时候都没有上升,你会得到一个堆栈溢出 - 就像你一样。



谢谢你你的帮助!实际上它是一种隐藏的对象游戏,程序会要求你在网格中寻找东西。:)例如,寻找5个苹果等等。

我重新开始到目前为止它还在工作,但我仍然需要研究如何在网格中只有一个确切的或不太大的项目被要求,而且如果没有无限的递归,我似乎无法做到这一点




好​​的,所以转储随机性! :笑:



相反,设置一个位置列表,然后随机随机播放:

And since it's your loop termination condition...you need to know what is happening to it.

So use the debugger, and put a breakpoint in the while loop. Step over the method calls and see what has happened to the value. Because if that doesn't go up at any time in the loop, you will get a stack overflow - just as you are.

"Thank you for your help! Actually it's a hidden object game of sorts, where the program will ask you to look for something in the grid. :) Like for example, look for 5 apples, etc.
I started over and so far it's working, but I still have to work on how there should only be an exact or a not too big number of the item being asked for in the grid, and I can't seem to do that without the endless recursion"


OK, so dump the randomness! :laugh:

Instead, set up a list of locations, and "shuffle" them randomly:

List<Item> ordered = new List<Item>();
for (int i = 0; i < 63; i++)
    {
    Item item = new Item(i);
    ...
    ordered.Add(item);
    }
List<Item> shuffled = new List<Item>();
while (ordered.Count > 0)
    {
    int remove = rand.Next(ordered.Count);
    Item item = ordered[remove];
    ordered.Remove(item);
    shuffled.Add(item);
    }



然后以随机顺序获取物品或地点列表或任何内容,无需递归。

看看我的意思?


You then get a list of Items or locations or whatever in a random order and no need to recurse.
See what I mean?


如果我理解你的代码正确,你有一个固定数量的按钮,你想从一个池中随机分配一个问题和图像到每个按钮问题。



如果是这种情况,我认为你应该首先创建你的按钮并将它们对准你的网格。

If I understand your code correctly, you have a fixed number of buttons and you want to assign a problem and image to each button randomly from a pool of problems.

If this is the case, I think you should create your buttons first and align them into your grid.
// As you have a fixed number of problems, you can create an enum
private enum ProblemTypes
{
    Undefined = -1,    // Used to show an unintialized value
    Pencil = 0,
    Donut = 1
}

// Also only load your images once
private void LoadImages()
{
    // I have no idea where you create the variables donut and pencil
    donut[0] = Image.FromFile(GUILoc + "ChocoDonut_Hori.png");
    donut[1] = Image.FromFile(GUILoc + "ChocoDonut_Verti.png");
    donut[2] = Image.FromFile(GUILoc + "PinkDonut_Hori.png");
    donut[3] = Image.FromFile(GUILoc + "PinkDonut_Verti.png");}
    
    pencil[0] = Image.FromFile(GUILoc + "GreenPencil_Down.png");
    pencil[1] = Image.FromFile(GUILoc + "GreenPencil_Up.png");
    pencil[2] = Image.FromFile(GUILoc + "PinkPencil_Down.png");
    pencil[3] = Image.FromFile(GUILoc + "PinkPencil_Up.png");
}

private void CreateButtons()
{
    int numberOfButtons = 63;        // This can be configurable later on
    int positionX = 0;
    int positionY = 0;
    int horizontalSpace = 25;
    int verticalSpace = 20;
    for (int i=0; i<numberofbuttons;>    {
        Button btn = new Button();
        btn.Name = String.Format("button{0}", i+1);
        btn.Tag = ProblemTypes.Undefined;
        btn.X = positionX;
        btn.Y = positionY;
        btn.Size = new Size(70, 70);
        btn.FlatStyle = FlatStyle.Flat;
        btn.BackColor = Color.Transparent;
        btn.FlatAppearance.BorderSize = 0;
        btn.FlatAppearance.BorderColor = Color.FromArgb(0, 255, 255, 255);
        btn.FlatAppearance.MouseOverBackColor = Color.Transparent;
        btn.FlatAppearance.MouseDownBackColor = Color.Transparent;
        
        // Reset the x-position and increment the y-position every 7 column
        if (i % 7 == 0)
        {
            positionX = 0;
            positionY += verticalSpace;
        }
        else
        {
            positionX += (btn.Size.X + horizontalSpace);
        }
     
        // I have not taken into account your TableLayoutPanel
        // If you want to use it you have to figure that part out yourself
        panDoodles.Controls.Add(btn);
    }
}

// This is where you have to put in some work
public void AssignProblemToButtons()
{
    foreach (Button btn in panDoodles.Controls)
    {
        // Not sure how you want to assign problem type and image
        // That part of your code is a bit confusing so this is just the principal functionality
        btn.Tag = GetProblem(problemRandomNumber);
        btn.Image = GetImage((ProblemTypes)btn.Tag, imageRandomNumber);
    }
}





这只是一个开始,而不是整个代码。

它只是展示了如何更改逻辑以避免递归函数

(递归函数在正确的上下文中很好,但不在这里)



祝你好运,我希望这有点帮助。



This just a start for you and not the entire code.
It just shows how you can change the logic a bit in order to avoid recursive functions
(Recursive functions are good in the right context, but not here)

Good luck and I hope this was a bit helpful.


这篇关于如何在运行时创建大量按钮?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆