winforms 如何让窗体加载识别按钮的名称在事件处理程序的26个按钮的刽子手游戏使用C#?

piztneat  于 2022-12-14  发布在  C#
关注(0)|答案(2)|浏览(156)
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;

        }

    }

我是一个编程新手,所以请考虑到这一点。
我正在尝试使用C#(WindowsForm)创建一个Hangman游戏。
我的问题在if (button.Text.Equals(l1[i].Text));它会给我一个错误:“虽然我在Button button= sender as Button;中将name“button”声明为name,但当前上下文”“中不存在该按钮.
另一个问题是在以前的Hangman项目中,我尝试了另一种方法,但概念是相同的,就是像这里一样使用bool b,如果用户点击了一个按钮,Form 1知道b变为true,而不是保持false。但这并没有发生,因为Form1在我点击按钮之前加载,所以即使b变为true,它不能再次加载Form1,因为一个表单只能创建一次,一旦我们运行程序。
那么我该怎么做来解决这两个问题呢?

uxh89sit

uxh89sit1#

这里没有足够的信息来确定,所以做一些假设,所有的按钮创建在表单设计器与一个字母表的每个字母和用户有尽可能多的尝试,因为他想,直到答案是揭示。
问题是您正在测试窗体Load事件中的按钮单击(if(b)),该事件在按下任何按钮之前触发一次,因此不会起作用。
我建议你在当前声明bool b = false;的地方声明Label[] l1;-这使得在button_click事件中可以访问。反正你不需要b,所以删除它。
然后将Button Click事件处理程序更改为:

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");        
}

我还没有创建一个工作的例子,所以不能肯定这将工作,但应该有帮助。我会把它作为一个评论,但不能引用代码的方式。

cbjzeqam

cbjzeqam2#

您的问题是“如何让Form load识别26个按钮的事件处理程序中的按钮名称”。您还提到,当您单击按钮时,您的目标是为您的游戏更改bool值的状态。
第二个简单的方法是将Appearance属性设置为Button,使用一个看起来像按钮的Checkbox。(看起来像按钮),简化Load事件处理程序的一种方法是迭代MainForm中的 * 所有 * 控件,如下所示。此示例将演示如何不仅识别控件的Name,而且使用该名称自动生成游戏设置所需的字母表字符,并沿着此过程中添加一个事件以在用户单击时处理按钮。
下面是设计器窗口中TableLayoutPanel的视图,其中包含26个复选框。

此方法将访问Form上的每个控件,并对每个控件调用initCheckBox方法。

public MainForm() =>  InitializeComponent();
protected override void OnLoad(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;
}

我们将传递的特定fX将通过查看控件名称来设置文本,从中提取整数,并将整数转换为字符。我们还将为每个复选框分配一个Click处理程序。

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;
}

下面是程序运行时'MainForm'的外观:

你所能做的就是获取Click处理函数的这个通用功能,并扩展它以执行你的游戏所需的功能。作为一个如何实现这个功能的Minimal Reproducible Example,让我们通过在主窗体标题栏上显示新的bool值来实现onAnyClick

private void onAnyClick(object sender, EventArgs e)
{
    if (sender is CheckBox checkbox)
    {
        Text = $"{checkbox.Text} = {checkbox.Checked}";
    }
}

点击“按钮T”后,标题栏显示如下:

相关问题