c# array looping with itself - c#

Why I'm doing this:
So I'm trying to make an application for a game called clash royale, after winning the games there you get a "random" chest, which is actually not random... When you create your account you get a digit assigned to you from 0 to 239, and after that it follows a pattern for the chest drops. The applciation I'm making would take a user's entries and compare it to the pattern, thus being able to predict how soon the next chests of a higher quality would drop.
The help I need with the code:
Is it possible to make an array kind of... loop within itself.. So for example when going through the array in a loop, if "i" is 239, then adding +1 would take it back to the beginning, or #0 (239 not necessarily being the limit).
The class (and it's container that I want to loop):
class Chest
{
public int ID { get; set; }
public string Type { get; set; }
public Chest()
{
}
public Chest(int id, string type)
{
ID = id;
Type = type;
}
}
class ChestContainer
{
private Chest[] ChestList = new Chest[240];
public int Count { get; set; }
public ChestContainer(int size)
{
ChestList = new Chest[size];
}
public void Add(Chest chest)
{
ChestList[Count++] = chest;
}
public Chest Get(int index)
{
return ChestList[index];
}
}
Also wouldn't mind any tips to improve my class / container class, at the moment this is what I've been doing for pretty much my entire "career" as this is what we were thought in uni (minus the string override for the class).

You could use Modulo % in order to get a loop kind of thing.
If you replace the Container.Add method with the one below, the index will be "reset" (for lack of better words).
public void Add(Chest chest)
{
ChestList[Count++%(ChestList.Length)] = chest;
}
After updating the method, if you want an example, you can try the code below:
var container = new ChestContainer(240);
for (int i = 0; i < 1000; i++)
container.Add(new Chest(i, $"{i}"));
Edit In order to have the Get method working as well, modifying it as mentioned below will ensure your container works as expected:
public Chest Get(int index)
{
return ChestList[index%(ChestList.Length)];
}
To test it out, you can use the code below:
var container = new ChestContainer(240);
for (int i = 0; i < 1000; i++)
{
container.Add(new Chest(i, $"{i}"));
var value = container.Get(i);
}

You can overload the [] operator to define it's behaviour.
Something like this:
public static Chest operator [] (int index) {
return ChestList[index%240];
}

public Chest Get(int index)
{
return ChestList[index%240]; //put your limit here
}
How it works: % is the modulo operator.
It returns the remainder of a devision.
Example:
5/2 = 2, remaining 1
=> 5%2 = 1
In your case, when numbers higher than 239 are entered, with modulo it just wraps around.

Related

Best way to write multiple constructor overloads in C#

I am learning C# and made a simple "Player" class. But I struggle having multiple overload.
Here's my best solution but I feel like it could be done simpler/better.
class Player : Entity
{
public Player() {
Name = "Player";
XP = 0;
LVL = 1;
XPToLvlUp = 10;
XpRank = 10;
}
public Player(string name) : this() {
Name = name;
}
public Player(string name, int _Hp, int _Mp) : this(name) {
HP = _Hp;
MP = _Mp;
}
public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl) : this(name, _Hp, _Mp) {
XP = _Xp;
LVL = _Lvl;
}
public Player(string name, int _Hp, int _Mp, int _Xp, int _Lvl, int XpByRank) : this(name, _Hp, _Mp, _Xp, _Lvl) {
XpRank = XpByRank;
}
//deleted code for better reading
private int XPToLvlUp;
private int XpRank;
public int XP;
public int LVL;
public string Name;
}
Is it good and if not please tell me why.
Thanks for your responses!
I think it's fine as is. One question to ask yourself: Are each of those methods actually likely to be called?
One option is to just let the programmer set those values after they've instantiated the class:
var myPlayer = new Player();
myPlayer.XP = 5;
However, there are situations where you really want all the info up front, so that may not be suitable.
Another option could be an options class that is passed to the ctor:
public class PlayerSettings
{
public Name = "Player";
public XP = 0;
public LVL = 1;
public XPToLvlUp = 10;
public XpRank = 10;
}
Then your ctors looks like this:
public Player() : this(new PlayerSettings())
{
}
public Player(PlayerSettings settings)
{
//Fill in appropriate variables here
}
That option would be called in this way:
var playerSettings = new PlayerSettings() { XP = 5 };
var myPlayer = new Player(playerSettings());
In the end, I'm not sure one is "better" than the other, it largely depends on your needs.
Your class is almost good and acceptable.
Short story: use Properties.
Long story:
First of all make or follow the naming rules, it will make your code more friendly to read. It's up to you, just a suggestion. For complex names consisting of multiple words you may use CamelCasedNames. And avoid shorten names for all types of data where it maybe useful. For example you may expand Lvl to Level but Xp to Experience will look as something odd. It's up to you too.
string name; // local Variable, first character lower cased
private string _name; // private Field, first character is lower cased with leading "_"
public string Name { get; set; } // public Property, first character is upper cased
I'll show you alternatives to overriden constructors and will follow the naming rules.
1) Default values for constructor (with a part of your class to keep it simple)
class Player
{
public Player(string name = "Player", int xp = 0, int level = 1)
{
Name = name;
Xp = xp;
Level = level;
}
// Properties instead of Fields
public int Xp { get; private set; } // restrict modification of the property outside of a class but reading is available
public int Level { get; private set; }
public string Name { get; set; }
}
2) Properties without constructor with default values
First Property purpose is restrict access to data to keep internal object data consistent. Even you make mistakes in the code. Good way to avoid some bugs.
Second property purpose is executing code while you're getting or setting one. For example, making properties dependent on each other to store less and only unique data.
class Player
{
public int Xp { get; private set; } = 0;
public int Level { get; private set; } = 1;
public string Name { get; set; } = "Player";
}
Usage
Player player = new Player() { Name = "KillerPWNZ", Level = 100, Xp = 999999 };
Bonus: Another Property feature
You can execute any code in get or set clause.
Let's assume that each next player's level require doubled amount of xp from previous but 2nd level requre 100 XP. And you decided to invoice to the 1st leveled player 1000 XP. Obviously you'll need to bump the Level few times. Assuming that Xp contains relative to Level value.
The invoice
player.Xp += 1000;
The Property with code
private int _xp = 0;
public int Level { get; private set; } = 1;
public int Xp
{
get => _xp; // same as: get { return _xp; }
set
{
_xp = value; // here value is keyword containing data you want to set
while (_xp >= GetXpPerLevel(Level))
{
_xp -= GetXpPerLevel(Level);
Level++;
}
while (_xp < 0 && Level > 1)
{
_xp += GetXpPerLevel(Level - 1);
Level--;
}
}
}
// helper method
private int GetXpPerLevel(int level)
{
if (level < 1) return 0;
// int result = 100;
// for (int i = 1; i < level; i++) result *= 2;
// return result;
// or the same with some binary shift magic :)
return 100 << (level - 1);
}

How to clear a list of type class

i have a List which get's and set's data from/to my class "Type" after a specific condition is fulfilled i want to clear all the variables value's that have been gathered here's my code
List<Type> Win = new List<Type>();
void Check(int a)
{
if (a>10)
{
Win.Add(new Type() { Power = 10 + a * 100, Current = 1 });
}
if(a<10)
{
Win.Add(new Type() { Power = 10 + a * 100, Current = 1 });
}
}
My class:
public class Type
{
public int Power { get; set; }
public int Current { get; set; }
}
And like this it will always enter the 2 if's at least once because I'm giving him a parameter "a" and a will change let's say 5 times and it will get a lot of different values.How can i clear the entire "Type.Power" and "Type.Current" variables or just clear the entire list "Win" ?
To empty the entire list, you can use .Clear().
Win.Clear();
To reset all instances of `Type.Power' and 'Type.Current' per instance in your list, you would need to iterate the list and update the members to their default value 0.
Win.ForEach(x =>
{
x.Power = 0;
x.Current = 0;
});

Variable not returning actual values

I want correctly return some variables (arrays)
kazkas.Ads[n]; (n = how many ads are)
kazkas.Ads[n].id;
kazkas.Ads[n].Days[m].Stats.Clicks; // every day have his own clicks
kazkas.Ads[n].Days[m].Stats.Impresons; // every day have his own impresions
from this method and use these variables in other class.
public static void GetAdsStats(string Ticket, DateTime start, DateTime end, int CamId)
{
var client = new CampaignStatsServiceClient();
var id = new CampaignIdFilter();
id.CampaignId = CamId;
var statsdata = new GetAdStatsData();
var kazkas = new Campaign();
kazkas = client.GetAdStats(Ticket, new GetAdStatsData
{
IdFilter = id,
StartDate = start,
EndDate = end
});
long AllClicks = 0;
long AllImpresions = 0;
int reklamos = kazkas.Ads.Length;
long[] statistikaClikai = new long[reklamos];
long[] statistikaImpresions = new long[reklamos];
for (int i = 0; i < reklamos; i++)
{
int dienos = kazkas.Ads[i].Days.Length;
for (int lop = 0; lop < dienos; lop++)
{
AllClicks = AllClicks + kazkas.Ads[i].Days[lop].Stats.Clicks;
AllImpresions = AllImpresions + kazkas.Ads[i].Days[lop].Stats.Impressions;
}
statistikaClikai[i] = AllClicks;
statistikaImpresions[i] = AllImpresions;
}
}
I know that void type can't return anything, but this how I know that my method works ( from debugging). Like you see I was trying do that with for loop. Here i have 9 Ads and every ad have one day.
Like I says I want return every Ads id[in array], and every days.stats.impresions and days.stats.click
how can I do that ? Ore how return more variables/arrays from method to other class, I am using webservises, so i cant use database ore something like that.
As can be seen by the downvotes of the question, you need to design the return value and then code against it.
Your query almost does it (now):
kazkas.Ads[n]; (n = how many ads are)
kazkas.Ads[n].id;
kazkas.Ads[n].Days[m].Stats.Clicks; // every day have his own clicks
kazkas.Ads[n].Days[m].Stats.Impressions; // every day have his own impressions
Your existing code show this should be expanded to include:
kazkas.Ads[n].Total.Clicks;
kazkas.Ads[n].Total.Impressions;
So now you're ready to design. First you want a Stat Class that just contains CLicks and Impressions:
public class Stat
{
public long Impressions { get; set; }
public long Clicks { get; set; }
}
An optimisation here may be to use a struct, but I won't go into that.
As you currently have defined it each Day has just a Stats property:
public class DayStat
{
public Stat Stats { get; set; }
}
Now finally we can define the top level AdStat:
public class AdStat
{
public int id { get; set; }
public DayStat Day[];
public Stat Total { get; set; }
}
Etc... There's further issues here, such as ensuring arrays are created and Stat instances are never null (which is why making some of these classes structs is an option). But I'm really a VB programmer so I'll stop here before I get caught typing crap into the SO IDE :-)
Create a class or struct with members you need
public class Stat
{
public int Id { get; set; }
public long Clicks { get; set; }
...
}
Change the signature of your method from void GetAdsStats to IEnumberable<Stat> GetAdsStats and either return a collection of stats or use yield keyword to return the stat object.
Also if you do not want your method to return anything (return type void) do not use a name starting with Get.
Example:
public static IEnumerable<Stat> GetAdsStats(...)
{
...
var statList = new List<Stat>();
for (int i = 0; i < reklamos; i++)
{
var stat = new Stat();
statList.Add(stat);
int dienos = kazkas.Ads[i].Days.Length;
for (int lop = 0; lop < dienos; lop++)
{
AllClicks = AllClicks + kazkas.Ads[i].Days[lop].Stats.Clicks;
AllImpresions = AllImpresions + kazkas.Ads[i].Days[lop].Stats.Impressions;
}
stat.Clicks = AllClicks;
stat.Impression = AllImpresions;
}
return statList;
}
Change your void to the type you want to return, say Campaign, and return the appropriate variable. The variables you define in your method, only live in your method and are not accessible from another method or class.

Understanding classes and using Random [closed]

As it currently stands, this question is not a good fit for our Q&A format. We expect answers to be supported by facts, references, or expertise, but this question will likely solicit debate, arguments, polling, or extended discussion. If you feel that this question can be improved and possibly reopened, visit the help center for guidance.
Closed 9 years ago.
I've written the following class to return a random number like rolling a dice:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace GameTest
{
class Dice
{
public int publicMinNum
{
get { return _minNum; }
set { _minNum = value; }
}
public int publicMaxNum
{
get { return _maxNum; }
set { _maxNum = value; }
}
static int _minNum;
static int _maxNum;
static Random diceRoll = new Random();
public int rolled = diceRoll.Next(_minNum, _maxNum);
}
}
This class is called a couple of times in my form:
private void btnPushMe_Click(object sender, EventArgs e)
{
Dice myRoll = new Dice();
myRoll.publicMinNum = 1;
myRoll.publicMaxNum = 7;
lblMain.Text = myRoll.rolled.ToString();
Dice mySecondRoll = new Dice();
mySecondRoll.publicMinNum = 1;
mySecondRoll.publicMaxNum = 13;
lblMain2.Text = mySecondRoll.rolled.ToString();
}
As you can see, I call the class twice as myRoll and mySecondRoll. I thought by doing this it would create separate instances of the class and output two separate numbers (one between 1 and 6, the other 1 and 12)
The problems I am having are:
1) the first number out is always 0.
2) the two instances of the class interfere with one another, ie. the number that should be between 1 and 6 just isn't.
I'm wondering, not just how to fix the code, but would also like an explanation of what is happening here and why, thanks.
The problem is that you are declaring the fields in the Dice class as static. This means that there will only be one instance of that variable, which will be shared across all instances of the class within the application.
The following line:
public int rolled = diceRoll.Next(_minNum, _maxNum);
... gets run the moment you create your new Dice(), which means that you haven't yet initialized your _minNum and _maxNum values yet: that's why it's giving you a 0. You could turn this into a property, so the code would wait to be run until you asked for it:
public int Rolled { get { return diceRoll.Next(_minNum, _maxNum); } }
... but typically properties are not expected to change just by asking for their value. This sort of code tends to create so-called Heisenbugs, which are very difficult to track down because the system's behavior changes simply by trying to observe it.
So here's one way you might re-write your class, using a Roll() method to actually perform the roll, and a property that allows code to keep checking on the last roll's value whenever necessary:
public class Die
{
// Using a constructor makes it obvious that you expect this
// class to be initialized with both minimum and maximum values.
public Die(int minNum, int maxNum)
{
// You may want to add error-checking here, to throw an exception
// in the event that minNum and maxNum values are incorrect.
// Initialize the values.
MinNum = minNum;
MaxNum = maxNum;
// Dice never start out with "no" value, right?
Roll();
}
// These will presumably only be set by the constructor, but people can
// check to see what the min and max are at any time.
public int MinNum { get; private set; }
public int MaxNum { get; private set; }
// Keeps track of the most recent roll value.
private int _lastRoll;
// Creates a new _lastRoll value, and returns it.
public int Roll() {
_lastRoll = diceRoll.Next(MinNum, MaxNum);
return _lastRoll;
}
// Returns the result of the last roll, without rolling again.
public int LastRoll {get {return _lastRoll;}}
// This Random object will be reused by all instances, which helps
// make results of multiple dice somewhat less random.
private static readonly Random diceRoll = new Random();
}
(note that "die" is the singular form of "dice"). Usage:
private void btnPushMe_Click(object sender, EventArgs e)
{
Die myRoll = new Die(1, 7);
lblMain.Text = myRoll.Roll().ToString();
Die myRoll2 = new Die(1, 13);
lblMain2.Text = mySecondRoll.Roll().ToString();
}
Question Two is already aswered: because the variables are static:
static int _minNum;
static int _maxNum;
Question One on the other hand isnt answered yet, so here goes:
public int rolled = diceRoll.Next(_minNum, _maxNum);
this is not some dynamic call. This is a field initialisation, and will be set even before the constructor. You can check this out by debugging through the dice the first time.
at that point both _minNum and _maxNum are still 0, so rolled will be set to 0
this can be fixed by turning rolled into a property too:
public int rolled
{
get { return diceRoll.Next(_minNum, _maxNum); }
}
At the moment _minNum and _maxNum are getting set the first time because they are static, therefor when you create the second dice, they are already set.
Edit, since a recommendation was asked, this is how I'd create it:
The dice
class Dice
{
private static Random diceRoll = new Random();
private int _min;
private int _max;
public int Rolled { get; private set; }
public Dice(int min, int max)
{
_min = min;
_max = max;
// initializes the dice
Rolled = diceRoll.Next(_min, _max);
}
public int ReRoll
{
get
{
Rolled = diceRoll.Next(_min, _max);
return Rolled;
}
}
}
Note the the dice has two properties: Rolled, and ReRoll. Because your intention is unclear, I've added both to illustrate the behavior.
Rolled is set by the constructor. If you want a new number, you can ReRoll.
If you do intentionally wanted the lifetime of a roll to be one per dice (but I dont think so) You'd remove the ReRoll method.
The dice would be called like this:
private static void Main(string[] args)
{
Dice myRoll = new Dice(1, 7);
// All the same
var result1 = myRoll.Rolled.ToString();
var result2 = myRoll.Rolled.ToString();
var result3 = myRoll.Rolled.ToString();
// something new
var result4 = myRoll.ReRoll.ToString();
Dice mySecondRoll = new Dice(1, 13);
var result = mySecondRoll.ReRoll.ToString();
}
Your get/setter backing fields are marked as "static". If a variable is declared "static", the value is persisted throughout the application and shared between different instances of the type they live in.
See here.
Also,
since your class properties contain no logic, I suggest using "automatic" properties.
class Dice
{
public int publicMinNum { get; set; }
public int publicMaxNum { get; set; }
Random diceRoll = new Random();
public int rolled = diceRoll.Next(publicMinNum , publicMaxNum );
}
tutorial on automatic properties here.
Your problem is due to the static members.
From the MSDN documentation on static, "While an instance of a class contains a separate copy of all instance fields of the class, there is only one copy of each static field."
I would change your class to look more like the following:
class Dice
{
// These are non-static fields. They are unique to each implementation of the
// class. (i.e. Each time you create a 'Dice', these will be "created" as well.
private int _minNum, _maxNum;
// Readonly means that we can't set _diceRand anywhere but the constructor.
// This way, we don't accidently mess with it later in the code.
// Per comment's suggestion, leave this as static... that way only one
// implementation is used and you get more random results. This means that
// each implementation of the Dice will use the same _diceRand
private static readonly Random _diceRand = new Random();
// A constructor allows you to set the intial values.
// You would do this to FORCE the code to set it, instead
// of relying on the programmer to remember to set the values
// later.
public Dice(int min, int max)
{
_minNum = min;
_maxNum = max;
}
// Properties
public Int32 MinNum
{
get { return _minNum; }
set { _minNum = value; }
}
public Int32 MaxNum
{
get { return _maxNum; }
set { _maxNum = value; }
}
// Methods
// I would make your 'rolled' look more like a method instead of a public
// a variable. If you have it as a variable, then each time you call it, you
// do NOT get the next random value. It only initializes to that... so it would
// never change. Using a method will have it assign a new value each time.
public int NextRoll()
{
return _diceRand.Next(_minNum, _maxNum);
}
}
I think the real problem here is that you haven't quite modeled a Die properly.
A die has a min and max value (that define the start and end of a range) but once a die has been made you are not able to change this i.e. a six sided die isn't made into an eight sided die. As such there is no need for the public setters.
Now, not all die share the same range, this is something that is specific to each die and so these properties should belong to the instance and not be static.
Again each die object has a CurrentRoll value representing the number that is face up and this is indeed generated at random. However to change the CurrentRoll of a die you need to Roll it.
This leaves an implementation of Die looking a something like
class Die
{
private static Random _random;
public int CurrentRoll { get; private set; }
public int Min { get; private set; }
public int Max { get; private set; }
public Die(int min, int max)
{
Min = min;
Max = max;
Roll();
}
public int Roll()
{
CurrentRoll = _random.Next(Min, Max+1); // note the upperbound is exlusive hence +1
return CurrentRoll;
}
}
and you would use it like
public static void Main()
{
Die d1 = new Die(1, 6);
Die d2 = new Die(1, 6);
Console.WriteLine(d1.Roll());
Console.WriteLine(d2.Roll());
//...
}
demo

How to shuffle multiple related arrays?

I have some unusual I need to do. I am wondering if anyone can think of an easy
way to make the change that I need. What I have is a
public class Report
{
public string[] Text { get; set; }
public string[] Image { get; set; }
public string[] Explanation { get; set; }
}
The report class can have any number of Texts, Images and Explanations and the size of each array is always the consistent but maybe be different for each report instance.
What I need to do is to be able to sort the array elements in a random order. So for example I might have
Report.Text[0] = "text0";
Report.Text[1] = "text1";
Report.Text[2] = "text2";
Report.Image[0] = "img0";
Report.Image[1] = "img1";
Report.Image[2] = "img2";
Report.Explanation[0] = "exp0";
Report.Explanation[1] = "exp1";
Report.Explanation[2] = "exp2";
then after sorting
Report.Text[0] = "text2";
Report.Text[1] = "text0";
Report.Text[2] = "text1";
Report.Image[0] = "img2";
Report.Image[1] = "img0";
Report.Image[2] = "img1";
Report.Explanation[0] = "exp2";
Report.Explanation[1] = "exp0";
Report.Explanation[2] = "exp1";
Can anyone think of a simple way to do this? All I can think of is that I need to create a
new temporary object of the same size and do some kind of swapping. But I am not sure how
to randomize. The reason I am asking is just in case someone has had this need in the past.
I would strongly recommend that you refactor this to create a single class to encapsulate the { Text, Image, Explanation } tuple. At that point, the code will be cleaner and it'll be trivial to reorder the values. Heck, you may not even need a Report type at that point... you may just be able to have a List<ReportItem> or whatever. You'd only need a separate Report type if you wanted to add extra behaviour or data to tie things together.
(As an aside, I hope you don't really have public fields for these to start with...)
If you then have a question around shuffling a single collection, a modified Fisher-Yates shuffle is probably the easiest approach. You could do this with the multiple arrays as well, but it wouldn't be nice - and would have to be specific to Report... whereas you could easily write a generic Fisher-Yates implementation based on IList<T>. If you search on Stack Overflow, you should easily be able to find a few existing implementations :)
If you choose to change your class to the following:
public class Report
{
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
You could then do this using an extension method:
(See answer on this SO question)
Then call it this way:
List<Report> reports = new List<Report> { /* create list of reports */ }
Random rnd = new Random();
foreach (Report r in reports.Shuffle(rnd)) {
/* do something with each report */
}
Why don't you create a class
public class Report
{
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
and then create a List of those objects and manage it through the list properties:
IList<Report> yourList = new List<Report>()
Here is my solution
class StringWrapper
{
public int Index;
public string Str;
}
public string[] MixArray(string[] array)
{
Random random = new Random();
StringWrapper[] wrappedArray = WrapArray(array);
for (int i = 0; i < wrappedArray.Length; i++)
{
int randomIndex = random.Next(0, wrappedArray.Length - 1);
wrappedArray[i].Index = randomIndex;
}
Array.Sort(wrappedArray, (str1, str2) => str1.Index.CompareTo(str2.Index));
return wrappedArray.Select(wrappedStr => wrappedStr.Str).ToArray();
}
private StringWrapper[] WrapArray(string[] array)
{
int i = 0;
return array.Select(str => new StringWrapper {Index = ++i, Str = str}).ToArray();
}
Then you can call MixArray for each Report object for each property you wand to randomize.
I am not sure I am fond of this direction, but ...
To do exactly what you ask (the law, not the spirit of the law), you will have to add additional arrays and pull items over. In addition, for each array, you will need a List or similar to store the items you have already randomly pulled over. After that, things are simple. Use the Random class to create random numbers, check if the item has already been moved (using the List), if not store the result in the new array/list, add the value to your List to make sure you do not move the same item twice. Once everything is moved, set this new array to the old array.
Now, what is the business reason for randomizing? That might affect whether or not this is a good idea.
ADDED:
After examination of skeet's response, here is a way to solve this if you can use the following type of class:
public class Report {
public string Text { get; set; }
public string Image { get; set; }
public string Explanation { get; set; }
}
Here is one "down and dirty" type of sort:
private static SortedList<int, Report> SortRandomly(List<Report> reports)
{
Random rnd = new Random((int)DateTime.Now.Ticks);
List<int> usedNumbers = new List<int>();
SortedList<int, Report> sortedReports = new SortedList<int, Report>();
int maxValue = reports.Count;
foreach(Report report in reports)
{
bool finished = false;
int randomNumber = 0;
//Get unique random (refactor out?)
while(!finished)
{
randomNumber = rnd.Next(0, maxValue);
if(!usedNumbers.Contains(randomNumber))
{
finished = true;
usedNumbers.Add(randomNumber);
}
}
sortedReports.Add(randomNumber, report);
}
return sortedReports;
}
Note, you can also work to keep the sort in order and randomly picking from the original list, which means you can, in theory, keep it as a list.
private static List<Report> SortRandomly(List<Report> reports)
{
Random rnd = new Random((int)DateTime.Now.Ticks);
List<Report> outputList = new List<Report>();
List<int> usedNumbers = new List<int>();
int maxValue = reports.Count-1;
while(outputList.Count < reports.Count)
{
int randomNumber = rnd.Next(0, maxValue);
if(!usedNumbers.Contains(randomNumber))
{
outputList.Add(reports[randomNumber]);
}
}
return outputList;
}
Even better, consider sorting the list of numbers first and then grabbing the reports, in an order manner. Once again, the above are down and dirty implementations and using the specific requirements will certainly refine the algorithms.

Categories