Panel użytkownika
Nazwa użytkownika:
Hasło:
Nie masz jeszcze konta?

[C++] Kółko i krzyżyk. Problem z warunkiem wygranej

Ostatnio zmodyfikowano 2016-06-16 23:54
Autor Wiadomość
HoulScream
Temat założony przez niniejszego użytkownika
[C++] Kółko i krzyżyk. Problem z warunkiem wygranej
» 2016-06-15 18:57:19
Witam, jestem tutaj nowy i próbuję napisać prostą grę, kółko i krzyżyk. Może z grubsza zasady dla jasności: Gramy na planszy 9x9 i warunkiem zwycięstwa jest postawienie 5ciu takich samych znaczków w górę, dół, lub na skosy. Nie wszystko jest jeszcze zrobione ale nie chcę iść dalej niczym nie uporam się z niniejszym problemem, otóż po stworzeniu "szkicu" gry zacząłem dodawać warunki zwycięstwa (konkretnie pierwszy). Chciałem dodać warunek który będzie nam sprawdzał czy mamy pięć takich samych symboli w jednym wierszu. Jeżeli tak, metoda GameOver() zwraca true i gra się kończy, lecz jeżeli warunek nie zostanie spełniony zwraca ona false i gramy dalej. Problem polega na tym, że warunek zwraca poprawne wartości tylko jeżeli postawimy krzyżyk lub kółko w polach 1,2,3,4,5. Jeżeli wprowadzimy np 2,3,4,5,6 metoda ciągle będzie zwracać false, dopóki nie pojawi się kompletny ciąg 1,2,3,4,5. Proszę o wyrozumiałość, gdyż jestem na początku swojej drogi z C++. Oto kod i bardzo proszę o pomoc. Pozdrawiam

C/C++
#include <iostream>
#include <string>
#include <ios>
using namespace std;

#define SIZE 9
enum Figure { o, x };
class Point
{
public:
    char element = '\0';
    Point( char c )
    {
        this->element = c;
    }
    Point()
    {
        this->element = '\0';
    }
};

class Place
{
public:
    Point place[ SIZE * SIZE + 1 ];
   
    Place()
    {
       
    }
   
    void MakeStep( int i, Figure f )
    {
        place[ i ] =( f == Figure::o ? 'O': 'X' ); // zmienna1 != zmienna2 ? true : false;
    }
    bool GameOver()
    {
        // Sprawdzamy wiersze
        for( int i = 1; i <= SIZE * SIZE; i = + SIZE )
        {
            if(( place[ i ].element == 'O' ) &&( place[ i + 1 ].element == 'O' ) &&( place[ i + 2 ].element == 'O' ) &&( place[ i + 3 ].element == 'O' ) &&( place[ i + 4 ].element == 'O' ) )
            {
                cout << "Wygral Gracz: O";
                return true;
            }
            else if(( place[ i ].element == 'X' ) &&( place[ i + 1 ].element == 'X' ) &&( place[ i + 2 ].element == 'X' ) &&( place[ i + 3 ].element == 'X' ) &&( place[ i + 4 ].element == 'X' ) )
            {
                cout << "Wygral Gracz: X";
                return true;
            }
            else return false;
           
        }
        return false;
    }
   
    void ShowPlace()
    {
        system( "cls" );
        for( int i = 1; i <= SIZE * SIZE; i++ )
        {
            cout << " " << place[ i ].element << " ";
            if( i % SIZE ) cout << "|";
            else if( i != SIZE * SIZE )
            {
                string poprzeczka = "+---";
                cout << "\n---";
                for( int i = 0; i < SIZE - 1; i++ )
                {
                    cout << poprzeczka;
                }
                cout << "\n";
            }
            else cout << endl;
           
        }
       
    }
    void FillPlace()
    {
        for( int i = 0; i <= SIZE * SIZE + 1; i++ )
        {
            place[ i ].element = '0';
        }
    }
};

void main()
{
    Place * place = new Place();
   
    place->FillPlace();
    int i = 0;
    place->ShowPlace();
    while( !place->GameOver() )
    {
        int a;
        cin >> a;
        place->MakeStep( a, i % 2 == 0 ? Figure::o: Figure::x );
        place->ShowPlace();
        i++;
    }
    cin.get();
    cin.get();
};
P-149150
mateczek
» 2016-06-16 04:55:14
Błędów masz kilka !!!
1. return kończy ci pętle i funkcje. Dlatego sprawdza ci tylko pierwsze 5 i wychodzi z prawdą lub fałszem


C/C++
for( int i = 1; i <= SIZE * SIZE; i = + SIZE ) //źle bo w ten sposób zmienna "i" cały czas jest równe SIZE !!!
//jeśli już to
for( int i = 1; i <= SIZE * SIZE; i += SIZE )
//ale najprawdopodobniej
for( int i = 1; i <= SIZE * SIZE; i++ )



Zapoznaj się z debuggerem Szybko sam namierzysz takie niedociągnięcia
A tu algorytm oparty na liczeniu pod rząd wystąpień
C/C++
bool GameOver()
{
    // Sprawdzamy wiersze
    int countX = 0;
    int countO = 0;
    for( int i = 1; i <= SIZE * SIZE; i++ )
    {
        if( place[ i ].element == 'X' ) {
            countX++;
            if( countX == 5 ) { cout << "wygraly X: "; return true; }
        } else countX = 0; // gdy się nie trafi x to zerujemy licznik
       
        if( place[ i ].element == 'O' ) {
            countO++;
            if( countO == 5 ) { cout << "wygraly O: "; return true; }
        } else countO = 0;
       
    }
    return false;
}
P-149164
HoulScream
Temat założony przez niniejszego użytkownika
Dziękuję
» 2016-06-16 07:31:01
Bardzo dziękuję za skorygowanie błędów i sugestię. Zobaczymy co będzie dalej. Pozdrawiam :)

// EDIT

Zasugerowany algorytm również nie spełnia moich oczekiwań. Działa ale jest z nim pewien problem. Gdy ciąg np w polach 2,3,4,5,6 wszystko jest ok ale gdy na przykład podamy ciąg 8,9,(tu zaczna się nowy wiersz)10,11,12 algorytm nadal widzi w tym zwycięstwo. Jakieś sugestie ?
P-149167
kargi191
» 2016-06-16 08:49:32
Natknąłem się kiedyś na ten filmik w sieci:

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

Może okaże się dla Ciebie pomocny
P-149170
mateczek
» 2016-06-16 08:54:03
zrobić macierz 2D i dwie pętle for
pierwsza pętla indeksuje wiersze druga jedzie po elementach wierszy
P-149171
carlosmay
» 2016-06-16 09:58:49
zrobić macierz 2D i dwie pętle for
Można zostawić jak jest, tylko dodaj do warunku pętli drugą zmienną określająca koniec wiersza.

Dodanie jedynki do rozmiaru aby móc indeksować od 1 to kiepski pomysł.
Lepiej przyzwyczaić się do indeksowania naturalnego.
Wiem, że teraz jest wygodniej, ale gdy dojdą inne pętlę program z mało czytelnego
stanie się całkiem nieczytelny.
P-149175
HoulScream
Temat założony przez niniejszego użytkownika
» 2016-06-16 18:01:11
Zastosowałem się do powyższych sugestii i z grubsza nawet to działa, lecz napotkałem kolejny problem z którym nie mogę się uporać, mój warunek:
C/C++
for( int i = 1; i <= SIZE * SIZE; i++ )
{
    if(( place[ i ].element == 'O' ) &&( place[ i + 1 ].element == 'O' ) &&( place[ i + 2 ].element == 'O' ) &&( place[ i + 3 ].element == 'O' ) &&( place[ i + 4 ].element == 'O' ) )
    {
        cout << "Wygral Gracz: O" << endl;
        cout << "Koniec gry" << endl;
        return true;
    }
działa "aż za dobrze", konkretnie chodzi mi o to, że jeżeli pojawi się ciąg na skraju wiersza pojawia się np kółka (np 8,9) a kolejny zaczynał się będzie (10,11,12) również kółkami, to warunek wygranej również zajdzie. Myślałem o ograniczeniu wszystkiego jeszcze jednym warunkiem:
C/C++
if( i % SIZE <= 5 )
niestety również bez większych rezultatów, warunek wprowadził to, że w dolnym rzędzie muszą być co najmniej 4 jednakowe elementy aby gra się zakończyła (ciąg 9,10,11,12,13 - również wygrywał ale np 8,9,10,11,12 - już nie)

ma ktoś jakiś pomysł jak to ugryźć ? Pozdrawiam
P-149186
carlosmay
» 2016-06-16 23:54:02
Taki przykład dla poziomych wierszy:
C/C++
auto main()->int
{
    // plansza 4 x 4 i trzy pola wygrywają
    constexpr int SIZE = 4;
    constexpr int LENGTH_WIN_STRING = 3;
   
    std::array < int, SIZE * SIZE > arr { };
    arr[ 0 ] = 1;
    arr[ 1 ] = 1;
    arr[ 7 ] = 1;
    arr[ 8 ] = 1;
    arr[ 13 ] = 1;
   
    for( int i = 0; i < SIZE; ++i )
    {
        for( int j = i * SIZE; j <( SIZE + i * SIZE ) && j <( SIZE * SIZE - 2 ); ++j )
        {
            bool isCheckLineCorrect =( j % SIZE ) <=( SIZE - LENGTH_WIN_STRING );
            bool isWinString =( arr[ j ] == 0 ) &&( arr[ j + 1 ] == 0 ) &&( arr[ j + 2 ] == 0 );
           
            if( isWinString && isCheckLineCorrect ) {
                std::cout << "Wygrałeś w wierszu nr: " << i + 1 << '\n';
            }
        }
    }
}
P-149199
« 1 »
  Strona 1 z 1