C#:根据视图数量和随机显示图像

时间:2009-10-22 08:43:14

标签: c# visual-studio-2008

我不确定在此使用何种术语,因此请根据需要编辑标题。

出于学习目的,我正在尝试制作一个从指定文件夹中随机显示图像的屏幕保护程序。是的,Windows已经提供了这个,但再次,学习目的。虽然我宁愿第一次学习正确的方法,而不是不得不重新学习如何正确地做事。

现在我已经随机选择图像并显示它们等等。我想做的是根据特定图像的加载次数进行随机化。

例如:

图1:0视图(20%):1视图(19%)
图2:0次观看(20%):0次观看(24%)
图3:0视图(20%):1视图(19%)
图4:0次观看(20%):2次观看(14%)
图5:0浏览次数(20%):0次浏览(24%)

这样,图像2和图像5最有可能被显示在下一个。

我已经有一段时间了,但我不确定是什么问题,因为它只是抓住列表中的下一张照片。我试图通过查找具有相同数量的视图的所有图片然后通过该列表随机化来对它们进行分组,但它似乎并不完全正常工作。这是我显示图片的代码:

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;  
    }  
} 

我希望这很清楚,并提前感谢。

2 个答案:

答案 0 :(得分:1)

我认为你为自己做的工作比它需要做的更多。

我不完全确定你的变量都做了什么,但这就是我解决问题的方法(设置和错误检查代码等为了清晰起见而删除):

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];
}

基本上我们根据视图数量构建一个文件权重数组(较低的视图意味着更高的权重)。这些权重加起来为1(例如[0.19,0.24,0.19,0.14,0.24])并有效地将0到1的数字线分开:

|--------|-----------|-------|------|---------|
0                                             1
  (0.19)    (0.24)     (0.19) (0.14)  (0.24)    - Weightings
    0         1          2      3       4       - Corresponding images

然后我们选择0到1之间的随机数(rndChoice) - 这是我们选择的数字行中的位置。第二个循环只是找到哪个图像位于数字行中的那个点,并且该图像被显示出来。

答案 1 :(得分:0)

我在查看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();