• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

Gra w kółko i krzyżyk

VPS Starter Arubacloud
+1 głos
2,420 wizyt
pytanie zadane 16 kwietnia 2018 w C i C++ przez macias17 Nowicjusz (190 p.)
edycja 16 kwietnia 2018 przez macias17
Witam!

Mam problem ze stworzeniem gry w kółko i krzyżyk. Nie wiem, jak w ogóle się za to zabrać. Takie oto zadanie znalazło się w książce Alexa Allaina "C++. Przewodnik dla początkujących" i brzmi ono następująco: Napisz grę w kółko i krzyżyk, w której dwie osoby grają przeciwko sobie. Jeśli to możliwe, użyj typu wyliczeniowego w celu przechowywania wartości pól planszy. Mniej więcej wiem, co to ten typ wyliczeniowy i na czym polega, ale nie mam pojęcia jak go wykorzystać oraz w czym mi pomoże. Dodam, że w momencie pojawienia się tego zadania w książce zostały przerobione już podstawy C++, instrukcje warunkowe, pętle, funkcje oraz instrukcje switch case wraz z typem wyliczeniowym.

Proszę o pomoc w zrozumieniu jak owe zadanie zrobić, gdyż nie zależy mi tylko na tym żeby zdobyć kod źródłowy i tyle, ponieważ chciałbym wiedzieć jak się za to zabrać i w przyszłości umieć taką grę napisać. Chciałbym również korzystać tylko z tych funkcji, które na ten moment znam z książki.

Mam świadomość, że tego typu pytania już się pojawiły na forum i przeczytałem je, lecz nie wyczerpują one moim zdaniem tematu. Po lekturze dalej nie wiem jak to zrobić, gdyż bardzo często był tam tylko podawany kod, a dokładnego wytłumaczenia nie znalazłem.

Z góry dziękuję!
komentarz 16 kwietnia 2018 przez ScriptyChris Mędrzec (190,190 p.)

Jaki konkretnie masz problem? Zapoznaj się z zasadami zadawania pytań. Podaj szczegóły problemu i pokaż kod.

komentarz 16 kwietnia 2018 przez macias17 Nowicjusz (190 p.)
Przypadkowo dodałem pytanie nie zawierając informacji, a w tym czasie je edytowałem, dlatego wyglądało to tak, a nie inaczej.
1
komentarz 16 kwietnia 2018 przez ScriptyChris Mędrzec (190,190 p.)

W kursie Mirosława Zelenta było Kółko i Krzyżyk - możesz zobaczyć na czym to polega i się wzorować.

https://www.youtube.com/watch?v=vd0zDG4vwOw

komentarz 17 kwietnia 2018 przez macias17 Nowicjusz (190 p.)
Dziękuję bardzo, w wolnej chwili na pewno obejrzę.

6 odpowiedzi

+1 głos
odpowiedź 16 kwietnia 2018 przez Beginer Pasjonat (22,110 p.)
komentarz 17 kwietnia 2018 przez macias17 Nowicjusz (190 p.)
Dzięki!
0 głosów
odpowiedź 16 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

Po prostu np.

enum Field{X=0, O=1};

i na podstawie tego sprawdzasz kto wygrał. 

komentarz 16 kwietnia 2018 przez macias17 Nowicjusz (190 p.)
A można poprosić jakieś dokładniejsze informacje? Jak zrobić całą resztę? Zależy mi również na wytłumaczeniu. Mam narysować planszę za pomocą cout'ów czy jest na to jakaś lepsza metoda? Jak nanosić na planszę znaki wprowadzane przez użytkowników?
0 głosów
odpowiedź 17 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)

1. Pole w tej grze może mieć w trakcie rozgrywki 3 stany:

    X - KRZYZYK

    O - KOLKO

    P - PUSTE

Stąd typ enum będzie posiadał także 3 wartości. Z racji tego że nie używasz zapewne standardu C++11 lub nowszego, zadeklarujesz ten typ tak:

typedef enum {
    PUSTE,
    KRZYZYK,
    KOLKO
} StanPola;

2. Plansza w tej grze, jest 3 x 3 potrzebujesz więc kontenera tych "enum'ów" który je przechowa. Lepiej jest użyć std::array ale znów... pewnie nie było. Pozostają tablice. Możesz zrobić ją tak:

StanPola * plansza = new StanPola[3][3];
//
// Obowiązkowo przez zakończeniem programu...
//
delete [] plansza;

3. Potrzebujesz funkcji które:

    - Wyczyszczą całą planszę czyli ustawią wszystkie pola na wartość PUSTE.

    - Wyświetlą całą planszę z użyciem std::cout jako znaczki ASCII

    - Sprawdzą czy w wierszu nie ma 3 takich samych stanów/symboli

    - Sprawdzą czy w kolumnie nie ma 3 takich samych stanów/symboli

    - Sprawdzą czy diagonalnie ("na skos") nie ma takich samych stanów/symboli.

    - Funkcji która obsłuży logikę gry prezentując np. tekst "Maćku, grasz X. Gdzie postawisz symbol? Oddziel spacją: "
       i Maciek wpisze: 3 3 

A reszta zależy jak grę będziesz chciał rozbudować. Czy będą uprzejme pytania o imię, zapis stanu gry, gra sieciowa, może gra z AI (algorytm jest prosty a gra zupełna)  ... :)

2
komentarz 17 kwietnia 2018 przez draghan VIP (106,230 p.)

Z racji tego że nie używasz zapewne standardu C++11 lub nowszego, zadeklarujesz ten typ tak:

typedef enum {

    PUSTE,

    KRZYZYK,

    KOLKO

} StanPola;

A dlaczego nie po prostu:

enum StanPola
{
    PUSTE,
    KRZYZYK,
    KOLKO
};

?

komentarz 17 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)
Dlaczego lepiej array zamiast tablicy?
komentarz 17 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)
A czytaj z uwagą. Napisałem że lepiej lecz zapewne będzie informacja "nie wie nie znam". To samo z enum class.
komentarz 17 kwietnia 2018 przez draghan VIP (106,230 p.)

To samo z enum class.

Wiem, że w standardzie języka < C++11 nie ma silnie typowanych enumów. Ale dlaczego używać do tego typedef?

komentarz 17 kwietnia 2018 przez Hiskiel Pasjonat (22,830 p.)

Chyba źle zrozumiałeś to zdanie.

Dlaczego? Lepiej array zamiast tablicy.

Olej, tutaj Twoja odpowiedź była by na miejscu. Ale ja zadałem pytanie

Dlaczego lepiej array zamiast tablicy? 

Swoją drogą, jak utworzyć array 3x3? 

komentarz 17 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)
edycja 17 kwietnia 2018 przez mokrowski

@draghan, w kilku kontekstach typedef pozwala uniknąć klepania niepotrzebnego słowa enum w starych i bardzo starych kompilatorach. Niestety jak napisałeś to jest tylko alias na typ enum i nie uruchamia żadnych mechanizmów ścisłego typowania. Dodatkowo (co nie jest wymaganiem tego projektu), jak zrobisz typedef, łatwiej integrować się z kodem w C. No i przyzwyczajenie z większych projektów gdzie IMHO łatwiej znaleźć typ. No ale tu każdy ma swoje przemyślenia... Ogólnie. Jak się da uciekać od enum "f Cee":)

komentarz 17 kwietnia 2018 przez mokrowski Mędrzec (155,460 p.)

Ok, moja wina.. odpisywanie w biegu... i to Ja nie doczytałem :) Przepraszam... 

Do sedna...

Dlaczego? Lepiej array zamiast tablicy.

std::array jest kontenerem zarządzającym cyklem życia danych. W momencie zniszczenia samego kontenera, zwalnia alokowaną pamięć na dane a w tablicy niestety robisz to ręcznie. Jeśli w programie z tablicą zostanie np. rzucony wyjątek, ryzykujesz że nieprawidłowa jego obsługa spowoduje wyciek pamięci. Z std::array zwijana ramka stosu zniszczy i poprawnie zdealokuje obiekt std:array. Jednocześnie std::array ma konieczność podania stałego rozmiaru i może stosować wewnętrzną optymalizację dostępu do tejże pamięci, posiada łatwe w użyciu iteratory.

Swoją drogą, jak utworzyć array 3x3? 

Ano można tak.. w przykładzie prosty int i już nie "siliłem się" na duszenie standardu poniżej C++11:

#include <iostream>
#include <array>
#include <iomanip>

int main() {
    // 2-wymiarowy std::array 3 x 3 z danymi int.
    // Dzięki {{0}} jednocześnie następuje zerowanie.
    std::array<std::array<int, 3>, 3> fields{{0}};
    // Jakiś dostęp... 
    fields[1][2] = 102;
    // Wyświetlenie... 
    for(const auto& row: fields) {
        for(const auto& field: row) {
            std::cout << std::setw(8) << field;
        }
        std::cout << '\n';
    }
}

 

komentarz 17 kwietnia 2018 przez macias17 Nowicjusz (190 p.)
Dziękuję bardzo za pomoc! W razie jakichkolwiek pytań będę pisał.
0 głosów
odpowiedź 2 lutego 2020 przez ciocialol Nowicjusz (180 p.)


#include <iostream>

using namespace std;

void maps();
void player_status();
bool end_game();
char tab[3][3] = {{'1','2','3'},{'4','5','6'},{'7','8','9'}};
int row, column;
char turn;
int choice;
bool draw = false;

int main()
{
    cout <<"Who starts? X/O: ";
    cin>>turn;

    while(end_game())
    {
    maps();
    player_status();
    end_game();
    }

    if(turn=='O' && draw==false)
    {
        cout <<"Player X wins!"<<endl;
    }
    else if(turn=='X' && draw==false)
    {
        cout <<"Player O wins!"<<endl;
    }
    else if((turn=='X' || turn=='O') && draw==true)
    {
        cout <<"DRAW!"<<endl;
    }


    return 0;
}

void maps()
{
    cout<<"\n\n\t\t\t  TIC TAC TOE";
    cout <<"\n\n";
    cout <<"\t\tPlayer 1 = 'X' // Player 2 = 'O'";
    cout <<"\n\n";
    cout <<endl<<"\t\t\t---------------";
    cout <<endl<<"\t\t\t| "<<tab[0][0]<<" |"<<"| "<<tab[0][1]<<" |"<<"| "<<tab[0][2]<<" |";
    cout <<endl<<"\t\t\t---------------";
    cout <<endl<<"\t\t\t| "<<tab[1][0]<<" |"<<"| "<<tab[1][1]<<" |"<<"| "<<tab[1][2]<<" |";
    cout <<endl<<"\t\t\t---------------";
    cout <<endl<<"\t\t\t| "<<tab[2][0]<<" |"<<"| "<<tab[2][1]<<" |"<<"| "<<tab[2][2]<<" |";
    cout <<endl<<"\t\t\t---------------";
    cout<<endl<<endl<<endl;
}

void player_status()
{

    if(turn == 'X')
    {
        cout <<"Player nr 1 with X symbol: "<<endl;

    }
    else if(turn == 'O')
    {
        cout <<"Player nr 2 with O symbol: "<<endl;
    }

    cin>>choice;

    switch(choice)
    {
        case 1: row = 0; column = 0; break;
        case 2: row = 0; column = 1; break;
        case 3: row = 0; column = 2; break;
        case 4: row = 1; column = 0; break;
        case 5: row = 1; column = 1; break;
        case 6: row = 1; column = 2; break;
        case 7: row = 2; column = 0; break;
        case 8: row = 2; column = 1; break;
        case 9: row = 2; column = 2; break;
        default: cout <<"Wrong number!"<<endl;
    }

    if(turn == 'X' && tab[row][column]!='X' && tab[row][column]!='O')
    {
        tab[row][column] = 'X';
        turn = 'O';
    }
    else if(turn == 'O' && tab[row][column]!= 'X' && tab[row][column]!= 'O')
    {
        tab[row][column] = 'O';
        turn = 'X';
    }
    else cout <<"This box is already filled, choose another one!"<<endl;

    maps();


}

bool end_game()
{

    //checking rows and columns
    for(int i=0; i<3; i++)
    {
        if(tab[i][0]==tab[i][1] && tab[i][0]==tab[i][2] || tab[0][i]==tab[1][i] && tab[0][i]==tab[2][i])
            return false;
    }

    //checking for diagonals

    if(tab[0][0]==tab[1][1] && tab[0][0]==tab[2][2] || tab[0][2]==tab[1][1] && tab[0][2]==tab[2][0])
        return false;

    //checking if the game is continous
    for(int i=0; i<3; i++)
    for(int j=0; j<3; j++)
    if(tab[i][j]!='X' && tab[i][j]!='O')
    return true;

    draw = true;
    return false;
}
komentarz 22 lutego 2020 przez macias17 Nowicjusz (190 p.)
Dziękuję bardzo za poświęcony czas. :)
0 głosów
odpowiedź 13 kwietnia 2021 przez Kamil Poszepczyński Nowicjusz (140 p.)


#include <iostream>
#include <string>

using namespace std;

void MenuGlowne()
{
    cout<<"\t\t\t\t\t#########################"<<endl;
    cout<<"\t\t\t\t\t#          Witaj !      #"<<endl;
    cout<<"\t\t\t\t\t#W grze kolko i Krzyzyk #"<<endl;
    cout<<"\t\t\t\t\t#########################"<<endl;
    cout<<"\t\t\t\t\t#########################"<<endl;
    cout<<"\t\t\t\t\t#########################"<<endl;
    cout<<"\t\t\t\t\t#      [1] Nowa gra     #"<<endl;
    cout<<"\t\t\t\t\t#      [2] Wyjscie      #"<<endl;
    cout<<"\t\t\t\t\t#########################"<<endl;
}

void plansza(char pole1, char pole2, char pole3, char pole4, char pole5, char pole6, char pole7, char pole8, char pole9)
{
    cout<<"\t\t\t\t\t"<<pole1<<"  | "<<pole2<<"  | "<<pole3<<endl;
    cout<<"\t\t\t\t\t"<<"---+----+---"<<endl;
    cout<<"\t\t\t\t\t"<<pole4<<"  | "<<pole5<<"  | "<<pole6<<endl;
    cout<<"\t\t\t\t\t"<<"---+----+---"<<endl;
    cout<<"\t\t\t\t\t"<<pole7<<"  | "<<pole8<<"  | "<<pole9<<endl<<endl;

    cout<<endl<<endl;
    cout<<"\t\t\t\t\t Opis Pol: "<<endl<<endl;
    cout<<"\t\t\t\t\t"<<"1"<<"  | "<<"2"<<"  | "<<"3"<<endl;
    cout<<"\t\t\t\t\t"<<"---+----+---"<<endl;
    cout<<"\t\t\t\t\t"<<"4"<<"  | "<<"5"<<"  | "<<"6"<<endl;
    cout<<"\t\t\t\t\t"<<"---+----+---"<<endl;
    cout<<"\t\t\t\t\t"<<"7"<<"  | "<<"8"<<"  | "<<"9"<<endl;
}

void WyborKolka_Krzyzyk(int wybor)
{
    cout<<"Wybrales Pole "<<wybor<<" podaj jaka figura tam bedzie: "<<endl;
    cout<<"[1] Kolko"<<endl;
    cout<<"[2] Krzyzyk"<<endl;
}




bool SprawdzenieWygranej(char pole1, char pole2, char pole3, char pole4, char pole5, char pole6, char pole7, char pole8, char pole9)
{
    if(pole1 == 'X' && pole2 == 'X' && pole3 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole4 == 'X' && pole5 == 'X' && pole6 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole7 == 'X' && pole8 == 'X' && pole9 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole1 == 'X' && pole4 == 'X' && pole7 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole2 == 'X' && pole5 == 'X' && pole8 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole3 == 'X' && pole6 == 'X' && pole9 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole1 == 'X' && pole5 == 'X' && pole9 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }
    if(pole3 == 'X' && pole5 == 'X' && pole7 == 'X')
        {
        cout<<"Wygrana gracza od 'X'"<<endl;
        return true;
        }


    if(pole1 == 'O' && pole2 == 'O' && pole3 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole4 == 'O' && pole5 == 'O' && pole6 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole7 == 'O' && pole8 == 'O' && pole9 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole1 == 'O' && pole4 == 'O' && pole7 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole2 == 'O' && pole5 == 'O' && pole8 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole3 == 'O' && pole6 == 'O' && pole9 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole1 == 'O' && pole5 == 'O' && pole9 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
    if(pole3 == 'O' && pole5 == 'O' && pole7 == 'O')
        {
        cout<<"Wygrana gracza od 'O'"<<endl;
        return true;
        }
}










int main()
{
    char pole1 = ' ',pole2 = ' ',pole3 = ' ',pole4 = ' ',pole5 = ' ',pole6 = ' ',pole7 = ' ',pole8 = ' ',pole9 = ' ';
    enum KolkoKrzyzyk {Puste,O,X};
    while(true)
    {
    MenuGlowne();
    int WybormenuGlowne;
    cin>>WybormenuGlowne;
        if(WybormenuGlowne == 1)
        {
        pole1 = ' ',pole2 = ' ',pole3 = ' ',pole4 = ' ',pole5 = ' ',pole6 = ' ',pole7 = ' ',pole8 = ' ',pole9 = ' ';
    plansza(pole1,pole2,pole3,pole4,pole5,pole6,pole7,pole8,pole9);
    while(SprawdzenieWygranej(pole1,pole2,pole3,pole4,pole5,pole6,pole7,pole8,pole9) != true)
    {
    cout<<"\t\t\t\tPodaj Pole na ktorym chcesz postawic figure: "<<endl;
    int wybor;
    cin>>wybor;
    int WyborFigury;
    switch(wybor)
    {
    case 1:
        {
            WyborKolka_Krzyzyk(wybor);
            cin>>WyborFigury;
            switch(WyborFigury)
            {
            case 1:
                pole1 = 'O';
                break;
            case 2:
                pole1 = 'X';
                break;
            default:
                break;
            }
        break;
        }
    case 2:
        {
            WyborKolka_Krzyzyk(wybor);
            cin>>WyborFigury;
            switch(WyborFigury)
            {
            case 1:
                pole2 = 'O';
                break;
            case 2:
                pole2 = 'X';
                break;
            default:
                break;
            }
        break;
        }
    case 3:
        {
            WyborKolka_Krzyzyk(wybor);
            cin>>WyborFigury;
                switch(WyborFigury)
                {
                case 1:
                    pole3 = 'O';
                    break;
                case 2:
                    pole3 = 'X';
                    break;
                default:
                    break;
                }
        break;
        }
    case 4:
        {
        WyborKolka_Krzyzyk(wybor);
        cin>>WyborFigury;
            switch(WyborFigury)
            {
                case 1:
                    pole4 = 'O';
                    break;
                case 2:
                    pole4 = 'X';
                    break;
                default:
                    break;
            }
        break;
        }
    case 5:
        {
        WyborKolka_Krzyzyk(wybor);
        cin>>WyborFigury;
            switch(WyborFigury)
                {
                case 1:
                    pole5 = 'O';
                    break;
                case 2:
                    pole5 = 'X';
                    break;
                default:
                    break;
                }
        break;
        }
    case 6:
    {
    WyborKolka_Krzyzyk(wybor);
    cin>>WyborFigury;
        switch(WyborFigury)
            {
            case 1:
                pole6 = 'O';
                break;
            case 2:
                pole6 = 'X';
                break;
            default:
                break;
            }
    break;
    }
    case 7:
    {
    WyborKolka_Krzyzyk(wybor);
    cin>>WyborFigury;
        switch(WyborFigury)
            {
            case 1:
                pole7 = 'O';
                break;
            case 2:
                pole7 = 'X';
                break;
            default:
                break;
            }
    break;
    }
    case 8:
    {
    WyborKolka_Krzyzyk(wybor);
    cin>>WyborFigury;
        switch(WyborFigury)
            {
            case 1:
                pole8 = 'O';
                break;
            case 2:
                pole8 = 'X';
                break;
            default:
                break;
            }
    break;
    }
    case 9:
    {
    WyborKolka_Krzyzyk(wybor);
    cin>>WyborFigury;
        switch(WyborFigury)
            {
            case 1:
                pole9 = 'O';
                break;
            case 2:
                pole9 = 'X';
                break;
            default:
                break;
            }
    break;
    }
        default:
        break;
    }
    plansza(pole1,pole2,pole3,pole4,pole5,pole6,pole7,pole8,pole9);

    }
        }
    else if(WybormenuGlowne == 2)
        break;
}
    return 0;
}
.

Mój kod co do tego zadania - sam się jeszcze uczę więc może on zawierać błędy.

0 głosów
odpowiedź 15 kwietnia 2021 przez mkarolm Początkujący (290 p.)
Polecam zajrzeć do książki "Od zera do gier kodera" gdzie dokładnie omówiony jest taki projekt coś koło 150 strony. Po przeczytaniu na pewno zrozumiesz jak działa cały mechanizm krok po kroku.

Podobne pytania

+1 głos
2 odpowiedzi 1,035 wizyt
0 głosów
0 odpowiedzi 487 wizyt
pytanie zadane 26 października 2019 w JavaScript przez Kuba Romańczuk Początkujący (320 p.)
0 głosów
1 odpowiedź 913 wizyt
pytanie zadane 16 stycznia 2018 w C i C++ przez BinaryMan Stary wyjadacz (12,620 p.)

92,452 zapytań

141,262 odpowiedzi

319,085 komentarzy

61,854 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...