Gra karciana oczko - sztuczna inteligencja

0

Witam muszę napisać program "Gra karciana oczko - sztuczna inteligencja". A więc karty od 9,10,Jopek,Dama,Król,As.

Dziewiątka – 0 pkt.
Dziesiątka – 10 pkt.
Walet – 2 pkt.
Dama – 3 pkt.
Król – 4 pkt.
As – 11 pkt.

Gracz ma grać z komputerem który zapamiętuje jakie karty szły(czyli ma wiedzieć jakie karty zostały w talii). Karty w danym rozdaniu nie mogą się powtarzać ( co jest oczywiste ). No i komputer korzystając z wiedzy jakie karty są jeszcze w talii ma określić czy dobrać kartę czy nie. A i jeszcze jeśli ktoś wylosuje 2 asy to ma 21 punktów czyli oczko.

Program najlepiej jakby byl C++, ale jak byłby w pascalu to tez nie bedzie tragedii (chyba ograne)
Proszę o pomoc :)

0

Komputer widzi ile ma człowiek, i widzi ile ma aktualnie on sam, jeżeli bez dobierania wygrywa to nie nigdy nie dobiera, jeżeli bez dobierania przegrywa to zawsze dobiera, koniec kropka.

0

Program najlepiej jakby byl C++, ale jak byłby w pascalu to tez nie bedzie tragedii (chyba ograne)
:O
Kpisz sobie? Takie rzeczy to do działu praca. Myślisz, że komuś się chcę siedzieć nad tym x czasu żebyś Ty zrozumiał? Jeszcze raz powtórze. Kpisz sobie?

Powiedz z czym konkretnie masz problem to sądzę, że dostaniesz pomoc.

0

no głównie to chodzi mi o algorytm tej "inteligencji" komputera. Fasadin Już zaraz kpisz :P To jest forum a wiec zapytać można (" Kto pyta nie błądzi"). Jak nie masz czasu to ja to rozumiem sam go za wiele nie mam, choć może znajdzie się ktoś kto ma czas lub ktoś kto już z tym programem się borykał :)

0

@micrus, przecież dostałeś algorytm trzy dni temu:

_13th_Dragon napisał(a):

Komputer widzi ile ma człowiek, i widzi ile ma aktualnie on sam, jeżeli bez dobierania wygrywa to nigdy nie dobiera, jeżeli bez dobierania przegrywa to zawsze dobiera, koniec kropka.
Wraz z uwagą od @fasadin: -
w blackjacku krupier nie może grać jeżeli ma co najmniej 16 (z tego co pamietam)"

  • masz pełny komplet.
0

dobra sprobuje cos z tego wykminic :) ale czy cos z tego bedzie to nie wiem :P Jak cos nie bede wiedział to bede pytał :D W tygodniu jakos sie chyba za to wezme :)

0

A więc tak dzisiaj dopiero zabrałem się za pisanie tego diabelskiego programu :P Aktualnie moja praca stoi na takim etapie:

 #include <cstdlib>
#include <iostream>

using namespace std;
void cards (int karty[])
{
    karty [0]= 0;
    karty [1]= 10;
    karty [2]= 2;
    karty [3]= 3;
    karty [4]= 4;
    karty [5]= 11;
    karty [6]= 0;
    karty [7]= 10;
    karty [8]= 2;
    karty [9]= 3;
    karty [10]= 4;
    karty [11]= 11;
    karty [12]= 0;
    karty [13]= 10;
    karty [14]= 2;
    karty [15]= 3;
    karty [16]= 4;
    karty [17]= 11;
    karty [18]= 0;
    karty [19]= 10;
    karty [20]= 2;
    karty [21]= 3;
    karty [22]= 4;
    karty [23]= 11;
}
bool czyBylaWylosowana( int iLiczba, int tab[], int ile )
{
    if( ile <= 0 )
         return false;
   
    int i = 0;
    do
    {
        if( tab[ i ] == iLiczba )
             return true;
       
        i++;
    } while( i < ile );
   
    return false;
}

int wylosuj()
{
    return( rand() % 24 );
}

int main(int argc, char *argv[])
{
    srand( time( NULL ) );
    int liczba = 0;
    int wylosowanych = 0;
    int sumakomp = 0;
    int sumakrupier = 0;
    int card[24];
    string wybor;
    cards(card);
    cout << "Losuje komputer" << endl;
    do {
    liczba = wylosuj();
    cout << "wylosowana liczba: " << liczba << endl;
    if( czyBylaWylosowana( liczba, card , wylosowanych ) == false )
        {
            sumakomp= sumakomp + card[liczba];
            cout << "Aktualna ilosc oczek: " << sumakomp << endl;
            if (sumakomp > 21)
            {
                         cout << "Komputer przegral!!" << endl;
                         break;
            }
            if (sumakomp == 21)
            {
                         cout << "Komputer wygral !!" << endl;
                         break;
            }
            
            wylosowanych++;
        }
        } while (sumakomp < 17);
        cout << endl << "Losuje krupier" << endl;
    do {
    liczba = wylosuj();
    if( czyBylaWylosowana( liczba, card , wylosowanych ) == false )
        {
            sumakrupier= sumakrupier + card[liczba];
            cout << "Aktualna ilosc oczek: " << sumakrupier << endl;
            if (sumakrupier > 21)
            {
                         cout << "Krupier przegral!!" << endl;
                         break;
            }
            if (sumakrupier == 21)
            {
                         cout << "Krupier wygral !!" << endl;
                         break;
            }
            
            wylosowanych++;
            cout << "Czy dobrac karte?" << endl;
            cin >> wybor;
        }
        } while (wybor == "t");
    system("PAUSE");
    return EXIT_SUCCESS;
}

i pojawia się kilka pytań.

  1. Zastanawiam się jak zrobić aby gra toczyła się aż do skończenia talii. Pomyślałem że może stworzyć drugą tablicę i zapisywać w niej liczby wylosowane i jakąś funkcją np sprawdzać czy w tablicy znajduje się mniej niż 20 kart. tablica dala by mi także wgląd na losowane liczby.
    2.Jak sprawdzić czy gracz nie wylosował dwóch "11" jak się wylosuje dwie 11 to jest oczko ( pomimo że suma daje wynik 22)
  2. Co myślicie o tej metodzie sprawdzania powtórzeń?? Bo mam takie wrażenie jakby ona nie działała prawidłowo. Pomyślałem że można by było skorzystać z takiej dodatkowej tabeli o której pisałem w punkcie 1. I po prostu wylosowaną liczbę porównywać z dodatkową tablicą czy taka liczba już się w niej nie znajduje.
2

kod użytkownika @shalom, udostępniany na tym forum milion razy..

#include <iostream>
#include <vector>
#include <ctime>
using namespace std;
 
class Card
  {
  private:
    int value;
    string name;
    string color;
  public:
    Card(int v, string n, string c):value(v),name(n),color(c) {}
    int getValue()
    {
      return value;
    }
    string getName()
    {
      return name;
    }
    string getColor()
    {
      return color;
    }
    friend ostream& operator<<(ostream& strumien, Card c)
    {
      strumien<<c.getName()<<" "<<c.getColor();
      return strumien;
    }
  };
 
class Talia
  {
  private:
    vector<Card> talia;
  public:
    void add(Card c) //dodawania karty do talii
    {
      talia.push_back(c);
    }
    Card popCard() //wyciąganie karty z talii
    {
      srand(time(0));
      int index = rand()%talia.size();
      Card tmp = talia[index];
      talia[index] = talia.back();
      talia.pop_back();
      return tmp;
    }
    void createFull()
    {
      string kolory[4]={"kier","karo","pik","trefl"};
      string figury[13]={"2","3","4","5","6","7","8","9","10","Walet","Dama","Krol","As"}; //można by tu dla 2-10 użyć sstream, ale nie chce mieszać
      for (int i=0;i<4;i++)
        {
          for (int j=0;j<9;j++) //2-10
            {
              Card tmp(j+2,figury[j],kolory[i]); //generujemy kartę
              talia.push_back(tmp); //dodajemy do talii
            }
          for (int j=9;j<12;j++) //walet, dama, krol
            {
              Card tmp(j-7,figury[j],kolory[i]); //generujemy kartę
              talia.push_back(tmp); //dodajemy do talii
            }
          Card tmp(11,figury[12],kolory[i]); //as
          talia.push_back(tmp); //dodajemy do talii
        }
    }
    int getValue() //funkcja zwraca wartość wszystkich kart w talii
    {
      int sum = 0;
      for (int i =0; i<talia.size();i++)
        sum+=talia[i].getValue();
      return sum;
    }
    bool empty() const
      {
        return talia.empty();
      }
  };
 
int main()
{
  Talia talia, gracz1, gracz2;
  talia.createFull();
  // i może robić na przykład
  gracz1.add(talia.popCard());
  return 0;
}
8

edit: haha spóźniłem się z wklejeniem własnego kodu :D

0

No dobra chopaki , jest problem nie działa mi to i ni hu..hu nie wiem dlaczego. Dodam że korzystam z Dev C++.

Talia talia, gracz1, gracz2;
zastanawia mnie ta linijka w tym kodzie.

2
micrus napisał(a):

Dodam że korzystam z Dev C++.

A po co komputera uzywasz? Przeciez masz kartke i dlugopis. Co ja gadam, kawalek drewna i kawalek kamyka wystarczy do pisania przeciez.
Ile razy mozna mowic, ze to IDE jest nierozwijane od X lat i nie nalezy go uzywac.

0

http://ideone.com/6QVHBa
dodaj tam include <cstdlib> bo gdzieś go wcięło w tym kodzie powyżej.
Poza tym nie wiem co cię zastanawia w podanej linijce. Ot każdy gracz ma swoją "talię" czyli pewne karty w ręce.

0
n0name_l napisał(a):
micrus napisał(a):

Dodam że korzystam z Dev C++.

A po co komputera uzywasz? Przeciez masz kartke i dlugopis. Co ja gadam, kawalek drewna i kawalek kamyka wystarczy do pisania przeciez.
Ile razy mozna mowic, ze to IDE jest nierozwijane od X lat i nie nalezy go uzywac.

Spokojnie bez nerwów. jestem początkujący i nie mam rozeznania w programach. Kiedyś w technikum go używalismy to go zainstalowałem :P A zamiast sie denerwować to moglbyś napisać jaki program zainstalować :)

1

Zamiast prosić o gotowe, mógłbyś poszukać sam.
Code::Blocks zainstaluj.

0

Proszę jeszcze o podpowiedz jak tworzę do tego pragramu projekt (console application) to jaki mam kompilator wybrać?? Przepraszam że zadaje takie "trudne" pytania ale jestem zielony w tym programie code::blocks :P Nie ciśnijcie mnie za to pytanie :P

0

Dziekuje nieznajomy :) Kompilator działa. Natomiast po wklejeniu powyższego kodu, skompilowaniu i odpaleniu nic się nie dzieje :P

0

No a co niby się ma dziać? Przecież musisz napisać logikę gry która cię interesuje. To co masz tutaj podane to jest są tylko klasy związane z kartami i taliami, nie żadna konkretna gra. Jak chcesz oczko (ta gra w oczko rozegra sie oczywście "sama" bo to tylko przykład) to np.:

    Talia talia = new Deck();
    Talia gracz1 = new Deck();
    Talia gracz2 = new Deck();
    talia.createFull();

    while ((gracz1.getValue() <= 21) && (gracz2.getValue() <= 21)) {
      gracz1.add(talia.popCard());
      if (gracz1.getValue() <= 21) {
        gracz2.add(talia.popCard());
      }
    }
//a tutaj sprawdzasz sobie ile punktów który ma żeby stwierdzić kto wygrał
0

Shalom widzę kocur jesteś w programowaniu :P Ja to najpierw poduczę sie jak te klasy działają i jak z nich korzystać i wtedy sprubuję to ogarnąć :P a może shalom znasz jakieś strony co jest dobrze wytłumaczone. Bo ja sobie robie ten kurs
http://cpp0x.pl/kursy/Kurs-C++/Dodatkowe-materialy/297

0

Powiem szczerze ze cieżko jest mi ogarnać ten program. Shalom po wpisanu w glowny blok tego co podales nadal program nie reaguje. I teraz jeszcze jedno pytanie czy tym moim sposobem (łopatologicznym i z epoki kamieniołomów) da rade zrobić taki program?? Bo ja z tymi klasami chyba nie dam sobie rady... :P

1

Tamten kod nie powinien sie nawet skompilować, bo był tam błąd ;]
Czy twoim sposobem da się to zrobić? Da się. Tak jak można policzyć 100*5 poprzez dodanie stu 5. Pytanie tylko czy wolisz jednak zrobić to jak człowiek... Nie powinno sie programować póki nie umie się podstaw. Składnia języka to są podstawy.
Żeby nie umieć skorzystać z gotowca? Ja bym zastanowił czy programowanie to faktycznie jest coś dla ciebie...

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

class Card
{
private:
    int value;
    string name;
    string color;
public:
    Card(int v, string n, string c):value(v),name(n),color(c) {}
    int getValue()
    {
        return value;
    }
    string getName()
    {
        return name;
    }
    string getColor()
    {
        return color;
    }
    friend ostream& operator<<(ostream& strumien, Card c)
    {
        strumien<<c.getName()<<" "<<c.getColor();
        return strumien;
    }
};

class Deck
{
private:
    vector<Card> talia;
public:
    void add(Card c)
    {
        talia.push_back(c);
    }
    Card popCard()
    {
        int index = rand()%talia.size();
        Card tmp = talia[index];
        talia[index] = talia.back();
        talia.pop_back();
        return tmp;
    }
    void createFull()
    {
        string kolory[4]= {"kier","karo","pik","trefl"};
        string figury[13]= {"2","3","4","5","6","7","8","9","10","Walet","Dama","Krol","As"};
        for (int i=0; i<4; i++)
        {
            for (int j=0; j<9; j++)
            {
                Card tmp(j+2,figury[j],kolory[i]);
                talia.push_back(tmp);
            }
            for (int j=9; j<12; j++)
            {
                Card tmp(j-7,figury[j],kolory[i]);
                talia.push_back(tmp);
            }
            Card tmp(11,figury[12],kolory[i]);
            talia.push_back(tmp);
        }
    }
    int getValue()
    {
        int sum = 0;
        for (unsigned i =0; i<talia.size(); i++)
            sum+=talia[i].getValue();
        return sum;
    }
    bool empty() const
    {
        return talia.empty();
    }
};

int main()
{
    srand(time(0));
    Deck talia, gracz1, gracz2;
    talia.createFull();
    while ((gracz1.getValue() <= 21) && (gracz2.getValue() <= 21))
    {
        Card c = talia.popCard();
        cout<<"Gracz 1 wylosowal "<<c<<endl;
        gracz1.add(c);
        if (gracz1.getValue() <= 21)
        {
            c = talia.popCard();
            cout<<"Gracz 2 wylosowal "<<c<<endl;
            gracz2.add(c);
        }
    }
    cout<<"Punkty gracza 1 = "<<gracz1.getValue()<<endl;
    cout<<"Punkty gracza 2 = "<<gracz2.getValue()<<endl;
    return 0;
}
0

Ja wiem że programowanie nie jest dla mnie dlatego poszedłem na sieci komputerowe :P No ale niestety trafił mi sie taki przedmiot ( nie wiem po co w ogole jest on na mojej specjalizacji :P ) No i jeszcze trafił się profesorek starej daty i on nie rozumie że my programowanie omijamy szerokim łukiem :P i tak oto trafiłem na to forum :)

0

I uważasz ze jako sieciowiec nie będziesz musiał umieć programować? Współczuje ci w takim razie, bo mocno się zdziwisz, jak na rozmowie kwalifikacyjnej będą od ciebie wymagali dobrej znajomości programowania w bashu i pythonie na przykład. Tym bardziej będzie to bolesne jeśli teraz olewasz naukę podstaw programowania...

0

No to powiem tak teraz to mnie załamałeś :P Znalazłem sie w czarnej dup.... :P Pozostaje mi tylko jedno.. uczyć sie programowania :( Ale wiem tez że co mnie nie zabije to mnie wzmocni :) Będę musiał przysiąść sam do jakiś kursów i robić po kolei przykłady...

 class Card
{
private:
    int value;
    string name;
    string color;
public:
    Card(int v, string n, string c):value(v),name(n),color(c) {} // Ta linijka pozwala na wyciągniecie danych z sekcji private??
   
 int getValue() // Tu funkcje zwracające wartości
    {
        return value;
    }
    string getName()
    {
        return name;
    }
    string getColor()
    {
        return color;
    }
    friend ostream& operator<<(ostream& strumien, Card c) // a czy ta linijka ma też ma za zadanie pozwolić wyciągnąć dane z sekcji private??
    {
        strumien<<c.getName()<<" "<<c.getColor(); // Łączy figurę i kolor w jeden srtumień (w jedna nazwę??)
        return strumien;
    }
1

Ta linijka pozwala na wyciągniecie danych z sekcji private??

ani trochę bo to jest konstruktor -> ta linijka odpowiada za stworzenie obiektu Card z podanymi parametrami.

a czy ta linijka ma też ma za zadanie pozwolić wyciągnąć dane z sekcji private??

Ani trochę bo jak widzisz ta linijka zwraca strumień a nie żadne wartości. Ta funkcja służy do wypisania karty na ekran.

Łączy figurę i kolor w jeden srtumień (w jedna nazwę??)

Ani trochę. Po prostu przekazujemy do jakiegoś strumienia (pewnie cout albo ofstream) nazwę karty oraz jej kolor.

0
class Deck
{
private:
    vector<Card> talia; // vector czyli tablica która może zmieniac rozmiar??
public:
    void add(Card c) //dodawania karty do talii
    {
        talia.push_back(c); //push_back Dodaje nowy element na końcu wektora.
    }
    Card popCard() //wyciąganie karty z talii
    {
        int index = rand()%talia.size(); // generuje liczbe z zakresu równego ilosci kart w talii
        Card tmp = talia[index]; // zmiennej tmp przypisany numer karty w tablicy
        talia[index] = talia.back();// do tablicy talia o numerze [indeks] zostaje przypisany ostatni element wektora.
        talia.pop_back();// usuwa ostatni element wektora
        return tmp;
    }
    void createFull()
    {
        string kolory[4]= {"kier","karo","pik","trefl"}; // tablica kolorów
        string figury[13]= {"2","3","4","5","6","7","8","9","10","Walet","Dama","Krol","As"}; // tablica figur
        //można by tu dla 2-10 użyć sstream, ale nie chce mieszać
        for (int i=0; i<4; i++)// generowanie talii do gry.
        {
            for (int j=0; j<9; j++) //2-10
            {
                Card tmp(j+2,figury[j],kolory[i]); //generujemy kartę
              talia.push_back(tmp); //dodajemy do talii
            }
          for (int j=9;j<12;j++) //walet, dama, krol
            {
              Card tmp(j-7,figury[j],kolory[i]); //generujemy kartę
              talia.push_back(tmp); //dodajemy do talii
            }
          Card tmp(11,figury[12],kolory[i]); //as
          talia.push_back(tmp); //dodajemy do talii
        }
    }
    int getValue() //funkcja zwraca wartość wszystkich kart w talii
    {
        int sum = 0;
        for (unsigned i =0; i<talia.size(); i++)  // co to daje że zmienna i jest insigned??
            sum+=talia[i].getValue();  // sumowanie kart w talii
        return sum;
    }
    bool empty() const
    {
        return talia.empty(); //sprawdza czy wektor jest pusty
    }
};

int main()
{
    srand(time(0));
    Deck talia, gracz1, gracz2; //każdy gracz ma swoją "talię" czyli pewne karty w ręce. 
    talia.createFull(); // tworzy talie z której gracze beda dobierali karty 
    while ((gracz1.getValue() <= 21) && (gracz2.getValue() <= 21))
    {
        Card c = talia.popCard(); // do zmiennej c zostaje przypisana wylosowana karta
        cout<<"Gracz 1 wylosowal "<<c<<endl;
        gracz1.add(c); // dodanie wylosowaniej karty do talii gracza 1
        if (gracz1.getValue() <= 21)
        {
            c = talia.popCard(); // do zmiennej c zostaje przypisana wylosowana karta
            cout<<"Gracz 2 wylosowal "<<c<<endl;
            gracz2.add(c);// dodanie wylosowaniej karty do talii gracza 2
        }
    }
    cout<<"Punkty gracza 1 = "<<gracz1.getValue()<<endl; // wypisuje zdobyte punkty 
    cout<<"Punkty gracza 2 = "<<gracz2.getValue()<<endl;
    return 0;
}
 
1

zmiennej tmp przypisany numer karty w tablicy

Nie, przecież widzisz chyba że przypisujemy tam KARTĘ a nie żaden numer
Poza tym nie rozpisuj tego po linijce tylko spróbuj zrozumień. popCard() działa tak, że podmienia wylosowaną kartę z kartą z końca (tzn przedstawia te dwie karty miejscami, tak że kartę wylosowana mamy na końcu tablicy) a potem usuwa kartę z końca tablicy (czyli tą którą wylosowaliśmy) i ją zwraca. Czemu tak? Bo usuwanie ze środka wektora jest kosztowne, bo trzeba "poprzesuwać" wszystkie elementy tablicy żeby zapełnić lukę. Usuwanie z końca jest łatwiejsze.

Zmienna unsigned to taka która przyjmujem wartości z zakresu 0..N, tzn nie przyjmuje wartości ujemnych. Tutaj to tylko kosmetyka.

0

sorry z tym tmp pojechałem po całości :/ nie wiem dlaczego taką głupotę napisałem :/ Jak byk jest napisane :P
czyli tak losowany jest numer indeksu, później to zmiennej tmp zapisywana jest karta wylosowana (i ona wychodzi z funkcji), później żeby usunąć ta wylosowana kartę z tej talii z której dobieramy przesuwamy kartę wylosowaną na koniec wektora i dopiero wtedy ją usuwamy tak??

0

Czyli ta funkcja pop_back - najpierw usuwa ostatni element i redukuje wielkość zbiornika(tablicy) o 1??
Removes the last element in the vector, effectively reducing the container size by one.

Jak napisać żeby program wykonywał się aż do momentu kiedy talia się skończy?? Próbowałem tego, ale program się nie zatrzymywał... tak jakby talia się nie kończyła...

int main()
{
    srand(time(0));
    Deck talia, gracz1, gracz2; //każdy gracz ma swoją "talię" czyli pewne karty w ręce.
    talia.createFull();// tworzy talie z której gracze beda dobierali karty
    do{
    while ((gracz1.getValue() <= 21) && (gracz2.getValue() <= 21))
    {
        Card c = talia.popCard(); // do zmiennej c zostaje przypisana wylosowana karta
        cout<<"Gracz 1 wylosowal "<<c<<endl;
        gracz1.add(c); // dodanie wylosowaniej karty do talii gracza 1
        if (gracz1.getValue() <= 21)
        {
            c = talia.popCard(); // do zmiennej c zostaje przypisana wylosowana karta
            cout<<"Gracz 2 wylosowal "<<c<<endl;
            gracz2.add(c);// dodanie wylosowaniej karty do talii gracza 2
        }
    }
    cout<<"Punkty gracza 1 = "<<gracz1.getValue()<<endl; // wypisuje zdobyte punkty
    cout<<"Punkty gracza 2 = "<<gracz2.getValue()<<endl;
    }
    while (talia.empty() == false );
    return 0;
}
 
0

A moze warto zrozumieć co piszesz a nie pisać na pałę? Przecież widzisz że wewnętrzne pętle zostaną przerwane jeśli któryś z graczy będzie miał w ręce więcej iż 21 (bo tak działa oczko...) i wstawienie jeszcze jednej pętli dookoła tego nie zmieni. Jak chcesz żeby gracze dobierali karty aż talia sie nie skończy to wystarczy ci:

while(!talia.empty()){
  gracz1.add(talia.popCard());
  if(!talia.empty()){
    gracz2.add(talia.popCard());
  }
}
//voila, talia opróżniona
0

jak wyczyścic wektor gracz1??

bo wywnioskowałem że program działa błędnie bo wyświetla (zapętla się) cały czas wynik z zakończonej 1 rundy, gdyż np jeden z graczy ma wiecej niż 21 oczek. Także muszę wyczyścić talie obu graczy żeby to działało... Tzn tak myślę że będzie działało :P Kombinowałem z np. gracz1.clear(); <- ale to mi za bardzo nie działa bo wyswietla że w klasie deck nie ma zdeklarowanej funkcji clear.

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