【问题标题】:C# Recursion error?C#递归错误?
【发布时间】:2016-01-13 23:27:27
【问题描述】:

我有一个很奇怪的问题。我正在使用递归方法,它应该在 6 个玩家(5 个机器人和 1 个玩家)中旋转,但是一旦它到达 bot 5(这是最后一个)它就不会这样做,它会跳过玩家的回合并继续到机器人 1 、机器人 2 、机器人 3 、机器人 4 、机器人 5 ,然后轮到玩家轮到它,换句话说,它跳过了玩家轮到的一个。我将在此处原始粘贴代码,如果有不清楚的地方在 cmets 中解释。

        private async Task Turns()
    {
        turns = ReturnTurns();
        GC.KeepAlive(Updates);
        if (!PFturn && Chips > 0)
        {
            if (Pturn)
            {
                call -= PreviousCalls.PreviousPlayerCall;
                pbTimer.Visible = true;
                pbTimer.Value = 1000;
                t = 60;
                up = int.MaxValue;
                Timer.Start();
                bRaise.Enabled = true;
                bCall.Enabled = true;
                bRaise.Enabled = true;
                bRaise.Enabled = true;
                bFold.Enabled = true;
                turnCount++;
                B1turn = true;
            }
        }
        if (PFturn || !Pturn || Chips <= 0)
        {
            if (pStatus.Text.Contains("Fold"))
            {
                B1turn = true;
            }
            if (!Pturn)
            {
                await Flip(0);
            }
            pbTimer.Visible = false;
            bRaise.Enabled = false;
            bCall.Enabled = false;
            bRaise.Enabled = false;
            bRaise.Enabled = false;
            bFold.Enabled = false;
            Timer.Stop();
            if (!B1Fturn && B1turn)
            {
                int previous = PreviousCalls.PreviousBot1Call;
                call -= PreviousCalls.PreviousBot1Call;
                if (Properties.Settings.Default.ThinkCheck)
                {
                    AutoCloseMsb.Show("Bot 1 Turn", "Turns", ThinkTime);
                }
                Combinations(2, 3, ref b1Type, ref b1Power, b1Status);
                Ai(2, 3, ref bot1Chips, ref B1turn, ref B1Fturn, b1Status, b1Power, b1Type, ref previous);
                await CheckTextBoxes();
                B1turn = false;
                turnCount++;
                B2turn = true;
                PreviousCalls.PreviousBot1Call = previous;
            }

            if (B1Fturn)
            {
                turns = ReturnTurns();
                B2turn = true;
            }
            await Flip(1);

            if (!B2Fturn && B2turn)
            {
                int previous = PreviousCalls.PreviousBot2Call;
                call -= PreviousCalls.PreviousBot2Call;
                Combinations(4, 5, ref b2Type, ref b2Power, b2Status);
                if (Properties.Settings.Default.ThinkCheck)
                {
                    AutoCloseMsb.Show("Bot 2 Turn", "Turns", ThinkTime);
                }
                Ai(4, 5, ref bot2Chips, ref B2turn, ref B2Fturn, b2Status, b2Power, b2Type, ref previous);
                await CheckTextBoxes();
                B2turn = false;
                turnCount++;
                B3turn = true;
                PreviousCalls.PreviousBot2Call = previous;
            }
            B3turn = true;
            if (B2Fturn)
            {
                turns = ReturnTurns();
                B3turn = true;
            }
            await Flip(2);

            if (!B3Fturn && B3turn)
            {
                int previous = PreviousCalls.PreviousBot3Call;
                call -= PreviousCalls.PreviousBot3Call;
                Combinations(6, 7, ref b3Type, ref b3Power, b3Status);
                if (Properties.Settings.Default.ThinkCheck)
                {
                    AutoCloseMsb.Show("Bot 3 Turn", "Turns", ThinkTime);
                }
                Ai(6, 7, ref bot3Chips, ref B3turn, ref B3Fturn, b3Status, b3Power, b3Type, ref previous);
                await CheckTextBoxes();
                B3turn = false;
                turnCount++;
                B4turn = true;
                PreviousCalls.PreviousBot3Call = previous;
            }

            if (B3Fturn)
            {
                turns = ReturnTurns();
                B4turn = true;
            }
            await Flip(3);

            if (!B4Fturn && B4turn)
            {
                int previous = PreviousCalls.PreviousBot4Call;
                call -= PreviousCalls.PreviousBot4Call;
                Combinations(8, 9, ref b4Type, ref b4Power, b4Status);
                if (Properties.Settings.Default.ThinkCheck)
                {
                    AutoCloseMsb.Show("Bot 4 Turn", "Turns", ThinkTime);
                }
                Ai(8, 9, ref bot4Chips, ref B4turn, ref B4Fturn, b4Status, b4Power, b4Type, ref previous);
                await CheckTextBoxes();
                B4turn = false;
                turnCount++;
                B5turn = true;
                PreviousCalls.PreviousBot4Call = previous;
            }
            if (B4Fturn)
            {
                turns = ReturnTurns();
                B5turn = true;
            }
            await Flip(4);

            if (!B5Fturn && B5turn)
            {
                int previous = PreviousCalls.PreviousBot5Call;
                call -= PreviousCalls.PreviousBot5Call;
                Combinations(10, 11, ref b5Type, ref b5Power, b5Status);
                if (Properties.Settings.Default.ThinkCheck)
                {
                    AutoCloseMsb.Show("Bot 5 Turn", "Turns", ThinkTime);
                }
                Ai(10, 11, ref bot5Chips, ref B5turn, ref B5Fturn, b5Status, b5Power, b5Type, ref previous);
                await CheckTextBoxes();
                B5turn = false;
                turnCount++;
                Pturn = true;
                PreviousCalls.PreviousBot5Call = previous;
            }
            if (B5Fturn)
            {
                turns = ReturnTurns();
                Pturn = true;
            }
            await Flip(5);
            if (!restart)
            {
                await Turns();
            }
        }
    }

【问题讨论】:

  • 这有意义吗?如何将递归用于“循环” - 你肯定会在某个时候溢出堆栈......?你不想要一个状态机(或者只是一个循环?)
  • 您应该努力制作minimal reproducible example 在此处发帖。这段代码充满了看起来对解决具体问题无关紧要的信息,制作mvce的过程甚至可以帮助你自己找出问题所在。
  • 我在await Turns() 行放置了一个断点,一旦到达它,它会向下移动 3 行,然后返回到 if (PFturn || !Pturn || Chips
  • 我需要一些能在 6 名玩家之间循环直到完成某些声明的东西
  • 怎么样...一个循环?不要试图变得聪明或任何东西,但你只是说“我需要一些可以循环的东西”。一个非常简单的状态机可以工作(只需保持当前状态“player,bot1,bot2,bot3,bot4..etc”)并采取相应的行动。它看起来像纸牌游戏,纸牌游戏规则很容易编写,因为它们通常非常有限

标签: c# recursion methods


【解决方案1】:

听起来您想以更有状态的方式处理此问题。一个简化的例子可能是:

// Player interface - the game engine will pass game state to the TakeTurn method
// The target of the TakeTurn call can mutate the game state
public interface IPlayer {

    void TakeTurn(GameState state);

    // Some info that other bots/players might need to look at
    int Chips { get; } 

    // also add other useful bits of info that other game components may need
    int SomeOtherUsefulInfo { get; }
}

public class GameState {

    // Is the game over?
    bool GameOver;

    // State information the bots/player will use to make decisions
    int ChipsInPot;

    // Reference to previous player which could help with AI decisions etc
    IPlayer previousPlayer;          
}

// Both Bot and Human class implement IPlayer which means they can both
// be handled by the same game pipeline step but have radically different
// implementations - such as AI or manual interaction
public class Bot : IPlayer {
    // AI here making sure to implement the IPlayer interface
}

public class Human : IPlayer {
    // Human player handling code but with same interface
}

// Game engine simply runs a loop to keep passing turns
public class GameEngine {
    GameState _state;
    List<IPlayer> _players;

    public GameEngine() {
       _players = new List<IPlayer>();
       _players.Add(new Bot("Fred"));
       _players.Add(new Bot("James"));
       _players.Add(new Bot("Arnold"));
       _players.Add(new Human("Jake")); 
    }

    public void GameLoop() {

        while(!_state.GameOver) {
          foreach(var player in _players) {
              player.TakeTurn(_state); // etc - keep mutating state and looping until the game ends

              // Add more complexity here :)
          }
        }
    }
}

【讨论】:

  • 这主要是伪代码,因为我在这里和那里错过了一些publics,但希望它能让您了解另一种方法 - 啊忘了将任何 IPlayer 实例添加到列表中,更新:)
  • 哦 1 个问题,我在 10 分钟前开始审查它,我不太确定如何在 List&lt;IPlayer&gt; 中添加新对象,我应该将我的机器人逻辑方法以及其他检查方法放在哪里其他一些东西
  • 您需要将IPlayer 接口实例添加到列表中 - 机器人逻辑的方法可以去任何它需要去的地方(例如 AI 助手类或其他东西),但肯定是主要的起点该逻辑来自Bot 类中的TakeTurn 方法。游戏逻辑可以放在GameEngine 类或更多辅助类中。由你决定如何布局它,但使用接口主游戏循环要简单得多(如果你愿意,你可以使用 if 语句,但这几乎正是接口的用途 - 具有不同实现的通用合同)
猜你喜欢
  • 1970-01-01
  • 2017-06-05
  • 2018-03-30
  • 2016-06-05
  • 2012-06-08
  • 2021-08-15
  • 1970-01-01
  • 1970-01-01
  • 2016-11-11
相关资源
最近更新 更多