C# losowanie - problem z powtórzeniem liczby

0

Dzień dobry,
mam taki kod

private void losowaniePytania(int [] tab2) // jako parametr tablica o 3 elementach
        {
            Random r = new Random(); // zmienna losowa
            int x = 0; // zmienna pomocnicza do przypisania losowania
            int y = 0; // zmienna pomocnicza iterator
            List<int> tab1 = new List<int>(); // lista indeksów pytań
            for (int i = 0; i < 10; i++) // wypełnienie listy liczbą pytań 0 - 9
            {
                tab1.Add(i);
            }
            do
            {
                bool czyOk = false; // zmienna pomocnicza do losowania
                int t = tab1.Count; // zmienna do przechowywania liczby elementów
                do
                {
                    x = tab1[r.Next(t)]; // losowanie
                    if (x < 0 || x == tab2[0] || x == tab2[1] || x == tab2[2])
                    {
                        czyOk = false; // jeśli false to losuj ponownie
                    }
                    else
                    {
                        czyOk = true; // losowanie ok
                        tab2[y] = x; // przypisanie wyniku losowania do tablicy
                        tab1.Remove(x); // usuwa wylosowany element
                        t--; // zmniejsza ilość elementów do wylosowania
                        y++;
                    }                    
                } while (czyOk == false); // koniec pojednyczego losowania
            } while (y < 3);
        } 

nie wiem co jest nie tak. Raz na kilka otworzeń aplikacji pytanie się powtarza. Najgorsze, że patrzę i nie widzę błędu. Będę wdzięczny jeśli ktoś rzuci okiem i coś podpowie.

0

Usuń z tablicy liczbę, która już została wylosowana?

0
AdamWox napisał(a):

Usuń z tablicy liczbę, która już została wylosowana?

jest w kodzie

tab1.Remove(x);
1

Po co używać listy jak można użyć zbioru, który przechowuje z definicji unikalne wartości?

Uzyj HashSet<int>, a będziesz miał pewność, że wstawiana wartość się nie powtórzy.

0

To kiedy ci się powtarza?

0
grzesiek51114 napisał(a):

Po co używać listy jak można użyć zbioru, który przechowuje z definicji unikalne wartości?

Uzyj HashSet<int>, a będziesz miał pewność, że wstawiana wartość się nie powtórzy.

Jak tego używać? Nigdy nie maiłem z tym do czynienia :)

0
AdamWox napisał(a):

To kiedy ci się powtarza?

Skompiluj i zobacz, sam nie wiem, dlatego założyłem ten post :)

0

napisałem coś takiego teraz i na razie w testach wychodzi nieźle

 private void losowaniePytania(int[] tab2) // jako parametr tablica o 3 elementach
        {
            Random r = new Random(); // zmienna losowa
            int x = 0; // zmienna pomocnicza do przypisania losowania
            int y = 0; // zmienna pomocnicza iterator
            HashSet<int> tab1 = new HashSet<int>(); // lista indeksów pytań
            for (int i = 0; i < 10; i++) // wypełnienie listy liczbą pytań 0 - 9
            {
                tab1.Add(i);
            }
            do
            {
                bool czyOk = false; // zmienna pomocnicza do losowania
                int t = tab1.Count; // zmienna do przechowywania liczby elementów
                do
                {
                    x = r.Next(10); // losowanie
                    if (tab1.Contains(x))
                    {
                        czyOk = true; // losowanie ok
                        tab2[y] = x; // przypisanie wyniku losowania do tablicy
                        tab1.Remove(x); // usuwa wylosowany element
                        t--; // zmniejsza ilość elementów do wylosowania
                        y++;
                    }
                    else
                    {
                        czyOk = false; // jeśli false to losuj ponownie
                    }                    
                } while (czyOk == false); // koniec pojednyczego losowania
            } while (y < 3);
        } 

#edit - jednak się powiela :(

0

Skompilowałem, uruchomiłem chyba z 15 razy, zobaczyłem i ani razu się nie powtórzyło.

0
AdamWox napisał(a):

Skompilowałem, uruchomiłem chyba z 15 razy, zobaczyłem i ani razu się nie powtórzyło.

Dam cały kod, może jest błąd w innym miejscu, sam już nie wiem

Form1

using System;
using System.Collections;
using System.Collections.Generic;
using System.Windows.Forms;

namespace Quiz_2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            losowaniePytania(tab);
            StartPosition = FormStartPosition.CenterScreen;
        }
        public class Pytanie
        {
            public string pyt, odp1, odp2, odp3, poprawna;
            public Pytanie(string zmPyt, string zmOdp1, string zmOdp2, string zmOdp3, string zmPoprawna)
            {
                pyt = zmPyt;
                odp1 = zmOdp1;
                odp2 = zmOdp2;
                odp3 = zmOdp3;
                poprawna = zmPoprawna;
            }
        }   
        public static Pytanie[] obj = new Pytanie[10]
        {
            new Pytanie("Kim był Jerzy Dudek?", "Malarzem", "Pisarzem", "Bramkarzem", "Bramkarzem"),
            new Pytanie("Titanic był?", "Samolotem", "Statkiem", "Pociągiem", "Statkiem"),
            new Pytanie("Kto napisał Pana Tadeusza?", "Adam Mickiewicz",
                "Juliusz Słowacki", "Juliusz Cezar", "Adam Mickiewicz"),
            new Pytanie("Co trzyma w ręku sędzia liniowy?", "Latarkę", "Pompkę do piłki",
                "Chorągiewkę", "Chorągiewkę"),
            new Pytanie("W którym roku zmarł Leonardo da Vinci?", "1533", "1519", "1513", "1519"),
            new Pytanie("Jakie miasto jest stolicą Hiszpanii?", "Madryt", "Barcelona", 
                "Sewilla", "Madryt"),
            new Pytanie("Jaki symbol znajduje się we fladze Argentyny?", "Chmura", "Słońce", 
                "Półksiężyc", "Słońce"),
            new Pytanie("Ile lat przestępnych występuje w ciągu 400 lat?", "96", "100", "104", "96"),
            new Pytanie("Jak nazywa się najbardziej wartościowa firma na świecie?", "BP",
                "Meble-Bodzio", "Apple", "Apple"),
            new Pytanie("Jak potocznie nazywa się hymn Francji?", "Paryżanka", "Marsylianka",
                "Francja nie ma hymnu", "Marsylianka")
        };
        public static Form2 f2 = new Form2(); //tworzenie od razu formatek z pytaniami
        public static Form3 f3 = new Form3();
        public static Form4 f4 = new Form4();
        public static int punkty = 0; // zliczanie punktów gracza
        public int[] tab = new int[3]; // tablca przechowuje wylosowane numery pytań
        private void Button1_Click(object sender, EventArgs e)
        {
            Hide();
            f2.Show();
        }
        private void losowaniePytania(int[] tab2) // jako parametr tablica o 3 elementach
        {
            Random r = new Random(); // zmienna losowa
            int x = 0; // zmienna pomocnicza do przypisania losowania
            int y = 0; // zmienna pomocnicza iterator
            HashSet<int> tab1 = new HashSet<int>(); // lista indeksów pytań
            for (int i = 0; i < 10; i++) // wypełnienie listy liczbą pytań 0 - 9
            {
                tab1.Add(i);
            }
            do
            {
                bool czyOk = false; // zmienna pomocnicza do losowania
                do
                {
                    x = r.Next(10); // losowanie
                    if (tab1.Contains(x))
                    {
                        czyOk = true; // losowanie ok
                        tab2[y] = x; // przypisanie wyniku losowania do tablicy
                        tab1.Remove(x); // usuwa wylosowany element
                        y++;
                    }
                    else
                    {
                        czyOk = false; // jeśli false to losuj ponownie
                    }                    
                } while (czyOk == false); // koniec pojednyczego losowania
            } while (y < 3);
        } 
        public static RadioButton GetCheckedRadio(Control container) // sprawdzanie które radio zaznaczone
        {
            foreach (var control in container.Controls) // pętla po radioButtonach
            {
                RadioButton radio = control as RadioButton; // przypisanie zmiennej wartości

                if (radio != null && radio.Checked) // jeśli zaznaczone
                {
                    return radio; // podaj które radio
                }
            }
            return null;
        }
    }
}

Form2

using System;
using System.Windows.Forms;

namespace Quiz_2
{
    public partial class Form2 : Form
    {
        Form1 myForm = new Form1();
        int i;
        void dodaj(ref int x)
        {
            x = myForm.tab[0];
        }
        
        
        public Form2()
        {
            dodaj(ref i);
            InitializeComponent();
            StartPosition = FormStartPosition.CenterScreen;
            textBox1.Text = Form1.obj[i].pyt;        
            radioButton1.Text = Form1.obj[i].odp1;
            radioButton2.Text = Form1.obj[i].odp2;
            radioButton3.Text = Form1.obj[i].odp3;
        }
        bool klikniete = false;
        private void button1_Click(object sender, EventArgs e)
        {
            
            if (Form1.GetCheckedRadio(groupBox1) == null)
            {
                MessageBox.Show("Wybierz odpowiedź");
            }
            else
            {
                if (Form1.GetCheckedRadio(groupBox1).Text == Form1.obj[i].poprawna && klikniete == false)
                {
                    Form1.punkty++;
                    klikniete = true;
                }                
                Hide();
                Form1.f3.Show();
            }            
        }
        private void Form2_FormClosed(object sender, FormClosedEventArgs e)
        {
            Application.Exit();
        }
    }
}

Pozostałe formy analogicznie jak Form2

1
public partial class Form1 : Form
    {
            List<int> tab1 = new List<int>();  // lista indeksów pytań
        public Form1()
        {
            InitializeComponent();
            for (int i = 0; i < 10; i++) // wypełnienie listy liczbą pytań 0 - 9
            {
                tab1.Add(i);
            }
            losowaniePytania(tab);
            StartPosition = FormStartPosition.CenterScreen;
        }
        public class Pytanie
        {
            public string pyt, odp1, odp2, odp3, poprawna;
            public Pytanie(string zmPyt, string zmOdp1, string zmOdp2, string zmOdp3, string zmPoprawna)
            {
                pyt = zmPyt;
                odp1 = zmOdp1;
                odp2 = zmOdp2;
                odp3 = zmOdp3;
                poprawna = zmPoprawna;
            }
        }   
        public static Pytanie[] obj = new Pytanie[10]
        {
            new Pytanie("Kim był Jerzy Dudek?", "Malarzem", "Pisarzem", "Bramkarzem", "Bramkarzem"),
            new Pytanie("Titanic był?", "Samolotem", "Statkiem", "Pociągiem", "Statkiem"),
            new Pytanie("Kto napisał Pana Tadeusza?", "Adam Mickiewicz",
                "Juliusz Słowacki", "Juliusz Cezar", "Adam Mickiewicz"),
            new Pytanie("Co trzyma w ręku sędzia liniowy?", "Latarkę", "Pompkę do piłki",
                "Chorągiewkę", "Chorągiewkę"),
            new Pytanie("W którym roku zmarł Leonardo da Vinci?", "1533", "1519", "1513", "1519"),
            new Pytanie("Jakie miasto jest stolicą Hiszpanii?", "Madryt", "Barcelona", 
                "Sewilla", "Madryt"),
            new Pytanie("Jaki symbol znajduje się we fladze Argentyny?", "Chmura", "Słońce", 
                "Półksiężyc", "Słońce"),
            new Pytanie("Ile lat przestępnych występuje w ciągu 400 lat?", "96", "100", "104", "96"),
            new Pytanie("Jak nazywa się najbardziej wartościowa firma na świecie?", "BP",
                "Meble-Bodzio", "Apple", "Apple"),
            new Pytanie("Jak potocznie nazywa się hymn Francji?", "Paryżanka", "Marsylianka",
                "Francja nie ma hymnu", "Marsylianka")
        };
        public static Form2 f2 = new Form2(); //tworzenie od razu formatek z pytaniami
        public static Form3 f3 = new Form3();
        public static Form4 f4 = new Form4();
        public static int punkty = 0; // zliczanie punktów gracza
        public int[] tab = new int[3]; // tablca przechowuje wylosowane numery pytań
        private void Button1_Click(object sender, EventArgs e)
        {
            Hide();
            f2.Show();
        }
        private void losowaniePytania(int[] tab2) // jako parametr tablica o 3 elementach
        {
            Random r = new Random(); // zmienna losowa
            int x = 0; // zmienna pomocnicza do przypisania losowania
            int y = 0; // zmienna pomocnicza iterator

            do
            {
                bool czyOk = false; // zmienna pomocnicza do losowania
                do
                {
                    x = r.Next(10); // losowanie
                    if (tab1.Contains(x))
                    {
                        czyOk = true; // losowanie ok
                        tab2[y] = x; // przypisanie wyniku losowania do tablicy
                        tab1.Remove(x); // usuwa wylosowany element
                        y++;
                    }
                    else
                    {
                        czyOk = false; // jeśli false to losuj ponownie
                    }                    
                } while (czyOk == false); // koniec pojednyczego losowania
            } while (y < 3);
        } 
        public static RadioButton GetCheckedRadio(Control container) // sprawdzanie które radio zaznaczone
        {
            foreach (var control in container.Controls) // pętla po radioButtonach
            {
                RadioButton radio = control as RadioButton; // przypisanie zmiennej wartości

                if (radio != null && radio.Checked) // jeśli zaznaczone
                {
                    return radio; // podaj które radio
                }
            }
            return null;
        }
    }

Z każdym losowaniem pytania wypełniasz listę od nowa. Może wypełnij listę raz w konstruktorze i wtedy losuj ;)

#edit
Jeśli mówisz o powtórkach z każdym włączeniem aplikacji to to normalne. Musisz zapisać listę już wylosowanych pytań gdzieś do pliku, aby później zainicjować tylko listę z pytaniami, które nie zostały już wybrane.

0

Nie no właśnie problem był taki, że jak apka była otwarta to np Form 2 i Form 3 miały te same pytania.
Dzięki za odpowiedź, chyba już wiem gdzie był błąd :) Pozdrawiam serdecznie :)

0

A nie lepiej użyć tego algorytmu?
https://rosettacode.org/wiki/Knuth_shuffle

0
adam_qwe napisał(a):

A nie lepiej użyć tego algorytmu?
https://rosettacode.org/wiki/Knuth_shuffle

Nie, ponieważ to nie jest losowanie kolejności argumentów w tablicy :) chodzi o to że jest zbiór pytań z indeksami 0 - 9 i do tego tablica[3] do której mają być przypisane 3 elementy. Niby można pomieszać tablicę pytań i brać z niej zawsze pierwsze 3 elementy ale nie taki jest pomysł autora ;D chcę to zrobić inaczej ale dziękuję za odpowiedź :)

1 użytkowników online, w tym zalogowanych: 0, gości: 1