Home > OS >  How to let Form load recognize the name of the button in the event handler of 26 buttons for Hangman
How to let Form load recognize the name of the button in the event handler of 26 buttons for Hangman

Time:12-11

        public Form1()
    {
        InitializeComponent();
    }
    Random g = new Random();
    bool b = false;
    private void button_click(object sender, EventArgs e)
    {
        Button button= sender as Button;
        b=true;           
    }
    private void Form1_Load(object sender, EventArgs e)
    {   
        button1.Click  = button_click;
        button2.Click  = button_click;
        button3.Click  = button_click;
        button4.Click  = button_click;  
        button5.Click  = button_click;  
        button6.Click  = button_click;  
        button7.Click  = button_click;
        button8.Click  = button_click;
        button9.Click  = button_click;
        button10.Click  = button_click;
        button11.Click  = button_click;
        button12.Click  = button_click;
        button13.Click  = button_click;
        button14.Click  = button_click;
        button15.Click  = button_click;
        button16.Click  = button_click;
        button17.Click  = button_click;
        button18.Click  = button_click;
        button19.Click  = button_click;
        button20.Click  = button_click;
        button21.Click  = button_click;
        button23.Click  = button_click;
        button24.Click  = button_click;
        button25.Click  = button_click;
        button26.Click  = button_click;

        StreamReader sr = new StreamReader(@"C:\Users\victus-pc\OneDrive\Desktop\notepad1.txt");
        int i;
        string s = sr.ReadToEnd();
        string[] t = s.Split(',');
        int l = g.Next(t.Length);
        Label[] l1 = new Label[t[l].Length];
        for (i = 0; i < l1.Length; i  )
        {
            l1[i] = new Label();
            l1[i].Size = new Size(30, 30);
            l1[i].Left = 20   50 * i;
            l1[i].Top = 20;
            l1[i].Text = t[l][i].ToString();
            l1[i].Visible = false;
            this.Controls.Add(l1[i]);
        }

        if (b)
        {
            for (i = 0; i < l1.Length; i  )
            {
                if (button.Text.Equals(l1[i].Text))
                {
                    l1[i].Visible = true;
                }
                else
                    label2.Text = (int.Parse(label2.Text) - 1).ToString();
                break;
            }
            if (int.Parse(label2.Text) == 0)
                MessageBox.Show("Game Over");
            b = false;

        }

    }

I'm a beginner in programming,so please take that into consideration.

I'm trying to create a Hangman game using C# (WindowsForm).

My problem is in if (button.Text.Equals(l1[i].Text)); it gives me an error that is : "The name "button" does not exist in the current context", though i declared it as name in Button button= sender as Button;.

Another problem is that in a previous Hangman project, i tried another way but same concept that is to use bool b like here,and if the user clicked on a button,Form 1knows that bbecomes true and doesn't stay false. But that doesn't happen, because Form1 loads before i click on a button,so even if b becomes true,it cannot load the Form1 again because a form can only be created once ,once we run the program.

So what should i do to fix these 2 problems?

CodePudding user response:

There's not enough info here to be certain, so making some assumptions that all the buttons created in form designer with one for each letter of the alphabet and the user has as many tries as he wants until answer is revealed.

The issue is that you are testing for button click (if (b)) in the form Load event, which fires once and before any buttons have been pressed, so won't work.

I would suggest you declare Label[] l1; where you currently declare bool b = false; - that makes is accessible in the button_click event. You don't need b anyway so remove it.

Then change your Button Click event handler to this:

private void button_click(object sender, EventArgs e)
{
    Button button= sender as Button;
    for (int i = 0; i < l1.Length; i  )
    {
      if (button.Text.Equals(l1[i].Text))
      {
         l1[i].Visible = true;
      }
      else  label2.Text = (int.Parse(label2.Text) - 1).ToString();  // Not sure what label2 is, so not sure if this is correct.
    }
    if (int.Parse(label2.Text) == 0) MessageBox.Show("Game Over");        
}

I haven't created a working example, so can't be sure this will work as-is, but should help. I would have made it a comment, but couldn't quote code that way.

CodePudding user response:

You mention several issues in your post so let me see if I can answer a couple of the main questions. Then, after giving this a try, consider posting new questions one-at-a-time for issues that remain. As I understand it, when you click on buttons your objective is to change the states of bool values for your game. The easy way to do that is to use a Checkbox that looks like a button by setting its Appearance property to Button. Here's a view of a TableLayoutPanel in the designer window that holds 26 checkboxes.

designer

Your Load event of your MainForm can be simplified by iterating the control tree.

public MainForm() =>  InitializeComponent();
protected override void onl oad(EventArgs e)
{
    base.OnLoad(e);
    // This will call initCheckBox() for every Control of the `MainForm`. 
    IterateControlTree(null, initCheckBox, null);
}
internal delegate bool FxControlDlgt(Control control, Object args);
// Iterate the control tree with 'some function' generically known as `fX`.
internal bool IterateControlTree(Control control, FxControlDlgt fX, Object args)
{
    if (control == null) control = this;
    if (!fX(control, args)) return false;
    foreach (Control child in control.Controls)
    {
        if (!IterateControlTree(child, fX, args))
        {
            return false;
        }
    }
    return true;
}

The specific fX that we'll pass is going to set the text by looking at the control name, extracting the integer from it, and converting the integer to a character. We'll also assign a Click handler to each checkbox.

private bool initCheckBox(Control control, object args)
{
    // This is called for every control, so filter for CheckBox only.
    if (control is CheckBox checkbox)
    {
        // One way to autogenerate the Text from the Name property.
        string sval = checkbox.Name.Replace("checkBox", string.Empty);
        if(int.TryParse(sval, out int offset))
        {
            char c = (char)('A'   (offset - 1));
            checkbox.Text = c.ToString();
        }
        checkbox.Click  = onAnyClick;
    }
    return true;
}

Here's what the `MainForm' looks like now when the program is run:

screenshot

What you can do is take this generic functionality of the Click handler and extend it to perform the functionality you need for your game. As a title-bar-text

  • Related