C #: отображение изображений на основе количества просмотров и случайных - PullRequest
1 голос
/ 22 октября 2009

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

В учебных целях я пытаюсь создать заставку, которая отображает изображения случайным образом из указанной папки. Да, 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 ]

1 голос
/ 22 октября 2009

Я думаю, вы делаете больше работы для себя, чем нужно.

Я не совсем уверен, что все ваши переменные делают, но именно так я бы решил проблему (код настройки и проверки ошибок и т. Д. Удален для ясности):

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) - это позиция в выбранной нами числовой строке. Второй цикл просто находит, какое изображение находится в этой точке в числовой строке, и это изображение отображается.

0 голосов
/ 22 октября 2009

Я нашел идею при просмотре этой ссылки.

При сортировке списка умножьте вес на случайное число.

Так что попробуйте

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();
...