I'm not sure what kind of terminology to use in this so please edit the title to fit as necessary.
For learning purposes, I'm trying to make a screensaver tha开发者_开发问答t displays images randomly from a specified folder. Yes, Windows already comes with this but again, learning purposes. Though I'd prefer to learn the proper way the first time instead of having to go back through and relearn how to properly do things.
Now I already have it randomly choosing images and displaying them, etc. What I'd like to do is randomize based on how many times a specific image has been loaded.
For example:
Image 1: 0 views(20%) : 1 view (19%) Image 2: 0 views(20%) : 0 views(24%) Image 3: 0 views(20%) : 1 view (19%) Image 4: 0 views(20%) : 2 views(14%) Image 5: 0 views(20%) : 0 views(24%)
This way Image 2 and Image 5 would have the highest chance of being shown next.
I've been at this for a while but I'm not sure what's wrong as it's simply grabbing the next pic along the list. I tried to group them by finding all the pictures with the same number of views and then randomizing through that list but it doesn't seem to exactly work the greatest. Here's the code I have for displaying the pictures:
Random rnd = new Random();
string file = "";
int totalViews = 0;
List<string> array = new List<string>();
void ShowPicture()
{
array.Clear();
label1.Text = "";
foreach (Screen screen in Screen.AllScreens)
{
bool done = false;
while (!done)
{
int rand = rnd.Next(100), total;
foreach (string info in files.Keys)
{
total = (100 / files.Count) - (files[info] * (files.Count - 1)) + totalViews;
if (total >= rand)
{
foreach (string tmp in files.Keys) if (total >= files[tmp]) array.Add(tmp);
label1.Text = "Percentage for image: " + total;
done = true;
break;
}
}
}
file = array[rnd.Next(array.Count)];
files[file]++;
totalViews++;
Image image = Image.FromFile(file);
pictureBox1.Image = image;
label1.Text += "\nTotal Views: " + totalViews;
}
}
I hope this is clear enough and thanks in advance.
I think you're making more work for yourself than it needs to be.
I'm not entirely sure what your variables all do, but this is how I would solve the problem (setup and error checking code etc. removed for clarity):
int totalViews; // Assuming this stores the total number of images that
// have been shown so far (4 in your example)
double [] fileWeighting; // How to weight each file
int [] fileViews; // How many times each file has been seen in total
// Note Sum(fileViews) = totalViews
for(int i = 0; i < files.Count; i++) {
fileWeighting[i] = ((double)totalViews - (double)fileViews[i]) /
(double)totalViews;
}
double rndChoice = Random.NextDouble();
double acc = 0;
for (int j = 0; j < files.Count; j++) {
if ( (rndChoice - acc) < fileWeighting[j] ) {
// Display image j
break;
}
acc += fileWeighting[j];
}
Basically we build an array of file weightings based on their view count (lower views mean higher weightings). These weightings add up to 1 (e.g. [0.19, 0.24, 0.19, 0.14, 0.24]) and effectively divide up the 0 to 1 number line:
|--------|-----------|-------|------|---------|
0 1
(0.19) (0.24) (0.19) (0.14) (0.24) - Weightings
0 1 2 3 4 - Corresponding images
We then choose a random number between 0 and 1 (rndChoice
) - this is the position in the number line we have chosen. The second loop simply finds which image lies at that point in the number line, and that image gets displayd.
I found the idee when looking at this link.
Basically, multiply the weight with the random number when sorting the list.
So try this
List<KeyValuePair<string, decimal>> list = new List<KeyValuePair<string, decimal>>();
for (int iItem = 0; iItem < 10; iItem++)
list.Add(new KeyValuePair<string, decimal>(iItem.ToString(), iItem/10m));
Random rnd = new Random();
list.Sort( delegate(KeyValuePair<string, decimal> item1, KeyValuePair<string, decimal> item2)
{
if (item1.Value == item2.Value)
return 0;
decimal weight1 = 1 / (item1.Value == 0 ? 0.01m : item1.Value);
decimal weight2 = 1 / (item2.Value == 0 ? 0.01m : item2.Value);
return (weight1 * rnd.Next()).CompareTo(weight2 * rnd.Next());
});
list.Reverse();
精彩评论