1

Hello I'm making 10x10 cube with panels and the panels needs to change color when you click X times the panel but the code is so large, Is there another way for the code not to be so long?

This is my code:

int cont1 = 0, cont2 = 0, cont3 = 0, cont4 = 0, cont5 = 0, cont6 = 0, cont7 = 0, cont8 = 0, cont9 = 0, cont10 = 0;

then the event to change de color(All of my Panels have the same code but difference is "cont" and panel name):

 private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            cont1++;
            if (cont1 <= 5)
            {
                panel1.BackColor = Color.SlateBlue;
            }
            if (cont1 >=5)
            {
                panel1.BackColor = Color.Cyan;
            } 
            if (cont1 >= 10)
            {
                panel1.BackColor = Color.Lime;
            }
            if (cont1 >= 15)
            {
                panel1.BackColor = Color.Yellow;
            }
            if (cont1 >= 20)
            {
                panel1.BackColor = Color.Red;
            } 
        }

//other panel 
private void panel2_MouseClick(object sender, MouseEventArgs e)
        {
            cont2++;
            if (cont2 <= 5)
            {
                panel2.BackColor = Color.SlateBlue;
            }
            if (cont2 >= 5)
            {
                panel2.BackColor = Color.Cyan;
            }
            if (cont2 >= 10)
            {
                panel2.BackColor = Color.Lime;
            }
            if (cont2 >= 15)
            {
                panel2.BackColor = Color.Yellow;
            }
            if (cont2 >= 20)
            {
                panel2.BackColor = Color.Red;
            }
        }

note: Each panel changes its color, not all at the same time Actually work with 4x4 but 10x10 is large for me

ADyson
  • 57,178
  • 14
  • 51
  • 63

2 Answers2

3

You don't actually need to create large amount of variables because you need to keep track of control states. You can leverage the existence of control Tags and cut down the amount of code you write.

Be it 1000 x 1000 panels the below method would work flawlessly for your usecase. All you need do is point all target panel mouseClick to it and allow it handle the rest.

private void panel_MouseClick(object sender, MouseEventArgs e)
{
    Control ctrl = sender as Control;

    //get previous value from control tag or start at 0
    int count = ctrl.Tag == null ? 0 : (int)ctrl.Tag;

    //set backcolor of control based on tag number             
    if (count >= 20) ctrl.BackColor = Color.Red;
    else if (count >= 15) ctrl.BackColor = Color.Yellow; 
    else if (count >= 10) ctrl.BackColor = Color.Lime;
    else if (count >= 5)  ctrl.BackColor = Color.Cyan;
    else ctrl.BackColor = Color.SlateBlue; 

   // if (count == xx)
    //{// you may want to reset count after a certain number. Do that here...}

    ctrl.Tag = ++count;
}
Joel Coehoorn
  • 399,467
  • 113
  • 570
  • 794
Giddy Naya
  • 4,237
  • 2
  • 17
  • 30
  • if i want add a label to count the clicks on panel i can add `label1.Text = count.ToString();`? but the problem of large code is the same – Javier Aceves Aug 06 '19 at 02:13
  • You can make the names of labels relative to their panel. For example: `panel1` can have a label named `panel1_label` and `panel2` would have `panel2_label` then at the end of `MouseClick` function you can find the label using the `ctrl.Name` append with the word `_label` to get the target label for the panel. For more info about finding controls with name [see this reply](https://stackoverflow.com/a/1639106/8043806). Ask a new question if this solves your problem. – Giddy Naya Aug 06 '19 at 02:55
  • if i can add in the same mouse event on panel? because i need implement when you click in the panel inside have label who show the number of clicks? – Javier Aceves Aug 09 '19 at 21:21
  • I think that is a different question than the initial. You might want to ask that as a new question to get the solution as an answer. – Giddy Naya Aug 09 '19 at 21:43
  • ok i do that, but you can explain me this: your example in `book isTag Parse = Int64.TryParse(ctrl.Tag, out count);` the convert doesn't work because "object" cannot covert in "string" – Javier Aceves Aug 10 '19 at 02:47
  • Call `.ToString()` on Tag before parsing. See update – Giddy Naya Aug 10 '19 at 03:07
  • i'm getting two error the "if" is invalid because c# expect ; and out count show me "out int" cant convert in "out long" – Javier Aceves Aug 10 '19 at 03:33
  • Change int64 to int32. Remove condition from if braces, see update – Giddy Naya Aug 10 '19 at 03:38
  • 2
    Thanks to boxing, the `Tag` property is perfectly capable of holding `int` values directly. Converting to and from string is insane. – Joel Coehoorn Aug 10 '19 at 03:44
0

You could refactor this to use a method where you pass in the specific panel object and the current count value, rather than repeating the same logic over and over:

    private void panel1_MouseClick(object sender, MouseEventArgs e)
    {
        cont1++;
        updateColour(panel1, cont1);
    }

    //other panel 
    private void panel2_MouseClick(object sender, MouseEventArgs e)
    {
        cont2++;
        updateColour(panel2, cont2);
    }

    private void updateColour(Control ctrl, int count)
    {
        if (count >= 20)
        {
            ctrl.BackColor = Color.Red;
        }
        else if (count >= 15)
        {
            ctrl.BackColor = Color.Yellow;
        }
        else if (count >= 10)
        {
            ctrl.BackColor = Color.Lime;
        }
        else if (count >= 5)
        {
            ctrl.BackColor = Color.Cyan;
        }
        else
        {
            ctrl.BackColor = Color.SlateBlue;
        }
    }

Note 1: I also re-wrote the count-checking logic so that it didn't unnecessarily paint the panel (up to) 4 different colours, instead it will always paint it just once. (In your previous logic, if the count was 21, it would first set the panel to Cyan (because 21 >= 5), then Lime (because 21 is also >= 10), and so on until the last if).

Note 2: Since BackColor is actually a property of the parent Control class, you could use this updateColour function with any control, not just a Panel)

In general in your code, if you find yourself repeating the same basic logic more than once, that usually means it's time to turn that logic into a separate method which can then be re-used across your application.

There is likely to be more refactoring you can do here (e.g. putting the panels and related counts into a data structure which links them together, and then using only one "click" handler method for all the panels, and using the sender to determine which panel was clicked) - but my example should reduce quite a large amount of your repetition.

ADyson
  • 57,178
  • 14
  • 51
  • 63
  • ooh! thaks!, but if my cube is 10x10 i need like 100 count right? i can apply other thing to make more smaller? – Javier Aceves Aug 06 '19 at 00:22
  • Potentially yes - see my latest edit. I'll leave that as an exercise for you to try and figure out the exact code to make it work. Ask again if you get stuck. – ADyson Aug 06 '19 at 00:24