Skocz do zawartości
  • 👋 Witaj na MPCForum!

    Przeglądasz forum jako gość, co oznacza, że wiele świetnych funkcji jest jeszcze przed Tobą! 😎

    • Pełny dostęp do działów i ukrytych treści
    • Możliwość pisania i odpowiadania w tematach
    • System prywatnych wiadomości
    • Zbieranie reputacji i rozwijanie swojego profilu
    • Członkostwo w jednej z największych społeczności graczy

    👉 Dołączenie zajmie Ci mniej niż minutę – a zyskasz znacznie więcej!

    Zarejestruj się teraz

[Pytanie] C++ - Losowanie liczb bez powtórzeń


Rekomendowane odpowiedzi

Opublikowano

Witam i Wesołych Świąt wszystkim :)

Zaczynam dopiero swoją przygodę z C++. Podczas pisania jednego ze swoich pierwszych skryptów, natrafiłem na problem.

Program ma:
1. Wczytać trzy liczby całkowite
2. Wylosować bez powtórzeń dwie z nich
3. Wypisać je.

Zamiast tego losuje TYLKO JEDNĄ i wypisuje ją w nieskończoność.
Kod zamieszczam poniżej:


#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;


void wczytanie(int tab[])
{
    int i = 0;
    do
    {
        cout << "Podaj liczbe: " << i+1 << endl;
        cin >> tab[i];
        i++;
        } while(i<3);
}



int wylosowanie()
{
 return rand();
}


bool czyWylosowane (int liczba, int tab[], int ile)
{
     if (ile <= 0);
        return false;
     int i = 0;
     do
     {
         if(tab[i] = liczba)
         return true;
         i++;
     } while (i < ile);
     
     return false;
}

bool czyIstnieje (int liczba, int tab[], int ile)
{
     int i = 0;
     do
     {
         if (tab[i] = liczba) 
         return true;
     }while (i < ile);
     
     
}

void wypisanie(int tab[])
{
     int i;
     do
     {
         i = 0;
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

int main()
{   
    srand(time(NULL));
    int dostepne[3];
    wczytanie(dostepne);
    int doWylosowania[2];
    int liczbaWylosowanych = 0;
    do
    {
        int liczba = wylosowanie();
        if ((czyIstnieje(liczba, dostepne, liczbaWylosowanych) && !(czyWylosowane(liczba,doWylosowania,liczbaWylosowanych))))
        doWylosowania[liczbaWylosowanych] = liczba;
        liczbaWylosowanych++;
    } while(liczbaWylosowanych < 2);
    wypisanie(doWylosowania);
    
    return 0;
}

Z góry dziękuję za pomoc i przepraszam za nieczytelny kod. :)

Opublikowano

2 rzeczy:

1)

bool czyIstnieje (int liczba, int tab[], int ile)
{
     int i = 0;
     do
     {
         if (tab[i] = liczba) 
         return true;
     }while (i < ile); 
}

Zapomniałeś w pętli o

i++;

2)

void wypisanie(int tab[])
{
     int i;
     do
     {
         i = 0;
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

A tutaj w pętli nie potrzebne jest:

i = 0;

Jak już tak bardzo chcesz nadać zmiennej "i" wartość "0", to wstaw to przed pętlę.

Opublikowano

Dziękuję za pomoc. Tak wygląda poprawiony kod:


#include <iostream>
#include <ctime>
#include <cstdlib>
using namespace std;


void wczytanie(int tab[])
{
    int i = 0;
    do
    {
        cout << "Podaj liczbe: " << i+1 << endl;
        cin >> tab[i];
        i++;
        } while(i<3);
}



int wylosowanie()
{
 return rand();
}


bool czyWylosowane (int liczba, int tab[], int ile)
{
     if (ile <= 0);
        return false;
     int i = 0;
     do
     {
         if(tab[i] = liczba)
         return true;
         i++;
     } while (i < ile);
     
     return false;
}

bool czyIstnieje (int liczba, int tab[], int ile)
{
     int i = 0;
     do
     {
         if (tab[i] = liczba) 
         return true;
         i++;
     }while (i < ile);
     
     
}

void wypisanie(int tab[])
{
     int i = 0;
     do
     {
        
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

int main()
{   
    srand(time(NULL));
    int dostepne[3];
    wczytanie(dostepne);
    int doWylosowania[2];
    int liczbaWylosowanych = 0;
    do
    {
        int liczba = wylosowanie();
        if ((czyIstnieje(liczba, dostepne, liczbaWylosowanych) && !(czyWylosowane(liczba,doWylosowania,liczbaWylosowanych))))
        doWylosowania[liczbaWylosowanych] = liczba;
        liczbaWylosowanych++;
    } while(liczbaWylosowanych < 2);
    wypisanie(doWylosowania);
    
    return 0;
}

Jednak teraz liczby losowane są z przedziału <d245777abca64ece2d5d7ca0d19fddb6.png , d245777abca64ece2d5d7ca0d19fddb6.png>. Poza tym wypisywane są tylko dwie liczby, mimo że pętla

void wypisanie(int tab[])
{
     int i = 0;
     do
     {
        
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

wskazuje na trzy.

 

Jakieś sugestie?

Opublikowano

Co do losowania liczb z przedziału to nie rozumiem czy traktujesz to jako błąd czy co...Ani w jednym ani w drugim kodzie nie widzę nigdzie próby losowania z przedziałem (chyba, że słabo paczam). Widzę natomiast tylko taki zapis:

int wylosowanie()
{
 return rand();
}

który mówi o zwróceniu wylosowanej liczby, nic tutaj niema o przedziałach. Jeżeli masz jakieś problemy z zrozumieniem działania liczb pseudolosowych to polecam zajrzeć TUTAJ.

 

Jeżeli chodzi o wypisywanie liczb w pętli to najlepiej proponuje Ci rozpisanie przebiegu tej pętli krok po kroku na kartce, a w mig połapiesz się gdzie jest błąd... no chyba, że nie dasz rady to poniżej masz moja rozpiskę (chyba dobrą, w sumie jest późno i mogłem walnąć byka :) )

void wypisanie(int tab[])
{
     int i = 0;
     do
     {
        
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

czyli...

I Przebieg Pętli

i = 0;

wypisanie wartości tablicy o indeksie 0

i = i + 1 / i = 0 + 1/ i = 1

sprawdzenie warunku, czy i < 2 / 1 < 2 (prawda, czyli można zrobić następny przebieg)

II Przebieg Pętli

i = 1;

wypisanie wartości tablicy o indeksie 1

i = i + 1/ i = 1 + 1/ i = 2

sprawdzenie warunku, czy i < 2 / 2 < 2(false, gdyby było =<(większe-równe) lub i < 3 to warunek byłby spełniony i można było by wykonać III przebieg pętli)

 

Wesołych Świąt :)

Opublikowano

@ kochan78

 

I Przebieg Pętli

i = 0;

wypisanie wartości tablicy o indeksie 0

i = i + 1 / i = 0 + 1/ i = 1

Czyli

void wypisanie(int tab[])
{
     int i = 0; // i = 0
     do
     {
        
        cout << tab[i] << "," << endl; // w wypadku 1 jest to wypisanie wartosci tablicy o indeksie 0
        i++; // i = i + 1
        } while (i<2); // sprawdzenie warunku i wykonanie petli ponownie 
}

Dalej nie widzę błędu.

Opublikowano

No to inaczej...

void wypisanie(int tab[])
{
     int i = 0;
     do
     {
        
        cout << tab[i] << "," << endl;
        i++;
        } while (i<2);
}

Powyższa pętla wykonuje się tylko w tedy, gdy zmienna "i" jest mniejsza od 2 zatem warunek wygląda tak:

while(i<2)

czyli instrukcje zostaną wykonane tylko, gdy zmienna "i" przyjmuje wartości 0 i 1 (zaczynasz od i = 0), a przy wartości 2 nie może być, ponieważ warunek "2 < 2" przyjmuje fałsz i pętla się nie wykonuje. Zostaną więc wypisane tylko 2 liczby - co jest błędem, gdyż Ty chcesz, aby zostały wypisane 3 liczby.

Zatem najlepiej będzie, gdy zmienisz po prostu warunek w while() na:

while(i<=2)

lub

while(i<3)

Myślę, że teraz już powinieneś załapać o co chodzi, a jak nie to poczytaj sobie trochę o tych pętlach :).

Opublikowano

1. Po co losujesz liczby jak maja zostac wczytane a nie wylosowane ?

int wylosowanie()
{
 return rand();
}

 

2. Co to za warunki

 if (tab[i] = liczba) 

//---------------
//poprawnie

if (tab[i] == liczba) 
3. Tak w ogole to albo ja tego kodu nie ogarniam ,albo on jest bezsensu :P

 

@ Osobicie bym to w taki sposob rozwiazal






#include <iostream>
#include <ctime>
#include <cstdlib>
	using namespace std;
int main()
{   
srand(time(NULL));
   
int i=0,ile,wyl,l;
    
cout<<"Ile liczb wprowadzic : ";	
	cin>>ile;
	
int A[ile][2];
    
while(i<ile)
    {
    cout<<"Podaj "<<i+1<<" liczbe: ";
    	cin>>A[i][0];
        
	A[i++][1]=0;
    };
    
cout<<"\n------------------\nIle wylsowac : ";
	cin>>wyl;

if(wyl<=ile)
   	{
	i=0;
	while (i<wyl)
		{
		if(A[l=rand()%ile][1]==0)
			{
			cout<<"\n"<<++i<<" -> "<<A[l][0]; 
			A[l][1]=1;
			}	
		};
	}
		
return 0;
}

Zarchiwizowany

Ten temat przebywa obecnie w archiwum. Dodawanie nowych odpowiedzi zostało zablokowane.

×
×
  • Dodaj nową pozycję...