Рекурсивная система меню

#c# #recursion #xna

#c# #рекурсия #xna

Вопрос:

Я пытаюсь закодировать рекурсивный класс меню, с возможностью навигации с помощью клавиш со стрелками, который почти завершен, просто у него, похоже, есть небольшие проблемы в ситуациях, после некоторого увеличения / уменьшения (перенос меню) он становится нестабильным и, как ни странно, начинает переходить к подпунктам дажекогда эта группа будет закрыта.

Вот мои функции ввода:

     {
        if (Keyboard.Pressed(Keys.Up))
        {
            if (Index >= 0)
            {
                if (!GoUp(Groups[Index]))
                {
                    Index--; if (Index == -1) Index = (Groups.Count - 1);
                    if (Groups[Index].Open) Groups[Index].Index = ((Groups[Index].Groups.Count   Groups[Index].Items.Count) - 1);
                }
            }
        }
        if (Keyboard.Pressed(Keys.Down))
        {
            if (Index >= 0)
            {
                if (!GoDown(Groups[Index])) Index  ;
                if (Index >= Groups.Count) Index = 0;
            }
        }
    }
    internal bool GoUp(Group group)
    {
        if (!group.Open) return false;
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count) amp;amp; group.Groups[group.Index].Open) if (GoUp(group.Groups[group.Index])) return true;
        group.Index--;
        if (group.Index == -1) return true;
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count) amp;amp; group.Groups[group.Index].Open) group.Groups[group.Index].Index = ((group.Groups[group.Index].Groups.Count   group.Groups[group.Index].Items.Count) - 1);
        return (group.Index >= 0);
    }
    internal bool GoDown(Group group)
    {
        if (!group.Open) return false;
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count) amp;amp; group.Groups[group.Index].Open) if (GoDown(group.Groups[group.Index])) return true;
        group.Index  ;
        if (group.Index >= (group.Groups.Count   group.Items.Count)) { group.Index = -1; return false; }
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count)) group.Groups[group.Index].Index = -1;
        return true;
    }
  

Он отлично отображает меню, но ради вас, вот мой чертежный код:

     public void Draw(Batch batch, Vector2 position, SpriteFont font, int width)
    {
        VisibleItems = Groups.Count;
        for (var i = 0; i < Groups.Count; i  ) DrawGroup(Groups[i], null, batch, ref position, font);
    }
    internal void DrawGroup(Group group, Group parent, Batch batch, ref Vector2 position, SpriteFont font)
    {
        const float textScale = .15f;
        batch.DrawString(group.Name, font, position, (((((parent == null) amp;amp; (group == Groups[Index])) || ((parent != null) amp;amp;
            (parent.Index >= 0) amp;amp; (parent.Groups.Count > parent.Index) amp;amp; (group == parent.Groups[parent.Index]))) amp;amp; (group.Index == -1)) ? GroupSelectedColor : GroupColor), new Vector2(textScale));
        position.Y  = (font.MeasureString(group.Name).Y * textScale);
        if (group.Open)
        {
            var x1 = position.X;
            if (group.Groups.Count > 0)
            {
                position.X  = 10;
                var x2 = position.X;
                for (var i = 0; i < group.Groups.Count; i  )
                {
                    DrawGroup(group.Groups[i], group, batch, ref position, font);
                    position.X = x2;
                }
                position.X -= 10;
            }
            if (group.Items.Count > 0)
            {
                position.X  = 10;
                for (var i = 0; i < group.Items.Count; i  )
                {
                    batch.DrawString(group.Items[i].Name, font, position, (((group.Index >= group.Groups.Count) amp;amp; (i == (group.Index - group.Groups.Count))) ? ItemSelectedColor : ItemColor), new Vector2(textScale));
                    position.Y  = (font.MeasureString(group.Items[i].Name).Y*textScale);
                }
                position.X -= 10;
            }
            position.X = x1;
        }
    }
  

Ответ №1:

Неважно, проблема заключалась исключительно в том, что в функции GoUp отсутствовала простая строка

 else if (group.Index < -1) group.Index = -1;
  

новая функция GoUp:

     internal bool GoUp(Group group)
    {
        if (!group.Open) return false;
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count) amp;amp; group.Groups[group.Index].Open) if (GoUp(group.Groups[group.Index])) return true;
        group.Index--;
        if (group.Index == -1) return true;
        else if (group.Index < -1) group.Index = -1;
        if ((group.Index >= 0) amp;amp; (group.Index < group.Groups.Count) amp;amp; group.Groups[group.Index].Open) group.Groups[group.Index].Index = ((group.Groups[group.Index].Groups.Count   group.Groups[group.Index].Items.Count) - 1);
        return (group.Index >= 0);
    }