英文:
Clicking on the buttons doesn't do anything
问题
我正在为学校项目在Windows Forms中编写此代码。基本上是一个记忆数字方块位置的思维游戏。问题在于我卡在了点击显示数字的按钮部分。以下是我的代码(更新版本,但仍然没有点击按钮的结果):
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project
{
public partial class Form1 : Form
{
// ...(你的代码继续)
private void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
if (showingNumbers)
return;
int expectedNumber = currentPlayerLevel;
if (button.Text == expectedNumber.ToString())
{
currentPlayerLevel++;
if (currentPlayerLevel > MaxLevel)
{
gameTimer.Stop();
EndGame();
}
else if (currentPlayerLevel > currentLevel)
{
currentLevel++;
UpdateLevelLabel();
StartNewLevel();
}
}
}
// ...(你的代码继续)
}
}
请注意,我只翻译了代码部分,没有包括图片和其他内容。如果你需要进一步的帮助,请随时提出。
英文:
I'm making this code in Windows Forms for a school project. Its basically a mind game in which you have to remember the positions of numbers in squares. The problem is that I'm stuck on the part of clicking the buttons which display numbers. Here's my code (updated version still no result of clicking a button):
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project
{
public partial class Form1 : Form
{
private const int MaxLevel = 25;
private const int ShowTimeMilliseconds = 1000;
private const int InitialTimeSeconds = 5;
private Button[] buttons;
private int currentLevel;
private int currentPlayerLevel;
private bool gameStarted;
private bool showingNumbers;
private Timer showNumbersTimer;
private Timer gameTimer;
private Random random;
public Form1()
{
InitializeComponent();
InitializeButtons();
random = new Random();
}
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach (var button in buttons)
{
button.Click += Button_Click;
}
startButton.Click += startButton_Click;
}
private void InitializeGame()
{
currentPlayerLevel = 1;
currentLevel = 1;
UpdateLevelLabel();
}
private void StartGame()
{
gameStarted = true;
gameTimer = new Timer();
gameTimer.Interval = 1000;
gameTimer.Tick += GameTimer_Tick;
gameTimer.Start();
InitializeGame();
int randomButtonIndex = random.Next(0, currentLevel * currentLevel);
foreach (Button button in buttons)
{
button.Text = string.Empty;
}
ShuffleButtons();
buttons[randomButtonIndex].Text = "1";
StartNewLevel();
startButton.Enabled = false;
}
private void ShuffleButtons()
{
int n = buttons.Length;
while (n > 1)
{
n--;
int k = random.Next(n + 1);
Button value = buttons[k];
buttons[k] = buttons[n];
buttons[n] = value;
}
}
private void StartNewLevel()
{
showingNumbers = true;
DisableButtons();
List<int> numbers = Enumerable.Range(1, currentLevel).ToList();
numbers = numbers.OrderBy(x => random.Next()).ToList();
int randomButtonIndex = random.Next(0, currentLevel);
for (int i = 0; i < currentLevel; i++)
{
buttons[i].Text = numbers[i].ToString();
buttons[i].BackColor = Color.LightGreen;
buttons[i].Enabled = true;
}
buttons[randomButtonIndex].Text = "1";
showNumbersTimer = new Timer();
showNumbersTimer.Interval = ShowTimeMilliseconds;
showNumbersTimer.Tick += ShowNumbersTimer_Tick;
showNumbersTimer.Start();
}
private void EndLevel()
{
showingNumbers = false;
showNumbersTimer.Stop();
ClearButtons();
EnableButtons();
}
private void EndGame()
{
gameStarted = false;
gameTimer.Stop();
currentPlayerLevel = 0;
UpdateLevelLabel();
MessageBox.Show("Game Over!");
}
private void UpdateLevelLabel()
{
textBox1.Text = $"Level: {currentPlayerLevel}";
}
private void ShowNumbersTimer_Tick(object sender, EventArgs e)
{
int index = Array.FindIndex(buttons, button => button.Text == "1");
buttons[index].BackColor = SystemColors.Control;
buttons[index].Text = string.Empty;
EndLevel();
}
private int initialTimeSeconds = InitialTimeSeconds;
private void GameTimer_Tick(object sender, EventArgs e)
{
initialTimeSeconds--;
if (initialTimeSeconds < 0)
{
gameTimer.Stop();
EndGame();
}
UpdateTimerLabel();
}
private void UpdateTimerLabel()
{
textBox2.Text = initialTimeSeconds.ToString();
}
private void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
if (showingNumbers)
return;
int expectedNumber = currentPlayerLevel;
if (button.Text == expectedNumber.ToString())
{
currentPlayerLevel++;
if (currentPlayerLevel > MaxLevel)
{
gameTimer.Stop();
EndGame();
}
else if (currentPlayerLevel > currentLevel)
{
currentLevel++;
UpdateLevelLabel();
StartNewLevel();
}
}
}
private void DisableButtons()
{
foreach (Button button in buttons)
{
button.Enabled = false;
}
}
private void EnableButtons()
{
foreach (Button button in buttons)
{
button.Enabled = true;
}
}
private void ClearButtons()
{
foreach (Button button in buttons)
{
button.Text = string.Empty;
button.BackColor = SystemColors.Control;
}
}
private void startButton_Click(object sender, EventArgs e)
{
if (!gameStarted)
{
InitializeGame();
StartGame();
}
}
}
}
Also some images of how the form looks when started:
I tried adding the buttons with code which did not work well and I'm expecting the program to allow me to click on the buttons and actually work.
答案1
得分: 1
对于基本的按钮或其他控件,你可以通过Visual Studio设计器中控件的属性窗格将控件连接到事件处理程序。但如果你想要稍微复杂一点,希望所有这些按钮都使用相同的方法,那么你可以在代码中连接事件处理程序:
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach(var button in buttons)
{
button.Click += this.Button_Click;
}
}
确保InitializeButtons()
方法只调用一次!
还有这个让我感到难过:
buttons.OrderBy(b => Guid.NewGuid())
大多数情况下,它的性能会比O(n)差一点,但有可能出现极少的病态情况,导致它花费很长时间才能完成。相反,查找如何执行Fisher-Yates洗牌,它的时间复杂度确切为O(n)。
这也让我感到难过:
Random random = new Random();
这行代码本身没问题,但放置的位置不对。与其限定在一个方法的范围内,最好将伪随机数生成器的范围延长。将其限定在类(窗体)或应用程序的范围内会更好。
英文:
For a basic button or other control, you connect the control to the event handlers via the Control's properties pane in the Visual Studio designer. But you're getting just a bit fancy, where you want all these buttons to use the same method. In that case, you can wire up the event handlers in code:
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach(var button in buttons)
{
button.Click += this.Button_Click;
}
}
Make sure this InitializeButtons()
method is only called once!
Also, this makes me sad:
buttons.OrderBy(b => Guid.NewGuid())
It's going to be just a little worse than O(n) most of the time, but it's possible to get into rare pathologic cases where this takes a loooooong time to finish. Instead, look up how to do a Fisher-Yates shuffle, which is guaranteed as exactly O(n).
This also makes me sad:
Random random = new Random();
The line itself is fine, but it's in the wrong place. Rather than scoped to a method, you are much better off when the PRNG is long-lived. Scope it to the class (form) or application, instead.
答案2
得分: 0
处理按钮点击事件时,您可以在Form1.cs[Design]文件中双击按钮。它会在InitializeComponent();
中添加事件处理程序,如下所示:this.button1.Click += new System.EventHandler(this.button1_Click);
最好的做法是不要修改InitializeComponent文件,但您仍然可以只更改此行:this.button1.Click += new System.EventHandler(this.Button_Click);
当按下button1时,这将调用函数Button_Click(),然后您可以将其应用到所有按钮。
或者(最佳实践),您可以修改函数InitializeButtons()
如下:
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach (var button in buttons)
{
button.Click += new System.EventHandler(this.Button_Click);
}
startButton.Click += new System.EventHandler(this.startButton_Click);
}
它将为按钮数组中的每个按钮创建事件处理程序,并在单击按钮时调用函数Button_Click();
。
英文:
To handle the clicking Event on a button, you can double click the button in your Form1.cs[Design] file. It will add the eventHandler in the: InitializeComponent();
like so: this.button1.Click += new System.EventHandler(this.button1_Click);
It's good practice not to modify the InitializeComponent file, but it is still possible for you to just change the line with this:
this.button1.Click += new System.EventHandler(this.Button_Click);
this will call you function Button_Click() when button1 is pressed, you can then to this to all your buttons.
Alternatively (and best practics), you can modify your function InitializeButtons()
to this:
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach(var button in buttons)
{
button.Click += new System.EventHandler(this.Button_Click);
}
startButton.Click += new System.EventHandler(this.startButton_Click);
}
It will create the EventHandler for each button in buttons, and when you click a button it will call you function Button_Click();
答案3
得分: 0
我纠正了你的游戏,但它可能不完全符合你的要求。
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace 项目
{
public partial class Form1 : Form
{
private const int 最大级别 = 25;
private const int 显示时间毫秒 = 1000;
private const int 初始时间秒 = 15;
private Button[] 按钮们;
private int 当前级别;
private int 当前玩家级别;
private bool 游戏已开始;
private bool 显示数字中;
private Timer 显示数字计时器;
private Timer 游戏计时器;
private Random 随机数生成器;
private List<string> 要记住的顺序 = new List<string>();
public Form1()
{
InitializeComponent();
初始化按钮();
随机数生成器 = new Random();
}
private void 初始化按钮()
{
按钮们 = new Button[] { 按钮2, 按钮3, 按钮4, 按钮5, 按钮6, 按钮7, 按钮8, 按钮9, 按钮10, 按钮11, 按钮12, 按钮13, 按钮14, 按钮15, 按钮16, 按钮17, 按钮18, 按钮19, 按钮20, 按钮21, 按钮22, 按钮23, 按钮24, 按钮25, 按钮26 };
foreach (var 按钮 in 按钮们)
{
按钮.Click += 按钮_Click;
}
开始按钮.Click += 开始按钮_Click;
}
private void 初始化游戏()
{
当前玩家级别 = 1;
当前级别 = 1;
更新级别标签();
}
private void 开始游戏()
{
游戏已开始 = true;
游戏计时器 = new Timer();
游戏计时器.Interval = 1000;
游戏计时器.Tick += 游戏计时器_Tick;
游戏计时器.Start();
初始化游戏();
int 随机按钮索引 = 随机数生成器.Next(0, 当前级别 * 当前级别);
foreach (Button 按钮 in 按钮们)
{
按钮.Text = string.Empty;
}
打乱按钮顺序();
开始新级别();
开始按钮.Enabled = false;
}
private void 打乱按钮顺序()
{
int n = 按钮们.Length;
while (n > 1)
{
n--;
int k = 随机数生成器.Next(n + 1);
Button 值 = 按钮们[k];
按钮们[k] = 按钮们[n];
按钮们[n] = 值;
}
}
private void 开始新级别()
{
显示数字中 = true;
清除按钮();
int 随机按钮索引;
List<int> 已使用索引 = new List<int>();
for (int i = 0; i < 当前玩家级别; i++)
{
随机按钮索引 = 获取未使用的随机索引(已使用索引);
已使用索引.Add(随机按钮索引);
按钮们[随机按钮索引].Text = (i + 1).ToString();
按钮们[随机按钮索引].BackColor = Color.LightGreen;
按钮们[随机按钮索引].Enabled = true;
要记住的顺序.Add(按钮们[随机按钮索引].Name);
}
显示数字计时器 = new Timer();
显示数字计时器.Interval = 显示时间毫秒;
显示数字计时器.Tick += 显示数字计时器_Tick;
显示数字计时器.Start();
}
private int 获取未使用的随机索引(List<int> 已使用索引)
{
int 随机索引 = 随机数生成器.Next(0, 按钮们.Length - 1);
if (已使用索引.Contains(随机索引) == true)
{
随机索引 = 获取未使用的随机索引(已使用索引);
}
return 随机索引;
}
private void 结束级别()
{
显示数字中 = false;
显示数字计时器.Stop();
清除按钮();
启用按钮();
}
private void 结束游戏()
{
游戏已开始 = false;
游戏计时器.Stop();
当前玩家级别 = 0;
更新级别标签();
MessageBox.Show("游戏结束!");
}
private void 更新级别标签()
{
文本框1.Text = $"级别: {当前玩家级别}";
}
private int 显示数字数量;
private void 显示数字计时器_Tick(object sender, EventArgs e)
{
if (显示数字数量 == 0)
{
int 索引;
for (int i = 0; i < 当前玩家级别; i++)
{
索引 = Array.FindIndex(按钮们, 按钮 => 按钮.Text == (i + 1).ToString());
按钮们[索引].BackColor = SystemColors.Control;
按钮们[索引].Text = string.Empty;
}
显示数字中 = false;
游戏计时器.Start();
}
显示数字数量--;
}
private int 初始时间秒数 = 初始时间秒;
private void 游戏计时器_Tick(object sender, EventArgs e)
{
初始时间秒数--;
if (初始时间秒数 < 0)
{
游戏计时器.Stop();
结束游戏();
}
更新计时器标签();
}
private void 更新计时器标签()
{
文本框2.Text = 初始时间秒数.ToString();
}
private void
<details>
<summary>英文:</summary>
I corrected your game, but it may not exactly do what you wanted.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Project
{
public partial class Form1 : Form
{
private const int MaxLevel = 25;
private const int ShowTimeMilliseconds = 1000;
private const int InitialTimeSeconds = 15;
private Button[] buttons;
private int currentLevel;
private int currentPlayerLevel;
private bool gameStarted;
private bool showingNumbers;
private Timer showNumbersTimer;
private Timer gameTimer;
private Random random;
private List<string> toRememberOrder = new List<string>();
public Form1()
{
InitializeComponent();
InitializeButtons();
random = new Random();
}
private void InitializeButtons()
{
buttons = new Button[] { button2, button3, button4, button5, button6, button7, button8, button9, button10, button11, button12, button13, button14, button15, button16, button17, button18, button19, button20, button21, button22, button23, button24, button25, button26 };
foreach (var button in buttons)
{
button.Click += Button_Click;
}
startButton.Click += startButton_Click;
}
private void InitializeGame()
{
currentPlayerLevel = 1;
currentLevel = 1;
UpdateLevelLabel();
}
private void StartGame()
{
gameStarted = true;
gameTimer = new Timer();
gameTimer.Interval = 1000;
gameTimer.Tick += GameTimer_Tick;
gameTimer.Start();
InitializeGame();
int randomButtonIndex = random.Next(0, currentLevel * currentLevel);
foreach (Button button in buttons)
{
button.Text = string.Empty;
}
ShuffleButtons();
//buttons[randomButtonIndex].Text = "1";
StartNewLevel();
startButton.Enabled = false;
}
private void ShuffleButtons()
{
int n = buttons.Length;
while (n > 1)
{
n--;
int k = random.Next(n + 1);
Button value = buttons[k];
buttons[k] = buttons[n];
buttons[n] = value;
}
}
private void StartNewLevel()
{
showingNumbers = true;
ClearButtons();
int randomButtonIndex;
List<int> indexUsed = new List<int>();
for (int i = 0; i < currentPlayerLevel; i++)
{
randomButtonIndex = GetRandomIndexNotUse(indexUsed);
indexUsed.Add(randomButtonIndex);
buttons[randomButtonIndex].Text = (i+1).ToString();
buttons[randomButtonIndex].BackColor = Color.LightGreen;
buttons[randomButtonIndex].Enabled = true;
toRememberOrder.Add(buttons[randomButtonIndex].Name);
}
//buttons[randomButtonIndex].Text = "1";
show_num = currentPlayerLevel;
showNumbersTimer = new Timer();
showNumbersTimer.Interval = ShowTimeMilliseconds;
showNumbersTimer.Tick += ShowNumbersTimer_Tick;
showNumbersTimer.Start();
}
private int GetRandomIndexNotUse(List<int> indexUsed)
{
int randomIndex = random.Next(0, buttons.Length - 1);
if(indexUsed.Contains(randomIndex) == true)
{
randomIndex = GetRandomIndexNotUse(indexUsed);
}
return randomIndex;
}
private void EndLevel()
{
showingNumbers = false;
showNumbersTimer.Stop();
ClearButtons();
EnableButtons();
}
private void EndGame()
{
gameStarted = false;
gameTimer.Stop();
currentPlayerLevel = 0;
UpdateLevelLabel();
MessageBox.Show("Game Over!");
}
private void UpdateLevelLabel()
{
textBox1.Text = $"Level: {currentPlayerLevel}";
}
private int show_num;
private void ShowNumbersTimer_Tick(object sender, EventArgs e)
{
if (show_num == 0)
{
int index;
for (int i = 0; i < currentPlayerLevel; i++)
{
index = Array.FindIndex(buttons, button => button.Text == (i+1).ToString());
buttons[index].BackColor = SystemColors.Control;
buttons[index].Text = string.Empty;
}
showingNumbers = false;
gameTimer.Start();
}
show_num--;
//EndLevel();
}
private int initialTimeSeconds = InitialTimeSeconds;
private void GameTimer_Tick(object sender, EventArgs e)
{
initialTimeSeconds--;
if (initialTimeSeconds < 0)
{
gameTimer.Stop();
EndGame();
}
UpdateTimerLabel();
}
private void UpdateTimerLabel()
{
textBox2.Text = initialTimeSeconds.ToString();
}
private void Button_Click(object sender, EventArgs e)
{
Button button = (Button)sender;
if (showingNumbers)
return;
if(button.Name == toRememberOrder.First())
{
toRememberOrder.Remove(button.Name);
}
else
{
gameTimer.Stop();
EndGame();
}
if(toRememberOrder.Count() == 0)
{
gameTimer.Stop();
Timer_Reset();
currentPlayerLevel++;
UpdateLevelLabel();
StartNewLevel();
}
}
private void DisableButtons()
{
foreach (Button button in buttons)
{
button.Enabled = false;
}
}
private void EnableButtons()
{
foreach (Button button in buttons)
{
button.Enabled = true;
}
}
private void ClearButtons()
{
foreach (Button button in buttons)
{
button.Text = string.Empty;
button.BackColor = SystemColors.Control;
}
}
private void Timer_Reset()
{
initialTimeSeconds = InitialTimeSeconds;
UpdateTimerLabel();
}
private void startButton_Click(object sender, EventArgs e)
{
if (!gameStarted)
{
InitializeGame();
StartGame();
}
}
}
}
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论