Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: C++: Korttipakan sekoitus ja satunnaisuus

Sivun loppuun

vehkis91 [01.07.2008 22:49:13]

#

Olen tekemässä Blackjack-korttipeliä ja olen miettinyt, että miten saisin koneen sekoittamaan kortit. Paremman puutteessa käytän suoraan satunaislukuja. Olen tallentanut kaikkien korttien arvot taulukkoon ja mietin pystynkö jotenkin sekoittamaan taulukon arvot keskenään?

Olipas sekaista... :S

Niin ja miten pystyn ottamaan satunaislukuja esim 1-10, ku nyt pystyn ottaan vaan 0-n?

Edit tuli typo aiheeseen, mut sitä ei pysty korjaamaan... (mod. korjasi...)

Antti Laaksonen [01.07.2008 22:56:47]

#

Kun korttien tiedot ovat taulukossa, voit sekoittaa pakan esim. arpomalla 1000 kertaa (muukin riittävän suuri määrä kelpaa) kaksi taulukon kohtaa ja vaihtamalla näissä kohdissa olevat kortit keskenään. Tämän jälkeen voit ottaa taulukosta kortteja järjestyksessä, ja ne tulevat kuin sekoitetusta pakasta.

Jos pystyt arpomaan satunnaisluvun väliltä 0 – n, valitse sitten n = 9 ja lisää tulokseen 1, niin saat satunnaisluvun väliltä 1 - 10.

vehkis91 [01.07.2008 23:05:33]

#

Ajattelin että onnistuisi jollakin ton tyylisellä koodilla... Voitteko kertoa,että miten tästä eteenpäin? Antti en ihan ymmmärtänyt tuota sinun vinkkiäsi.(Olen tyhmä)

Tämä koodi on pelkkä pohja johon olisi kiva saada neuvoja. (Ei todellisen pelin pohja...)

#include <iostream>
#include <time.h>

using namespace std;

//GLOBAALI
int kortit[52]={1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11,12,13,
                1,2,3,4,5,6,7,8,9,10,11,12,13,1,2,3,4,5,6,7,8,9,10,11,12,13};


int main()
{
 kortit[52]=satunaisLukuGeneraattori();


 return EXIT_SUCCESS;
}

int satunaisLukuGeneraattori()
{
    int luku;

    srand(time(0));

    luku=rand() % 52;

    return luku;
}

Sami [01.07.2008 23:09:52]

#

Monessa ohjelmointikielissä on jo valmiina shuffle-funktio, joka sekoittaa sille annetun taulukon tai listan alkiot satunnaiseen järjestykseen. Jos tällaista ei ole, niin sellainen on helppo tehdä:


Seuraavassa lista on taulukko, jossa on listankoko alkiota. randomint arpoo kokonaisluvun annetulta väliltä (mukaanluettuna päätepisteet) ja swap vaihtaa kaksi taulukon alkiota keskenään.

for (int i = 0; i < listankoko-1; ++i) {
  int rnd = randomint(i, listankoko-1)
  swap(lista, i, rnd)
}

Tämän jälkeen taulukon pitäisi olla satunnaisessa järjestyksessä (olettaen että satunnaislukugeneraattori palauttaa riittävän satunnaisia lukuja).

vehkis91 [01.07.2008 23:23:00]

#

Iskee täällaista herjaa:
C:\Users\Lartsu\Desktop\Programing\Harjoituksia\BlackJack\main.cpp In function `int sekoitaKortit()':
46 C:\Users\Lartsu\Desktop\Programing\Harjoituksia\BlackJack\main.cpp `randomint' undeclared (first use this function)
(Each undeclared identifier is reported only once for each function it appears in.)
47 C:\Users\Lartsu\Desktop\Programing\Harjoituksia\BlackJack\main.cpp no matching function for call to `swap(int[53], int&, int&)'

Tässä on se funktio:

int sekoitaKortit()
{
    for (int i = 0; i < KORTTIEN_LKM-1; ++i)
    {
        int rnd = randomint(i, KORTTIEN_LKM-1);
        swap(kortit, i, rnd);
    }

}//SekoitaKortit

EDIT: Ja kieli on c++ jos joku ei huomannut...

Sami [01.07.2008 23:26:30]

#

Noiden kahden funktion toteutus jätettiin kotitehtäväksi... Tai vaihtoehtoisesti etsiä jotkin niitä vastaavat, oikeasti toteutetut funktiot.

vehkis91 [01.07.2008 23:30:05]

#

Jaa, no sit mulla on jo toi toinen valmiina... Ni sit vaan toteuttamaan, kiitos vinkeistä. :D

Antti Laaksonen [01.07.2008 23:39:16]

#

Tuossa on vielä yksi esimerkki, josta on toivottavasti hyötyä:

#include <iostream>
#include <cstdlib>
#include <ctime>

int pakka[52];
int kohta = 0;

char nimet[4][10] = {"pata", "ruutu", "risti", "hertta"};

void aloitus(void) {
    int i;
    for (i = 0; i < 52; i++) {
        pakka[i] = i;
    }
}

void sekoitus(void) {
    int i, a, b, v;
    for (i = 0; i < 1000; i++) {
        a = rand() % 52;
        b = rand() % 52;
        v = pakka[a];
        pakka[a] = pakka[b];
        pakka[b] = v;
    }
    kohta = 0;
}

void nosta(int maara) {
    int i;
    std::cout << "Nostetaan " << maara << " korttia:" << std::endl;
    for (i = 0; i < maara; i++) {
        std::cout << nimet[pakka[kohta] / 13] << " ";
        std::cout << (pakka[kohta] % 13 + 1) << std::endl;
        kohta++;
        if (kohta == 52) kohta = 0;
    }
}

int main(void) {
    srand(time(NULL));
    aloitus();
    sekoitus();
    nosta(3);
    nosta(1);
    nosta(4);
    return 0;
}

Muuttujassa kohta lukee, missä kohtaa pakkaa mennään. Kortin nostossa siirrytään takaisin pakan alkuun, jos kortit loppuvat kesken. Kun kortti tallennetaan kokonaislukuna välillä 0 - 51, kortin värin (0 - 3) saa selville kaavalla (n / 13) ja kortin arvon (1 - 12) saa selville kaavalla (n % 13 + 1). Esim. jos värit ovat 0 = pata, 1 = ruutu, 2 = risti ja 3 = hertta, kortin 28 väri on risti (28 / 13 = 2,15) ja arvo on 3 (28 % 13 + 1 = 3).

vehkis91 [01.07.2008 23:53:32]

#

Kiitos tuosta on paljon hyötyä.

ps: luulin, että et osaa c++, mutta ihan hyvinhän toi näyttää menevän... ;)

Antti Laaksonen [01.07.2008 23:56:45]

#

vehkis91 kirjoitti:

ps: luulin, että et osaa c++, mutta ihan hyvinhän toi näyttää menevän... ;)

Salaisuus piilee siinä, että tuo koodi on oikeastaan C:tä.

Metabolix [01.07.2008 23:58:57]

#

Josko tämä antaisi jotain ajatuksia... Kirjoitusvirheistä en mene takuuseen, mutta C++-osaamisen kannalta suosittelen, että luet ajatuksella läpi koko koodin ja yrität ymmärtää, mitä tapahtuu. Funktiot (sekä omani että standardikirjaston) tekevät juurikin sitä, mitä niiden nimistä voi päätellä, joten ymmärtämisen ei pitäisi olla vaikeaa.

#include <vector>
#include <stack>
#include <algorithm>

class korttipakka {
  std::stack<int> kortit;
public:
  korttipakka(bool taysi = true) {
    if (taysi) {
      tayta();
    }
  }
  bool tyhja() {
    return kortit.empty();
  }
  int nosta() {
    if (tyhja()) {
      throw "Virhe! Ei voi nostaa tyhjästä pakasta!";
    }
    // Katsotaan, poistetaan ja palautetaan
    int kortti = kortit.top();
    kortit.pop();
    return kortti;
  }
  void lisaa(int kortti) {
    kortit.push(kortti);
  }
  void tayta() {
    while (!tyhja()) {
      nosta();
    }
    for (i = 0; i < 52; ++i) {
      lisaa(i);
    }
  }
  void sekoita() {
    std:vector<int> apukortit;
    while (!tyhja()) {
      apukortit.push_back(nosta());
    }
    std::random_shuffle(apukortit.begin(), apukortit.end());
    for (int i = 0; i < apukortit.size(); ++i) {
      lisaa(apukortit[i]);
    }
  }
};

korttipakka pakka;
pakka.sekoita();
while (!pakka.tyhja()) {
  std::cout << pakka.nosta() << std::endl;
}

vehkis91 [02.07.2008 00:01:06]

#

Tuokin lienee ihan hyvä, mutta kun en ymmärrä mitään STL:stä, niin en ymmärrä tota... :S
Opettelen STL:n kunhan saan rahat Hietasen kirjaan.

Edit: tai no ei tuo kyllä hirveän monimutkaiselta näytä, kun paneutuu ajatuksella...

Teuro [02.07.2008 14:29:39]

#

Metabolix hyvä vinkki jälleen kerran!

Ihan pieni lisäys voisi olla main funktio, jolla testata tuota luokkaa. Tosin se on helppo lisätä ja toimii kyllä.

[edit]
korjaus -> lisäys -sanamuodon muutos-
[/edit]

vehkis91 [02.07.2008 14:44:48]

#

Jos ei main()-funktiota osaa tehdä, niin tuskimpa silloin pystyy tekemään edes alkeellista peliä...(niinkuin tämä. ;D)


Sivun alkuun

Vastaus

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

Tietoa sivustosta