繁体   English   中英

C#Windows窗体应用程序函数循环

[英]C# Windows Form Application Function Loop

我必须将我在控制台应用程序中创建的RPG游戏转换为用于编程简介类的Windows窗体应用程序。 一切都按预期进行,但后来我不得不改变战斗系统。 以下是调用战斗功能和战斗功能的按钮点击事件:

private void btStoryProgression_Click(object sender, EventArgs e)
{
     {...}

     else if (flagControl == 20)
        {
             Enemy enemy = new Enemy("Hellhound", "Oblivion Cave", 1);

             if (combat(player, enemy) == true)
             {
                 Lines.Text += "You won!\n";
                 player.itemList.Add(new Item("Fruit", 22));
             }
             else
             {
                 Lines.Text = "YOU DIED.";
                 Lines.Text += "GAME OVER.";
                 return;
             }
        }
}


bool combat(Player player, Enemy enemy)
{
    Lines.Text = enemy.getName() + " appeared!\n";
    int damage;
    bool battle = true;
    int battleChoice = 0, itemChoice = -1;

    turns = 0;
    Lines.Text += "What are you going to do?";
    buttonVisibility();
    buttonChoices("Attack", "Item");

    while (battle)
    {
         if (player.getSpeed() > enemy.getSpeed())
         {
            //Player turn
            if (battleChoice == 1)
            {
                Lines.Text = player.getName() + " attacked!\n";

                if (player.getAccuracy() < 100)
                {
                    Random rnd = new Random();
                    if (rnd.Next(1, 100) > player.getAccuracy())
                    {
                        Lines.Text += "The attack missed!\n";
                        goto enemyturn;
                    }
                }


                damage = player.getAtk() - enemy.getDef();
                if (damage < 0)
                    damage = 0;
                enemy.setHP(enemy.getHP() - damage);
                if (enemy.getHP() < 0)
                    enemy.setHP(0);

                    Lines.Text += "You dealt " + damage + " damage to " + enemy.getName();
                    Lines.Text += "Enemy HP is now " + enemy.getHP();

                    if (enemy.getHP() == 0)
                        return true;
                }
                else if (battleChoice == 2)
                {
                    Lines.Text += "Your items: ";
                    foreach (Item item in player.itemList)
                    {
                        Lines.Text += item.getName();
                    }
                    Lines.Text += "Choose a number based on the order the items appeared";
                    try
                    {
                        do
                        {
                            itemChoice = Convert.ToInt32(Console.ReadLine());
                            itemChoice--;

                        } while (itemChoice > player.itemList.Count());
                    }
                    catch (FormatException)
                    {
                        Console.WriteLine("SOMETHING WRONG!!");
                    }

                    Lines.Text += "Player HP was: " + player.getHP();
                    player.setHP(player.getHP() + player.itemList[itemChoice].getRecoverQtd());
                    Lines.Text += "Player HP is now: " + player.getHP();
                    player.itemList.RemoveAt(itemChoice);

                }

                enemyturn:
                //Enemy turn
                if (battleChoice != 0)
                {
                    Lines.Text += enemy.getName() + " attacked!\n";

                    damage = enemy.getAtk() - player.getDef();
                    if (damage < 0)
                        damage = 0;
                    player.setHP(player.getHP() - damage);
                    if (player.getHP() < 0)
                        player.setHP(0);

                    Lines.Text += enemy.getName() + " dealt " + damage + " damage to " + player.getName();
                    Lines.Text += player.getName() + " HP is now " + player.getHP();
                }

                if (player.getHP() == 0)
                    return false;

                turns++;
            }
            else
            {
                enemyturn:
                //Enemy turn
                if (battleChoice != 0)
                {
                    Lines.Text += enemy.getName() + " attacked!\n";

                    damage = enemy.getAtk() - player.getDef();
                    if (damage < 0)
                        damage = 0;
                    player.setHP(player.getHP() - damage);
                    if (player.getHP() < 0)
                        player.setHP(0);

                    Lines.Text += enemy.getName() + " dealt " + damage + " damage to " + player.getName();
                    Lines.Text += player.getName() + " HP is now " + player.getHP();

                    if (player.getHP() == 0)
                        return false;
                }
                //Player turn
                if (battleChoice == 1)
                {
                    Lines.Text += player.getName() + " attacked!\n";

                    if (player.getAccuracy() < 100)
                    {
                        Random rnd = new Random();
                        if (rnd.Next(1, 100) > player.getAccuracy())
                        {
                            Lines.Text += "The attack missed!";
                            goto enemyturn;
                        }
                    }

                    damage = player.getAtk() - enemy.getDef();
                    if (damage < 0)
                        damage = 0;
                    enemy.setHP(enemy.getHP() - damage);
                    if (enemy.getHP() < 0)
                        enemy.setHP(0);

                    Lines.Text += "You dealt " + damage + " damage to " + enemy.getName();
                    Lines.Text += "Enemy HP is now " + enemy.getHP();

                    if (enemy.getHP() == 0)
                        return true;
                }

                else if (battleChoice == 2)
                {
                    Lines.Text += "Your items: ";
                    for (int i = 0; i < player.itemList.Count; ++i)
                    {
                        Lines.Text += player.itemList[i].getName();
                    }
                    Lines.Text += "Choose a number based on the order the items appeared";

                }
                turns++;
            }
            return true;

        }

基本上,当我按下按钮并且调用战斗时,整个功能被跳过,直到找到一些松散的“其他”,或者,如果我限制每次比较,程序就会冻结。 我做了一些搜索,我看到人们建议使用Delegate或BackgroundWorker,但我仍然对使用它们感到困惑。 这个链接是我发现的最接近我的问题,但它也无法帮助我(也许是因为我是新手......)。

你能帮我吗? 先感谢您 :)

你的第一个问题是你的计算战斗的方法正在GUI线程上运行。 由于它很忙,它实际上无法真正完成更新GUI和GUI冻结的工作。 您永远不应该在GUI线程上执行长时间运行的任务。

你可以使用async和await来修改它,方法是创建一个新的异步方法,然后只需在按钮内运行它:

private async Task RunCombat()
{
    Enemy enemy = new Enemy("Hellhound", "Oblivion Cave", 1);
    //this next line will run async now and will not block your gui thread.
    bool combatResult = await Task.Run(() => combat(player, enemy));

     if (combatResult)
     {
         Lines.Text += "You won!\n";
         player.itemList.Add(new Item("Fruit", 22));
     }
     else
     {
         Lines.Text = "YOU DIED.";
         Lines.Text += "GAME OVER.";
         return;
     }

然后只需在按钮单击中调用此方法,而不是您已有的方法。 一旦你这样做,你将无法再在你的战斗方法中使用Lines.Text += ,因为它将在不同的线程上运行。

我将在表单类声明的上方创建一个名为LineAppenderDelegate的委托:

public delegate void LineAppenderDelegate(string lineToAdd);

然后创建一个AppendLine方法:

private void AppendLine(string lineToAdd)
{
    if(InvokeRequired) //if we are not on the gui thread
    {
        //re-call the same method on the gui thread
        LineAppenderDelegate d = new LineAppenderDelegate(AppendLine);
        Invoke(d, new object[]{lineToAdd});
    }
    else //we are on the gui thread and can just do the work
    {
        Lines.Text += lineToAdd;
    }
}

并使用它来添加行。 这个方法基本上检查你是否在正确的线程上与gui进行交互。 如果你不是,它会回想起gui线程上的方法。 如果你是,它只是做它的工作。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM