Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Lotto arvonta

Sivun loppuun

mandariini [27.10.2020 18:46:17]

#

Hei vaan,

Täsä lienee sata aloitusta, mutta en löytänyt vastausta juuri tähän kysymkseen. Onko mitään järkeä tehdä lottokonetta, jossa olennaisena pointtina on, ettei sama luku tule kahta kertaa, muulla kuin taulukolla?

Taulukotia en ole vielä opetellut, mutta tuntuu vähän ehkä monimutkaiselta tehdä pelkällä loopilla arpoen jokainen numero erikseen. Enkä ole edes varma, miten sekään tehdään.

Ideoita, mielipiteitä, apua?

peran [27.10.2020 19:57:08]

#

Muut "järkevät" vaihtoehdot ovat linkitetty lista ja binääripuu.

Ne eivät todellakaan ole helpompia, (ja eivät ehkä ole järkeviäkään).

Staattiset muuttujat eivät ole järkeviä.

Grez [27.10.2020 22:01:28]

#

Periaatteessahan voisi käyttää esim. 64-bittistä kokonaislukua. Sen voi toki sinänsä ajatella (64 bitin kokoiseksi) bittitaulukoksi.

Eli tyyliin:

long used = 0;
for (int i=0;i<7;i++) {
    int r = rand()%39;
    if ((1<<r)&used) {
		i--; //Uudestaan
	} else {
		cout << (r+1) << endl;
		used |= 1<<r;
	}
}

AtskaFin [27.10.2020 22:18:05]

#

Yksi helppo tapa on säilöä arvotut numerot set -rakenteessa.

#include <iostream>
#include <set>
#include <algorithm>

using namespace std;

/*
  * Palauttaa satunnaisen luvun väliltä a...b
  * Ei palauta kahta kertaa samaa numeroa
*/
set<int> s;
int uniqueRand(int a, int b) {
  while (true) {
    int rnd = rand() % (b-a) + a;

    if (!s.count(rnd)) {
      s.insert(rnd);
      return rnd;
    }
  }
}

int main() {
  // Arvotaan loton 7 numeroa
  for (int i = 0; i < 7; i++) {
    cout << uniqueRand(1, 40) << " ";
  }
}

jalski [27.10.2020 23:03:25]

#

Varmaan C++ vakio kirjastoista nyt löytyy joku valmis funktio, millä voi sekoittaa taulukon sisällön? Ja eipä tuo sekoitus nyt älyttömän vaikea itsekään ole toteuttaa.

Generoi taulukko, missä numerot 1 - 39. Sekoita taulukon sisältö ja lue taulukosta seitsemän ensimmäistä numeroa?

mandariini [28.10.2020 11:39:29]

#

Kiitos vastauksista. Olen ihan aloittelija vielä C++ kanssa, joten nämä erilaiset ideat on kyllä hyviä. Hahmottuu kokonaisuus ja se, että saman asian voi oikeasti tehdä monella tapaa - taito lienee selvittää, mikä niistä on paras ja toimivin.

AtskaFin kirjoitti:

(27.10.2020 22:18:05): Yksi helppo tapa on säilöä arvotut numerot set...

Tästä mä haluaisin vielä kysyä, kun tätä koodia yritän osata lukea. Mikä osuus tässä tekee sen, ettei sama luku tule kahta kertaa?

mandariini [28.10.2020 11:59:14]

#

Ehkä lienee helpompi laittaa koodinpätkä tähän:
Nyt ongelmana on, että tulostaa vain yhden numerot, eikä seitsemää. Ja lisähuomiona, että tulostaa aina luvun 3.

HUOM! Tässä käytän aliohjelmaa. Mainissa vain ktusutaan funktio lotto();

int lotto() {

	int a = 0;

	while (a < 7) {
		int numerot = rand() % 39 + 1;
		cout << numerot << endl;
		a++;

		if (!s.count(numerot)) {
			s.insert(numerot);
			return numerot;
		}

	}

}

Metabolix [28.10.2020 13:07:20]

#

Koodi tulostaa vain yhden numeron, koska heti ensimmäisellä kierroksella if-lause toteutuu ja sen sisällä return lopettaa funktion. Sinun ei ole varmaan mitään syytä käyttää return-riviä tässä, eli funktio voisi olla "void lotto" ilman return-riviä. Tämän jälkeen koodi toimiikin jo melkein oikein, paitsi että nyt tulostat luvun ja lasket sen a-laskuriin mukaan jo ennen if-lausetta, vaikka nämä pitäisi tehdä tietenkin vain if-lauseen toteutuessa. Lisäksi a-laskuri on turha, s voisi olla funktion sisällä ja s.size() kertoisi onnistuneesti arvottujen lukujen määrän.

Numero on aina sama, koska rand ei tuota satunnaislukuja vaan tietyllä kaavalla laskettavia pseudosatunnaislukuja (näennäisen satunnaisia lukuja) ja et aseta kaavalle mitään satunnaisempaa lähtöarvoa srand-funktiolla. Parempia satunnaislukuja saa C++:n uusilla satunnaisluokilla, ks. esimerkki:

#include <random>
#include <iostream>

int main() {
    std::random_device rd;  // Tästä saadaan hyvä satunnaisluku siemeneksi.
    std::mt19937 gen(rd()); // mt19937 on melko hyvä pseudosatunnaisgeneraattori.
    std::uniform_int_distribution<> distrib(1, 6); // Arvotaan kokonaislukuja 1-6.

    for (int n = 0; n < 10; ++n) {
        // Tässä haetaan generaattorilta satunnaisluku halutun jakauman mukaan.
        std::cout << distrib(gen) << ' ';
    }
    std::cout << '\n';
}

Sivun alkuun

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta