虽然循环不能按预期从列表中随机选取新字符串

时间:2022-01-14 18:14:52

Being a complete beginner I think I've done something seriously wrong within my WPF application as the while loop I've incorporated doesn't work as planned.

作为一个完全的初学者,我认为我在WPF应用程序中做了一些严重的错误,因为我已经合并的while循环不能按计划运行。

List<string> alreadyUsedReagents = new List<string>(new string[] {});
List<string> alreadyUsedMetals = new List<string>(new string[] { });

List<string> reagents = new List<string>(new string[]{
        "Hexaaqua ion",
        "Dilute NaOH",
        "Excess NaOH",
        "Dilute NH₃",
        "Excess NH₃",
        "Salt",
        "Na₂CO₃",
        "HCl"});

public void RefreshReagents()
{
    alreadyUsedReagents.Clear();
}

public string CycleThroughReagents()
{
    bool keepinLoop = true;
    string chosenReagent = null;

    while (keepinLoop == true)
    {
        int r = rnd.Next(reagents.Count);
        string pickedReagent = (string)reagents[r];


        if (!alreadyUsedReagents.Contains(pickedReagent))
        {
            alreadyUsedReagents.Add(pickedReagent);
            chosenReagent = pickedReagent;
            keepinLoop = false;
        }

        if (alreadyUsedReagents.Count == 8)
        {
            RefreshReagents();
            keepinLoop = false;
        }
        else
        {
            keepinLoop = true;
        }
    }

    return chosenReagent;
}

The while loop is suppose to loop through and return a reagent that has not been already used, all the used reagents are suppose to be stored within the alreadyUsedReagents list which the while loop analyses, then this CycleThroughReagents method is used within my SetButtonContent method which sets the button properties.

while循环假设循环并返回尚未使用的试剂,所有使用的试剂都假设存储在while循环分析的alreadyUsedReagents列表中,然后在我的SetButtonContent方法中使用此CycleThroughReagents方法按钮属性。

public void SetButtonContent(string ChosenMetal, TextBlock reagentText, TextBlock transMetalText,
        Button opt1, Button opt2, Button opt3, Button opt4, Button opt5, Button opt6, Button opt7, Button opt8)
{
    string pickedMetal = "Cobalt";
    string pickedReagent = CycleThroughReagents();

    reagentText.Text = pickedReagent;
    transMetalText.Text = pickedMetal;
} 

A switch function is implemented within this method which sets the tag of a specific button to 'correct' if the button matches the reagent set.

在该方法中实现了切换功能,如果按钮与试剂组匹配,则将特定按钮的标签设置为“正确”。

public partial class MainWindow : Window
{
    GameControl _GameControl = new GameControl();
    public string chosenMetal;
    int amtLeft = 8;


    public MainWindow()
    {
        InitializeComponent();
        chosenMetal = _GameControl.CycleThroughMetals();
        _GameControl.SetButtonContent(chosenMetal,ReagentAdded, transMetal, Opt1, Opt2, Opt3, Opt4, Opt5, Opt6, Opt7, Opt8);

        Opt1.Click += HandleButtonClicks;
        Opt2.Click += HandleButtonClicks;
        Opt3.Click += HandleButtonClicks;
        Opt4.Click += HandleButtonClicks;
        Opt5.Click += HandleButtonClicks;
        Opt6.Click += HandleButtonClicks;
        Opt7.Click += HandleButtonClicks;
        Opt8.Click += HandleButtonClicks;  
    }

    public void SwitchMetals()
    {
        chosenMetal = _GameControl.CycleThroughMetals();
        _GameControl.RefreshReagents(); //method which clears the 'alreadyUsedReagents' list
        _GameControl.SetButtonContent(chosenMetal, ReagentAdded, transMetal, Opt1, Opt2, Opt3, Opt4, Opt5, Opt6, Opt7, Opt8);
    }

    private void HandleButtonClicks(object sender, RoutedEventArgs e)
    {
        Button button = sender as Button;
        CheckForCorrect(button);

    }

    public void CheckForCorrect(Button button)
    {
        if ((string)button.Tag == "correct" && amtLeft != 0)
        {
            amtLeft -= 1;
            MessageBox.Show("You guessed correct!");
            _GameControl.SetButtonContent(chosenMetal, ReagentAdded, transMetal, Opt1, Opt2, Opt3, Opt4, Opt5, Opt6, Opt7, Opt8);
            button.IsEnabled = false;
        }

        if ((string)button.Tag != "correct")
        {
            MessageBox.Show("Oops!");
        }

        else if (amtLeft == 0)
          SwitchMetals();


    }
}

Then the above method is then used in the MainWindow to originally set the buttons and reagent text, and then the click method is used to see if the button clicked is the correct for the specific reagent that is set, and if it is then a new reagent is set. The problem I'm having is that it seems that I've completely messed up my code with the way I handle the looping and setting of the reagents, as when the reagent is displayed on the screen after each click sometimes the TextBlock appears blank and uses a previously used reagent. Any help would be seriously appreciated and I'm sorry in advance for including so much code sample but I'm seriously stumped on what to do from here.

然后在MainWindow中使用上述方法最初设置按钮和试剂文本,然后使用click方法查看点击的按钮是否对于所设置的特定试剂是正确的,如果它是新的试剂已设定。我遇到的问题是,我似乎完全弄乱了我的代码,我处理循环和设置试剂的方式,因为每次点击后在屏幕上显示试剂有时TextBlock显示为空白,使用以前使用的试剂。任何帮助都会得到认真的赞赏,我很抱歉提前包含了这么多代码示例,但是我真的很难过这里要做什么。

2 个解决方案

#1


3  

You could do this without any loop at all if instead of keeping track of alreadyUsedReagents you kept a list of unusedReagents.

你可以在没有任何循环的情况下做到这一点,如果不是跟踪已经存在的已使用的引用,你保留了一个unusedReagents列表。

RefreshReagents() then populates unusedReagents with the whole list.

然后,RefreshReagents()使用整个列表填充unusedReagents。

CycleThroughReagents() picks one at random, removes it from unusedReagents and returns it.

CycleThroughReagents()随机选择一个,将其从unusedReagents中删除并返回它。

Call RefreshReagents() whenever unusedReagents is empty.

每当unusedReagents为空时调用RefreshReagents()。

#2


4  

Just looking at the while loop, it seems that this piece:

只是看着while循环,似乎这件作品:

if (!alreadyUsedReagents.Contains(pickedReagent))
{
    alreadyUsedReagents.Add(pickedReagent);
    chosenReagent = pickedReagent;
    keepinLoop = false;
}

should be doing break. The way it is currently working does not prevent further iterations of the loop, as value that you set here in keepinloop can be overridden by the if/else below. So try replacing the line

应该休息一下。它当前工作的方式不会阻止循环的进一步迭代,因为你在keepinloop中设置的值可以被if / else下面覆盖。所以尝试更换线

keepinLoop = false;

with

break;

That should fix your loop.

那应该修复你的循环。

Update. Actually instead of using some made up flag to control your loop, it might be a better idea to use some real condition, like the number of used reagents for example:

更新。实际上,不是使用一些组合标志来控制你的循环,使用一些真实条件可能是一个更好的主意,例如使用的试剂数量:

while (alreadyUsedReagents.Count != 8)
{
    int r = rnd.Next(reagents.Count);
    string pickedReagent = (string)reagents[r];

    if (!alreadyUsedReagents.Contains(pickedReagent))
    {
        alreadyUsedReagents.Add(pickedReagent);
        chosenReagent = pickedReagent;
        break;
    }
}
RefreshReagents();

if (chosenReagent == null)
{
    // make sure to come up with some default
    // or your method will return null in some cases
}

#1


3  

You could do this without any loop at all if instead of keeping track of alreadyUsedReagents you kept a list of unusedReagents.

你可以在没有任何循环的情况下做到这一点,如果不是跟踪已经存在的已使用的引用,你保留了一个unusedReagents列表。

RefreshReagents() then populates unusedReagents with the whole list.

然后,RefreshReagents()使用整个列表填充unusedReagents。

CycleThroughReagents() picks one at random, removes it from unusedReagents and returns it.

CycleThroughReagents()随机选择一个,将其从unusedReagents中删除并返回它。

Call RefreshReagents() whenever unusedReagents is empty.

每当unusedReagents为空时调用RefreshReagents()。

#2


4  

Just looking at the while loop, it seems that this piece:

只是看着while循环,似乎这件作品:

if (!alreadyUsedReagents.Contains(pickedReagent))
{
    alreadyUsedReagents.Add(pickedReagent);
    chosenReagent = pickedReagent;
    keepinLoop = false;
}

should be doing break. The way it is currently working does not prevent further iterations of the loop, as value that you set here in keepinloop can be overridden by the if/else below. So try replacing the line

应该休息一下。它当前工作的方式不会阻止循环的进一步迭代,因为你在keepinloop中设置的值可以被if / else下面覆盖。所以尝试更换线

keepinLoop = false;

with

break;

That should fix your loop.

那应该修复你的循环。

Update. Actually instead of using some made up flag to control your loop, it might be a better idea to use some real condition, like the number of used reagents for example:

更新。实际上,不是使用一些组合标志来控制你的循环,使用一些真实条件可能是一个更好的主意,例如使用的试剂数量:

while (alreadyUsedReagents.Count != 8)
{
    int r = rnd.Next(reagents.Count);
    string pickedReagent = (string)reagents[r];

    if (!alreadyUsedReagents.Contains(pickedReagent))
    {
        alreadyUsedReagents.Add(pickedReagent);
        chosenReagent = pickedReagent;
        break;
    }
}
RefreshReagents();

if (chosenReagent == null)
{
    // make sure to come up with some default
    // or your method will return null in some cases
}