简体   繁体   中英

Xamarin.Forms Random List

I am running into a problem when trying to pull random List items, it keeps getting an "Out of Range Exception" rather than starting back at the begining. How do I get it to keep pulling randomly from the list?

        var rand = new Random();
        var next = rand.Next(1);

        Device.StartTimer(TimeSpan.FromSeconds(1), () =>
        {
            _countSeconds--;

            if (_countSeconds == 0)
            {
                count--; //trying to use count instead of index to go past the 4 list items
                next++;
                _countSeconds = 3;

                if (count < 6 && count >= 0)
                {
                    BindingContext = Footwork2[next];                       
                }
                else
                {
                    return false;
                }
            };

            CountLabel.Text = _countSeconds.ToString();

            return true;
        });

Your code would be more comprehensible if you implemented the logic in its own class. From what I understood, I tried to extract the logic:

class RandomFootwork
{
    Random _random = new Random();
    Footwork[] _footwork = // ... Whatever this is
    int _numberOfRounds = 10; // Parameterize this via constructor if you like

    int _numberOfFootworkDrawn = 0;
    
    public bool IsFinished => _numberOfFootworkDrawn == _numberOfRounds;

    public Footwork Next()
    {
        int index = _random.Next(_footwork.Length);
        var result = _footwork[index]; // Should work unless _footwork has Length 0
        _numberOfFootworkDrawn++;
        return result;
    }
}

This would simplify your UI-Code to

var randomFootwork = new RandomFootwork();

_countSeconds = SECONDS_BETWEEN_DRAWING;
Device.StartTimer(TimeSpan.FromSeconds(1), () =>
{
    _countSeconds--;

    if (_countSeconds == 0)
    {
        BindingContext = randomFootwork.Next();
        _countSeconds = SECONDS_BETWEEN_DRAWING;
    
        if(randomFootwork.IsFinished)
        {
            return false;
        }
    };

    CountLabel.Text = _countSeconds.ToString();
    return true;
});

Theoretically you could introduce a class abstracting the timer-logic, too, providing a callback to update the counter and one to draw footwork. And I would recommend a Viewmodel to integrate both.

public class FootworkGameViewmodel : INotifyPropertyChanged
{
    // Omitted the Counter and Footwork properties, as well as the implementation
    // of INotifyPropertyChanged, but I hope you get the idea.

    // Starts the game, should maybe invoked from a command
    public void Start()
    {
        var randomFootwork = new RandomFootwork();

        // The first callback of the FootworkTimer class just updates the counter
        // the second one draws whatever is drawn and updates the property
        // Footwork. Your view can bind to the properties to update.
        var footworkTimer = new FootworkTimer(counter => this.Counter = counter, 
                                              () => {
                                                        this.Footwork = randomFootwork.Next;
                                                        // Return false to quit the timer
                                                        return !randomFootwork.IsFinished;
                                                    });
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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