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

Kółko i krzyżyk 6x6/pentago funkcja ruchu

Object Storage Arubacloud
0 głosów
600 wizyt
pytanie zadane 30 listopada 2021 w C i C++ przez niezalogowany

Na projekt mam za zadanie napisać grę konsolową kółko i krzyżyk 6x6 oraz Pentago. Mam jednak pewne problemy, a zaczynam mieć coraz mniej czasu.

Miałoby to się odbywać za pomocą tablicy [6][6].

Stworzyłam funkcję rysującą planszę, jednak  nie jestem pewna w jaki sposób stworzyć pętle, aby widoczne było oddzielenie pomiędzy ćwiartkami.  

Największy problem mam jednak z ruchem gracza. Miałby się on odbywać przez określenie symbolu ćwiartki  q - lewa górna, w - prawa górna, a - lewa dolna, s - prawa dolna oraz numeru pola, który odpowiadałby ułożeniu na NumLocku. Wpadłam  na może niezbyt dobry pomysł aby określić ćwiartki przez pętle for w zależności od wiersza i kolumny tablicy. Jednak nadal mam problem z przetworzeniem tego na ruch gracza wraz z wyświetleniem w danym polu X lub O.

Nie jestem również pewna czy prawidłowo określiłam funkcję bool, które powinny zawracać true w razie spełnienia warunków wygranej. Jest bardzo pewna, że jest to zrobione nieprawidłowo.

Dodatkowo zrobiłam menu na switch. Mam jednak problem aby zrobić pętle do while (ponieważ switch opiera się na znakach i nie jestem pewna w jaki sposób określić wykonywanie switcha w pętli).

I ćwiartka        t[0][0], t[0][1], t[0][2]             II ćwiartka   t[0][3], t[0][4], t[0][5]
q (lewa góna)     t[1][0], t[1][1], t[1][2]            w(prawa górna) t[1][3], t[1][4], t[1][5]
                  t[2][0], t[2][1], t[2][2]                           t[2][3], t[2][4], t[2][5]

III ćwiartka      t[3][0], t[3][1], t[3][2]           IV ćwiartka     t[3][3], t[3][4], t[3][5]
a(lewa dolna)     t[4][0], t[4][1], t[4][2]         s(prawa dolna)    t[4][3], t[4][4], t[4][5]
                                  t[5][0], t[5][1], t[5][2]                                    t[5][3], t[5][4], t[5][5]

 

 

#include <iostream>
#include <string>

using namespace std;

char t[6][6]; //tablica 6x6 
const int kolumny = 6; //stała określająca liczbę kolumn 
const int wiersze = 6; // stała określająca liczbę wierszy
string g1;
string g2;

void rysujLinie(int kolumny)
{
    cout << "   ";
    for (int i = 0; i < kolumny; i++)
    {
        cout << " ---";
    }
    cout << endl;
}

void rysujNumery(int kolumny)
{
    cout << "   ";
    for (int i = 0; i < kolumny; i++)
    {
        cout << "  " << i + 1 << " ";
    }
    cout << endl;
}

void Plansza(int wiersze, int kolumny) //funkcja rysuje planszę, ale w sumie musiałbym jakoś przerobić, żeby widoczne było oddzieleni ćwirtek + wymaganie dodtkowe box drawings :(
{
    rysujNumery(kolumny);
    rysujLinie(kolumny);
    for (int i = 0; i < wiersze; i++)
    {
        cout << " " << int(1 + i);
        for (int j = 0; j < kolumny; j++)
        {
            cout << " |  ";
        }
        cout << " | " << int(1 + i) << endl;
        rysujLinie(kolumny);
    }
    rysujNumery(kolumny);
}
/* for (int i = 0; i < 6; i++) // pętla odpowiedzialna za ilość wierszy
    {
        for (int n = 0; n < 6; n++) //pętla odpowiedzialna za ilość kolumn
        {
            if (i % 2 == 0) cout << "-"; //rysujemy kreski poziome do planszy
            else if (n % 2 == 0 || i % 2 == 0 && i % 2 == 0) cout << "|"; //Rysujemy kreski pionowe do planszy
            else cout << " ";

        }

        cout << endl; ale to wychodzi plansza na jednowymiarową bardziej
    }*/



bool wygranaKiK() //warunki wygarnaej w kółko i krzyżyk 6x6, funkcja zwarca true jeśli wygrana
{
    for (int i = 0; i < 6; i++)
    {
        //wygrana przez rzędy
        return ((t[i][0] == t[i][1] == t[i][2] == t[i][3] == t[i][4] == t[i][5])|| //to wtedy wygrana ale jak to określić :( chyba, że spróbować z bool
        //wygrana przez kolumny
            (t[0][1] == t[1][i] == t[2][i] == t[3][i] == t[4][i] == t[5][i])|| //to wtedy wygrana ale jak to określić :( co zwrócić, dobra gubię się z else czy bez
       //wygraba po skosie
            (t[0][0] == t[1][1] == t[2][2] == t[3][3] == t[4][4] == t[5][5])|| //to coś zwrócić???
            (t[0][5] == t[1][4] == t[2][3] == t[3][2] == t[4][1] == t[5][0]));
        //prościej byłoby z pętlą tylko trzeba by  ją napisać heh
    }
}

bool remis() //kiedy zapełniona tablica bez znaków w liini, które umożliwiają wygraną
{
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 6; j++)
            if (t[i][j] == ' ')
                return false;
    return true;
}

void ruch(char t[][6]) //wybranie ćwiartki, a następnie pola w ćwiaertce 
{
    char q = t[6][6];
    char w = t[6][6];
    char a = t[6][6];
    char s = t[6][6];
    char odp;

    cout << "Podaj numer ćwiartki: q - lewa górna, w - prawa górna, a - lewa dolna, s - prawa dolna oraz numer pola: " << endl;
    cin >> odp;

    for (int i = 0; i < 3; i++) //podział na ćwiartki
    {
        for (int j = 0; j < 3; j++)
        {
            t[i][j] = q; //Icwiartka;
        }
    }

    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; 3 < j < 6; j++)
        {
            t[i][j] = w; //IIcwiartka;
        }
    }

    for (int i = 0; 3 < i < 6; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            t[i][j] = a;//IIIcwiartka;
        }
    }

    for (int i = 0; 3 < i < 6; i++)
    {
        for (int j = 0; 3 < j < 6; j++)
        {
            t[i][j] = s; //IVcwiartka;
        }
    }

}

void graKiK()
{
    cout << "\t\t\tWitaj w grze w kółko i krzyżyk" << endl;
    cout << "\t\t\Gracz: " << g1 << "X to twoj zeton" << endl;
    cout << "\t\t\Gracz: " << g2 << "O to twoj zeton" << endl;
    //składa się z planszy, warunku wygrania i remisu, ruchu. takie no podsumowanie
}

int main()
{
  
    cout << "\t\t\Witaj w grze w kolko i krzyzyk lub Pentago" << endl;
    cout << "\t\t\Zacznijmy od nadania nazwgraczy " << endl;
    cout << "\t\t\Podaj nazwe pierwszego gracza: " << endl;
    getline(cin, g1);
    cout << "\t\t\Nawza pierwszego gracza: " << g1 << endl;
    cout << "\t\t\Podaj nazwe drugiego gracza: " << endl;
    getline(cin, g2);
    cout << "\t\t\Nawza drugiego gracza: " << g2 << endl;


    char odp;
    //tu się walnie powitanie

    cout << "\t\t\Wybierz opcje: " << endl;
    cout << "\t\t\k: Gra w kolko i krzyzyk na planszy 6x6" << endl;
    cout << "\t\t\p:Gra w Pentago" << endl;
    cout << "\t\t\o: Predefiniowana plansza do Pentago" << endl;
    cout << "\t\t\h: Opis Pentago" << endl;
    cout << "\t\t\z: Wyjscie z programu" << endl;
    cin >> odp;

    switch (odp)
    {
    case 'k'://odowłanie do fukncji kik
        break;
    case 'p': //odwołanie do fukcji Pentago
        break;
    case 'o': //odwłoanie do fukcknji odpowidającej za predefiniowaną planszę
        break;
    case 'h':
        cout << "\t\t\Pentago jest gra dwuosobowa na planszy. Plansza sklada się z 4 ruchomych czesci, ktore mozna obracac. Każda część zawiera 9 miejsc na żetony" << endl;
        cout << "\t\t\ Gracze po kolei oddaja ruch skladajacy sie z 2 czesci: dolozenia swojego zetonu na niezajete pole planszy, obrot jednej z czesci planszy o 90 stopni w dowolnym kierunku. " << endl;
        cout << " \t\t\  Nie mozna zrezygnowac z adnej czesci ruchu. Wygrywa osoba, ktorej 5 zetonow, po pelnym ruchu, sa ulozone w rzedzie / kolumnie / po skosach(podobnie do gry kolko krzyzyk)." << endl;
        break;
    case 'z':
        break;
    default:
        cout << "\t\t\Niepoprawna opcja!" << endl << endl; // do porprawy 
        break;
    }
    return 0;
}

 

1 odpowiedź

+1 głos
odpowiedź 30 listopada 2021 przez TOM_CPP Pasjonat (22,640 p.)
edycja 30 listopada 2021 przez TOM_CPP

Kilka uwag odnośnie kodu.

  1. Nie używaj zmiennych globalnych. Im wcześniej się nauczysz programować bez ich używania tym lepiej.
  2. Pomyśl o użyciu struktury do enkapsulacji własnych funkcji (tak jak w przykładzie).
  3. Funkcja wygranaKiK jest źle napisana gdyż nie sprawdzane są wszystkie możliwe kombinacje wygranych.

Nie musisz sprawdzać wszystkich linii (pionowych,poziomych i ukośnych) aby obliczyć czy warunki wygranej są spełnione. Wystarczy w momencie ruchu ( polegającego na dodaniu elementu białego lub czarnego w puste miejsce tablicy )  sprawdzane będzie najbliższe sąsiedztwo tego elementu.

Szkielet takiej gry może wyglądać następująco.

#include <iostream>

using namespace std;

enum class Cell { Empty , Black , White };

struct Position
{
    int x {};
    int y {};
};

struct PentagoGame
{
    void drawBoard()
    {
        cout << "Drawing board";
    }

    bool checkRange( int x )
    {
        return  x >= 0 && x < 6 ;
    }

    string fillCell( Position pos , Cell cell )
    {
        board[pos.x][pos.y] = cell;
        return isVictory(pos) ? "Win "s+(cell==Cell::White?"White"s:"Black"s) : "No Win"s;
    }

    bool isVictory( Position pos )
    {
        int cx {0} , cy {0} , cxy {0};

        for( int i {-5} ; i<5 ; ++i )
        {
            bool xrange {checkRange(pos.x+i)};
            bool yrange {checkRange(pos.y+i)};

            if( xrange && board[pos.x][pos.y] == board[pos.x+i][pos.y] ) ++cx;
            else cx = 0;

            if( yrange && board[pos.x][pos.y] == board[pos.x][pos.y+i] ) ++cy;
            else cy = 0;

            if( xrange && yrange && board[pos.x][pos.y] == board[pos.x+i][pos.y+i] ) ++cxy;
            else cxy = 0;

            if( cx == 6 || cy == 6 || cxy == 6 ) return true;
        }

        return false;
    }

    Cell board[6][6];
};

int main()
{
    PentagoGame Pento;

    cout << Pento.fillCell( {0,0} , Cell::White ) << endl;
    cout << Pento.fillCell( {5,0} , Cell::Black ) << endl;
    cout << Pento.fillCell( {1,1} , Cell::White ) << endl;
    cout << Pento.fillCell( {4,0} , Cell::Black ) << endl;
    cout << Pento.fillCell( {2,2} , Cell::White ) << endl;
    cout << Pento.fillCell( {4,1} , Cell::Black ) << endl;
    cout << Pento.fillCell( {3,3} , Cell::White ) << endl;
    cout << Pento.fillCell( {5,1} , Cell::Black ) << endl;
    cout << Pento.fillCell( {4,4} , Cell::White ) << endl;
    cout << Pento.fillCell( {5,4} , Cell::Black ) << endl;
    cout << Pento.fillCell( {5,5} , Cell::White ) << endl;
}

 

komentarz 30 listopada 2021 przez niezalogowany

Programuje od jakiegoś miesiąca i mam z tym problemy, więc przepraszam, jeśli pytam się o jakieś oczywistości. Próbowałam pracować na szablonie, jednak mam z tym lekkie problemy. Rozumiem, że określamy w nim pozycję za pomocą współrzędnych oraz sprawdzanie warunków zwycięstwa.

Mimo tego chciałam spróbować jeszcze raz sama to stworzyć starając stosować się do rad. Udało mi się w miarę stworzyć kółko i krzyżyk[3][3] wykorzystując w dużej mierze pętle. Chciałabym przerobić to tak aby możliwa była gra na planszy[6][6], jednak cały czas mam błędy w kodzie, które np. uniemożliwiają podanie wiersza, kolumny > 3.

Próbowałam, zgodnie z radą, również stworzyć strukturę do gry w kółko i krzyżyk jednak najczęściej prowadziło to do ogromnej ilości błędów i ostrzeżeń. Powinnam osobno stworzyć strukturę na zmienne i grę w kik?

Przepraszam, jeśli jest wrażenie, że nie zrozumiałam nic z odpowiedzi, jednak programowanie jest dla mnie nowością, w której nie mam zbyt dużego doświadczenia. Bazuję jednocześnie rzeczach, które mieliśmy przedstawione na układach.

 

#include<iostream>
#include <string>
using namespace std;


static char t[6][6] = { {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '}, {' ', ' ', ' '} }, ch1; //tablica znaków ' ' zosatje do końca działania jeśli dobrze myślę
string g1, g2;
int w, k; //wiersz, kolumna
int alt = 0;

void reset()  //fukncja resetująca planszę, po wyrganej, remisie
{
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 6; j++)
            t[i][j] = ' ';
}

void rysuj_plansze()  //funkcja rusyjąca plansze DOPRACOWAĆ!
{
   
    for (int i = 0; i < 6; i++) 
    {
        for (int j = 0; j < 6; j++) 
        {
            if (j == 0)
                cout << "\t\t\t";
            cout << " " << t[i][j] << " ";
            if (j != 6)
                cout << "|";
        }
        cout << "\n";
        if (i != 6)
            cout << "\t\t\t---------------------\n";
    }
}

bool wygrana(char ch4)  //fukcja zwrwacająca true w wypadku wygranej
{
    return ((t[0][0] == ch4 && t[0][1] == ch4 && t[0][2] == ch4) ||
        (t[1][0] == ch4 && t[1][1] == ch4 && t[1][2] == ch4) ||
        (t[2][0] == ch4 && t[2][1] == ch4 && t[2][2] == ch4) ||
        (t[0][0] == ch4 && t[1][0] == ch4 && t[2][0] == ch4) ||
        (t[0][1] == ch4 && t[1][1] == ch4 && t[2][1] == ch4) ||
        (t[0][2] == ch4 && t[1][2] == ch4 && t[2][2] == ch4) ||
        (t[0][0] == ch4 && t[1][1] == ch4 && t[2][2] == ch4) ||
        (t[0][2] == ch4 && t[1][1] == ch4 && t[2][0] == ch4)); //dołożyć resztę, jest to bardz bardzo mało efektywne, ale inne pomysły jakoś mi nie wychodzą

 
 }



bool plansza_pelna() //plansza pełna ==> remis
{
    for (int i = 0; i < 6; i++)
        for (int j = 0; j < 6; j++)
            if (t[i][j] == ' ')
                return false;
    return true;
}

void ruch(char c1)  // ruch + sprawdzenie czy pole nie jest już zajęte
{
    if (t[w - 1][k - 1] == ' ')
        t[w - 1][k - 1] = c1;
    else {
        cout << "\nTo pole jest juz zajete!\n\n";
        alt--;
    }
}

void graj() // funkcja odpowiadająca za grę w kółko i krzyżyk 6x6, wprowadzenie przez graczy numeru kolumny i numeru wiersza, w którym chcą umieścić swój żeton
            //jednak źle dobrane warunki aby wstawić w wiersz i kolumnę > 3. gdzie robię błędy 
{
    do {
        if (alt % 2 == 0)
        {
            cout << endl << "\n" << g1 << " rudna\n";
            ch1 = 'X';
        }
        else 
        {
            cout << endl << "\n" << g2 << "'runda\n";
            ch1 = 'O';
        }
        while (1) 
        {
            cout << "Wypisz numer kolumny, w kotrej chcesz wykonac ruch:  ";

            cin >> k;

            if (k < 1 || k > 6)
                cout << "Wprowadz kolumne w liczbach z zakresu od 1 do 6!\n";
            else
                break;
        }
        while (1) 
        {
            cout << "Wypisz numer wiersza, w kotrym chcesz wykonac ruch:  ";
            
            cin >> w;
            if (w < 1 || w > 6)
                cout << "Wprowadz wiersz w liczbach z zakresu od 1 do 6\n";
            else
                break;
        }
        ruch(ch1);
        alt++;
        rysuj_plansze();
    } while (!wygrana(ch1) && !plansza_pelna());
}

void graw_kik()
{
    char ch; 

    do
    {
    rysuj_plansze();
    graj();

    cout << "\n\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
    cout << "\t\t\t\WYNIKI: ";

    if (plansza_pelna() && !(wygrana('X') || wygrana('O')))
        cout << "Remis!\n";

    else if (alt % 2 == 0)
        cout << g2 << " Wygrywa!\n";
    else
        cout << g1 << " Wygrywa!\n";

    cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n\n";
    cout << "\nChcesz zagrac jeszcze raz? (T / N): ";
    reset();
    alt = 0;
    cin >> ch;

} while (ch != 'n' && ch != 'N'); //gra dopóki odp T
}

int main() 
{
   

        cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
        cout << "\t\t\tWELCOME TO THE TIC-TAC-TOE GAME\n";
        cout << "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n";
        cout << "\nWprowadz nazwe pierwszego gracza ";
        getline(cin, g1);
        cout << "Symbol gracza:  " << g1 << " to 'X'\n";
        cout << "\nWprowadz nazwe drugiego gracza ";
        getline(cin, g2);
        cout << "Symbol gracza: " << g2 << " to 'O'\n\n";

       
        char odp;
        //tu się walnie powitanie

        cout << "\t\t\Wybierz opcje: " << endl;
        cout << "\t\t\k: Gra w kolko i krzyzyk na planszy 6x6" << endl;
        cout << "\t\t\p:Gra w Pentago" << endl;
        cout << "\t\t\o: Predefiniowana plansza do Pentago" << endl;
        cout << "\t\t\h: Opis Pentago" << endl;
        cout << "\t\t\z: Wyjscie z programu" << endl;

        cin >> odp;

        switch (odp)
        {
        case 'k': graw_kik();
            break;
        case 'p': //odwołanie do fukcji Pentago
            break;
        case 'o': //odwłoanie do fukcknji odpowidającej za predefiniowaną planszę
            break;
        case 'h':
            cout << "\t\t\Pentago jest gra dwuosobowa na planszy. Plansza sklada się z 4 ruchomych czesci, ktore mozna obracac. Każda część zawiera 9 miejsc na żetony" << endl;
            cout << "\t\t\ Gracze po kolei oddaja ruch skladajacy sie z 2 czesci: dolozenia swojego zetonu na niezajete pole planszy, obrot jednej z czesci planszy o 90 stopni w dowolnym kierunku. " << endl;
            cout << " \t\t\  Nie mozna zrezygnowac z adnej czesci ruchu. Wygrywa osoba, ktorej 5 zetonow, po pelnym ruchu, sa ulozone w rzedzie / kolumnie / po skosach(podobnie do gry kolko krzyzyk)." << endl;
            break;
        case 'z':
            break;
        default:
            cout << "\t\t\Niepoprawna opcja!" << endl << endl; // do porprawy 
            break;
        }
        return 0;
}

 

Podobne pytania

0 głosów
1 odpowiedź 3,538 wizyt
pytanie zadane 25 listopada 2018 w C# przez Corson Początkujący (260 p.)
0 głosów
0 odpowiedzi 266 wizyt
pytanie zadane 26 stycznia 2022 w C i C++ przez kwkstein Nowicjusz (150 p.)
0 głosów
0 odpowiedzi 703 wizyt
pytanie zadane 30 listopada 2021 w C i C++ przez niezalogowany

92,555 zapytań

141,400 odpowiedzi

319,537 komentarzy

61,938 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

Kolejna edycja największej imprezy hakerskiej w Polsce, czyli Mega Sekurak Hacking Party odbędzie się już 20 maja 2024r. Z tej okazji mamy dla Was kod: pasjamshp - jeżeli wpiszecie go w koszyku, to wówczas otrzymacie 40% zniżki na bilet w wersji standard!

Więcej informacji na temat imprezy 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!

...