Forum MOJA PASJA - PROGRAMOWANIE Strona Główna
http://www.programuj.com
  WikiWiki  FAQFAQ    SzukajSzukaj    UżytkownicyUżytkownicy    GrupyGrupy   RejestracjaRejestracja 
 ProfilProfil   Zaloguj się, by sprawdzić wiadomościZaloguj się, by sprawdzić wiadomości   ZalogujZaloguj 




Funkcja losowania liczb w kodzie C++


 
Napisz nowy temat   Odpowiedz do tematu    Forum MOJA PASJA - PROGRAMOWANIE Strona Główna -> C i C++
Zobacz poprzedni temat :: Zobacz następny temat  
Autor Wiadomość
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Hej!
Mam jakiegoś babola w kodzie programu, ale nie wychwyciłem gdzie dokładnie tkwi błąd. Kod jest bardzo krótki, oto on:

c++:

#include <iostream>
 #include <math.h>
 using namespace std;
 const unsigned IloscLiczb = 6;
const int MaxLiczba = 49;
 int main()
 {
 cout << "________Wybrano losowanie  duzego lotka.________\n\n";
                      cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\ni wyswietla"
                      " wynik na ekranie. Za kazdym razem wynik losowania jest inny.\n";
                     
                     
                      "\n\n\nPodaj, ile losowan ma zostac przeprowadzonych:  ";
                      int pola;
                      cin >> pola;
                      cin.ignore();
                      if(pola > 101)
                      {
                      cout << "Wybrales  " << pola << "  losowan. Ze wzgledu na bezpieczenstwo Twojego komputera,\n"
                      "nie mozna przeprowadzic wiecej niz 100 losowan.\n\n\n\n ";
                     
                      }
                      else
                      {
                     
                       while(pola)
                      {
                      pola = pola - 1;
                     
                      unsigned Liczby[IloscLiczb];//Od tego momentu algorytm korzysta z dosc znanego tricku - nie tlumacze
                      for(int i = 0; i < IloscLiczb; ++i) Liczby[i] = 0;
                      srand(static_cast<int>(time(NULL)));
                      for (int i = 0; i < IloscLiczb;)
                      {
                      Liczby[i] = rand() % MaxLiczba + 1;
                      bool PowtarzaSie = false;
                      for(int j = 0; j < i; ++j)
                      {
                      if(Liczby[j] == Liczby[i])
                      {
                             PowtarzaSie = true;
                             break;
                      }
                      }
                      if(!PowtarzaSie) ++i;
                      }
                      for(int i = 0; i < IloscLiczb; ++i)
                      cout << "    " << Liczby[i];
                      cout << "\n\n\n";
                      }
                     
                      }
 system("pause");
 }


Rzecz w tym, że przy ilości losowań większej niż jedno, wyniki losowań powtarzają się, a powinno być ich tyle ile podał klient. Funkcja losująca jakoś nie jest w stanie wykonywać przy każdym obrocie pętli nowych losowań, tylko powtarza to nieszczęsne pierwsze.

Kompiluje w dev- ie, czy trzeba coś zmienić w pętli while, aby wyniki losowań były różne a nie powtarzały się?
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Sinus32
programista


Dołączył: 22 Lip 2007
Posty: 1790
Skąd: z tego cyfrowego świata...

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Trochę poprawiłem - teraz działa jak należy:
c++:
#include <iostream>
#include <ctime> // Brakujący nagłówek
// Tu był użyty przestarzały nagłówek math.h który nie jest potrzebny

using namespace std;

const unsigned IloscLiczb = 6;
const int MaxLiczba = 49;

int main()
{
  srand(static_cast<int>(time(NULL))); // To tu powinno być
 
  cout << "________Wybrano losowanie  duzego lotka.________\n\n";
  cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\n"
          "i wyswietla wynik na ekranie. Za kazdym razem wynik losowania jest"
          "inny.\n" // Tu był średnik, a nie powinno go być
          "\n\n\nPodaj, ile losowan ma zostac przeprowadzonych:  ";
  int pola;
  cin >> pola;
  cin.ignore();
 
  if(pola > 101)
    cout << "Wybrales  " << pola << "  losowan. Ze wzgledu na bezpieczenstwo"
      "Twojego komputera,\nnie mozna przeprowadzic wiecej niz 100 losowan.\n\n\n";
  else
  {
    while(pola)
    {
      pola -= 1; // Optymalniejsze
      unsigned Liczby[IloscLiczb];
      for(int i = 0; i < IloscLiczb; ++i)
        Liczby[i] = 0; // Po co zerujesz? Zaraz je zapełnisz
      // Tu był srand wykonywany więcej niż raz w tym kodzie.
      // Powodował identyczne wylosowania.
      for (int i = 0; i < IloscLiczb;)
      {
        Liczby[i] = rand() % MaxLiczba + 1;
        bool PowtarzaSie = false;
        for(int j = 0; j < i; ++j)
        {
          if(Liczby[j] == Liczby[i])
          {
            PowtarzaSie = true;
            break;
          }
        }
        if(!PowtarzaSie) ++i;
      }
      for(int i = 0; i < IloscLiczb; ++i)
        cout << '\t' << Liczby[i]; // Tak będzie lepiej wyglądać
      cout << '\n';
    }
  }
  system("pause");
  return 0; // Brakowało, a jest konieczne
}

Problem był w tym, że srand był wywoływany wielokrotnie w ciągu jednej sekundy i wielokrotnie inicjował generator ciągle tą samą wartością.

Poza tym jeszcze jedna prośba: FORMATUJ KOD
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Wyślij email Odwiedź stronę autora
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Sprawdziłem poprawki i muszę się zgodzić z wszystkimi z nich. Oczywiście teraz jest tak jak powinno, a ja wiem na przyszłość.

Muszę przyznać "Sinus32", że masz bardzo logiczny i czytelny styl kodowania. Sam muszę wyrobić w sobie właśnie takie nawyki zamieszczania instrukcji.

Dzięki.
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Hej, w związku z już poprawnie działającym algorytmem losowań, wpadł mi do głowy pomysł, aby go jeszcze trochę usprawnić, otóż: kiedy klient wpisze ilość losowań, program wykonuje podaną liczbę losowań, a następnie podaje sześć najczęściej powtarzających się liczb. Chodzi o pewnego rodzaju system znajdowania najbardziej trafnych liczb. Liczb jest 49. Jeśli klient wpisze 70 losowań, taki program wykona je, a na dodatek na końcu wypisze te sześć najczęściej powtarzających się.

System świetny, tylko jak to nawiązać do powyższego, poprawionego przez Sinus32-a kodu?

Próbowałem pokombinować z samą funkcją losującą, ale jest to ponad moje obecne możliwości.

Ma ktoś jakiś pomysł?
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Sinus32
programista


Dołączył: 22 Lip 2007
Posty: 1790
Skąd: z tego cyfrowego świata...

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Policzyć ile razy wypadły poszczególne liczby, posortować wyniki i wypisać 6 najtrafniejszych
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Wyślij email Odwiedź stronę autora
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Ok, rozumiem, ale nie wiem jak to wykonać ( mój obecny etap nauki to wskaźniki, także klasy, dziedziczenie itd nie rozumiem).

Może jakaś podpowiedź naprowadzająca, może jakiś pseudo kod jak to wykonać?

Podejrzewam, że będzie trzeba zrobić jakąś funkcje, ale jak ona ma pozyskać dane, czyli te wszystkie wylosowanie liczby (Liczby[i]) co klient wybrał (pola)?

Potrzeba mi naprowadzenia na sposób realizacji.
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Sinus32
programista


Dołączył: 22 Lip 2007
Posty: 1790
Skąd: z tego cyfrowego świata...

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Zanalizuj ten kod:
Zastosowałem w nim kilka prawie logicznych sztuczek. Prawie zrobiło się spaghetti Very Happy Jakby coś było niejasne (a podejrzewam że będzie) to pisz.
c++:
#include <iostream>
#include <ctime>

using namespace std;

const unsigned short IloscLiczb = 6;
const unsigned short MaxLiczba = 49;

struct licznik
{
    int co;
    int ile;
};

void sortuj(licznik**, unsigned short);

int main()
{
  srand(static_cast<int>(time(NULL)));
 
  cout << "________Wybrano losowanie  duzego lotka.________\n\n";
  cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\n"
          "i wyswietla wynik na ekranie. Za kazdym razem wynik losowania jest"
          "inny.\n\n\nPodaj, ile losowan ma zostac przeprowadzonych: ";
  unsigned short IleLosowan;
  cin >> IleLosowan;
 
  if(IleLosowan > 5000) IleLosowan = 5000; // Trochę podniosłem górny limit
  if(IleLosowan < 1) IleLosowan = 1;
 
  unsigned short Liczby[IloscLiczb];
  licznik * Licznik[MaxLiczba];
  for (int i = 0; i < MaxLiczba; ++i)
  {
      Licznik[i] = new licznik;
      Licznik[i]->co = i + 1;
      Licznik[i]->ile = 0;
  }
 
  for (unsigned short Losowanie = 0; Losowanie < IleLosowan; ++Losowanie)
  {
    for(int i = 0; i < IloscLiczb; ++i)
    {
      Liczby[i] = rand() % MaxLiczba + 1;
      for(int j = 0; j < i; ++j) if(Liczby[j] == Liczby[i]) {--i; break;}
    }
    for(int i = 0; i < IloscLiczb; ++i)
    {
        ++(Licznik[Liczby[i] - 1]->ile);
        cout << '\t' << Liczby[i];
    }
    cout << '\n';
  }
 
  sortuj(Licznik, MaxLiczba);
 
  int min = Licznik[5]->ile;
  cout << "Najczesciej pojawiajace sie liczby:\n";
  // Wyświetla minimum 6 najczęściej wylosowanych liczb
  for (int i = 0; i < MaxLiczba; ++i)
  {
    if (Licznik[i]->ile >= min)
      cout << "Liczba " << Licznik[i]->co << " wypadla " << Licznik[i]->ile << " razy\n";
    delete Licznik[i];
  }
 
  system("pause");
  return 0;
}

void sortuj(licznik ** Dane, unsigned short Granica)
{
    licznik * temp;
    unsigned short int i, j;
    Granica--;
    for(i = 0; i < Granica; i++)
        for(j = 0; j + i < Granica; j++)
            if(Dane[j]->ile < Dane[j+1]->ile)
            {
                temp = Dane[j];
                Dane[j] = Dane[j+1];
                Dane[j+1] = temp;
            }
}
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Wyślij email Odwiedź stronę autora
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Ok, lol, kod potężnie przebudowany.

c++:

if(IleLosowan > 5000) IleLosowan = 5000; // Trochę podniosłem górny limit
  if(IleLosowan < 1) IleLosowan = 1;


Rzeczywiście, dzięki temu nie trzeba puszczać głupiego komunikatu. Jestem ciekaw ile można by było ustawić najw. liczbę losowań, tak aby komp klienta nie oszalał?


c++:
Licznik[i] = new licznik;
      Licznik[i]->co = i + 1;
      Licznik[i]->ile = 0;

Ok, ale co oznacza gdy piszesz:
c++:
->
Nie widziałem takiego zapisu?


c++:
void sortuj(licznik**, unsigned short);


Co robią te dwie gwiazdki po "licznik" i co daje to, że jest on typu "struct"?
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Sinus32
programista


Dołączył: 22 Lip 2007
Posty: 1790
Skąd: z tego cyfrowego świata...

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Komputer nie oszaleje nawet jak dasz mu nieograniczony limit, przy czym pamiętaj że najwięcej czasu zabiera mu wyświetlenie tekstu, a nie przetworzenie danych.

Operator -> jest operatorem dostępu pośredniego (przez wskaźnik). Dowiesz się o nim wszystkiego jak poczytasz o strukturach i klasach.

Dwie gwiazdki oznaczają że argumentem jest wskaźnik do wskaźnika do wskaźnika na daną typu 'licznik'. Kliknij na link "kurs" w moim podpisie i poczytaj o wskaźnikach.
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Wyślij email Odwiedź stronę autora
Dante190884



Dołączył: 03 Paź 2007
Posty: 19
Skąd: Kraków

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Ok, zaimplementowałem Twój kod do swojego kalkulatora, choć nie było łatwo, bo wystąpiły problemy z funkcją "sortuj". Ponieważ menu mam realizowane za pomocą "switch", w case xx funkcja nie dała się skompilować.
Przeniosłem więc ją do instrukcji "if" i teraz w skrócie to wygląda tak:

c++:

//DEFINICJE I DEKLARACJE DO DUŻEGO LOTKA*********************************************************************************
const unsigned short IloscLiczb = 6;// Ilość liczb wylosowanych w dużym lotku.
const unsigned short MaxLiczba = 49;// Losowanie w dużym lotku spośród 49 liczb.

struct licznik
{
    int co;
    int ile;
};

void sortuj(licznik**, unsigned short);

fun. main:

switch(wybor)
....
....
....

if(wybor == 14)
      {
      system("cls");
      srand(static_cast<int>(time(NULL)));// W losowaniu lotto potrzebny do wykonania losowania wielokrotnie.
     
      cout << "________________Wybrano losowanie  duzego lotka.________________\n\n";
      cout << "Program automatycznie losuje szesc liczb z czterdziestu dziewieciu\n"
      "i wyswietla wynik na ekranie. Za kazdym razem wynik losowania jest"
      " inny.\nPonadto wyswietla min. szesc najczesciej powtarzajacych sie liczb.\n\n"
      "\nPodaj, ile losowan ma zostac przeprowadzonych:  ";
     
      unsigned short IleLosowan;
      cin >> IleLosowan;
 
      if(IleLosowan > 50000) IleLosowan = 50000; // Optymalna liczba losowań. Jak klient wpisze
      if(IleLosowan < 1) IleLosowan = 1; // większą, to i tak zostanie wykonanych max. 50 000.
 
      unsigned short Liczby[IloscLiczb];
      licznik * Licznik[MaxLiczba];
      for (int i = 0; i < MaxLiczba; ++i)
          {
          Licznik[i] = new licznik;
          Licznik[i]->co = i + 1;//Operator -> jest operatorem dostępu pośredniego (przez wskaźnik).
          Licznik[i]->ile = 0;
          }
 
      for(unsigned short Losowanie = 0; Losowanie < IleLosowan; ++Losowanie)
         {
         for (int i = 0; i < IloscLiczb; ++i)
             {
             Liczby[i] = rand() % MaxLiczba + 1;
             for(int j = 0; j < i; ++j) if(Liczby[j] == Liczby[i]) {--i; break;}
             }
         for(int i = 0; i < IloscLiczb; ++i)
            {
            ++(Licznik[Liczby[i] - 1]->ile);
            cout << '\t' << Liczby[i];
            }
         cout << '\n';
         }
 
       sortuj(Licznik, MaxLiczba);
 
       int min = Licznik[5]->ile;
       cout << "Najczesciej powtarzajace sie liczby to:\n\n";// Wyświetla minimum 6 najczęściej wylosowanych liczb
                     
       for(int i = 0; i < MaxLiczba; ++i)
          {
          if (Licznik[i]->ile >= min)
          cout << "Liczba  " << Licznik[i]->co << "  wypadla  " << Licznik[i]->ile << "  razy\n\n";
          delete Licznik[i];
          }                                                                         
                     
       }

}


void sortuj(licznik ** Dane, unsigned short Granica)
           {
           licznik * temp;
           unsigned short int i, j;
           Granica--;
           for(i = 0; i < Granica; i++)
           for(j = 0; j + i < Granica; j++)
           if(Dane[j]->ile < Dane[j+1]->ile)
             {
             temp = Dane[j];
             Dane[j] = Dane[j+1];
             Dane[j+1] = temp;
             }
           }     
//koniec***************************************************



Wszystko działa wyśmienicie, niestety nie jestem w stanie jeszcze zrozumieć zasadniczego działania. Ponieważ jest to zrealizowane za pomocą "tricków", których jeszcze nie znam, nie mogę nawet pobawić się nad modyfikowaniem tego kodu (bo pewnie bym popsuł). A chciałem jeszcze dodać jedną rzecz: otóż po wylosowaniu i wybraniu najczęściej powtarzających się liczb, algorytm mógł by wypisać na ekranie tylko te liczby, które ani razu nie zostały wylosowane spośród wszystkich losowań.

Nie wiem, czy to trudne i czy trzeba będzie mocno zmodyfikować/dodać kod?
_________________
www.lifecode.go.pl
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Odwiedź stronę autora
Sinus32
programista


Dołączył: 22 Lip 2007
Posty: 1790
Skąd: z tego cyfrowego świata...

Post Zacytuj zaznaczone Odpowiedz z cytatem OCEŃ POST
Modyfikacja była by bardzo prosta. Była by w tej części kodu:
c++:
       for(int i = 0; i < MaxLiczba; ++i)
          {
          if (Licznik[i]->ile >= min)
          cout << "Liczba  " << Licznik[i]->co << "  wypadla  " << Licznik[i]->ile << "  razy\n\n";
          // Tutaj <----------------------------------
          delete Licznik[i];
          }

Tablica wskaźników Licznik zawiera MaxLiczba rekordów w których są zapisane liczby i ilość ich wystąpień.
Powrót do góry
Ogląda profil użytkownika Wyślij prywatną wiadomość Wyślij email Odwiedź stronę autora
Wyświetl posty z ostatnich:   
Napisz nowy temat   Odpowiedz do tematu    Forum MOJA PASJA - PROGRAMOWANIE Strona Główna -> C i C++ Wszystkie czasy w strefie CET (Europa)
Strona 1 z 1

 
Skocz do:  
Nie możesz pisać nowych tematów
Nie możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach


hosting sponsorowany przez hosted.pl
Powered by phpBB © 2001, 2002 phpBB Group