Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. International
  3. Polish
  4. 'animacja' gry connect 4 (C++, Qt)
Forum Updated to NodeBB v4.3 + New Features

'animacja' gry connect 4 (C++, Qt)

Scheduled Pinned Locked Moved Polish
11 Posts 4 Posters 5.5k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    truemop
    wrote on last edited by
    #1

    Witam! Napisałem w C++ grę Connect 4 (http://en.wikipedia.org/wiki/Connect_Four, http://pl.wikipedia.org/wiki/Czwórki) do gry z komputerem. Do wyświetlania planszy stosuję pole Plain Text Edit. Na początku zrobiłem zwykłe przepisywanie planszy (zwykła tablica 6x7, 0 pole puste; 1,2 pionki graczy) do tego pola. Teraz próbuję zrobić funkcję, która w Plain Text Edit zrobi tekstową animację wrzucania pionka, czyli pionek pojawia się w najwyższym wierszu, po odpowiednim czasie pojawia się we wierszu niżej i niżej aż napotka inny pionek. Niestety ta funkcja nie działa, gdyż drukuje planszę dopiero po wykonaniu wszystkich kroków oraz czasem pionek komputera pojawia się wyżej niż powinien, przy czym w następnym ruchu jest on już tam gdzie powinien.

    Oto te dwie funkcje:
    @void MainWindow::drukujplanszegui()
    {
    stringstream strumien;
    string tekst;

    for(int i=0;i<6;i++)
    {
        strumien<<pozycja[i][0];
        for(int j=1;j<7;j++)
        {
            strumien<<setw(3)<<pozycja[i][j];
        }
        strumien<<endl;
    }
    
    tekst = strumien.str();
    QString tekst_qt = tekst.c_str();
    ui->ptePlansza->clear();
    ui->ptePlansza->appendPlainText(tekst_qt);
    

    }

    void MainWindow::drukujplanszeanimacja(int kolumna1, int gracz5)
    {
    for(int i=0;i<5;i++)
    {
    pozycja[i][kolumna1]=gracz5;
    drukujplanszegui();
    Sleep(500);
    if(pozycja[i+1][kolumna1]!=0)
    break;
    pozycja[i][kolumna1]=0;
    }
    if(pozycja[5][kolumna1]==0)
    pozycja[5][kolumna1]=gracz5;

    }@

    "Plik z całym programem":http://www.speedyshare.com/vP8sy/Connect4-gui.zip

    Poza tym próbuję zrobić sprawdzenie czy wykorzystywane przeze mnie listy zostały wczytane z pliku.

    @MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
    {
    ui->setupUi(this);

    p2=listaZpliku("wartoscioweulozenia2.txt");     //utworzenie listy jednokierunkowej z pliku
    p1=listaZpliku("wartoscioweulozenia1.txt");
    p1p=listaZpliku("wartoscioweulozenia1pion.txt");
    p2p=listaZpliku("wartoscioweulozenia2pion.txt");
    if(p2==NULL)
    {
        ui->ptePlansza->clear();
        wyswietlpteplansza("Blad pliku. Sprawdz, czy pliki wartoscioweulozenia1.txt ; wartoscioweulozenia2.txt ; wartoscioweulozenia1pion.txt ; wartoscioweulozenia2pion.txt znajduja sie w folderze roboczym i uruchom program ponownie.");
    }
    

    .
    .
    .
    }
    @

    listazpliku:
    @wartosciowe* listaZpliku(string plik) //wczytuje z pliku do listy jednokierunkowej
    {
    wartosciowe *pocz, *akt, *og;
    string a, b, c, d, e;

    ifstream we;
    we.open (plik.c_str());
    if (!we.good())
    return NULL;
    else
    {
        we>>a>>b>>c>>d>>e;  //wczytanie zmiennych tymczasowych z pliku
        pocz= new wartosciowe;
        if(!we.eof())
        {
            pocz->w1=atoi(a.c_str());   //wczytanie do listy tymczasowych zmiennych typu string skonwertowanych do liczb całkowitych
            pocz->w2=atoi(b.c_str());
            pocz->w3=atoi(c.c_str());
            pocz->w4=atoi(d.c_str());
            pocz->pkt=atoi(e.c_str());
            pocz->nast=NULL;
            og=pocz;
            while (!we.eof())
            {
                we>>a>>b>>c>>d>>e;
                akt= new wartosciowe;
                akt->w1=atoi(a.c_str());
                akt->w2=atoi(b.c_str());
                akt->w3=atoi(c.c_str());
                akt->w4=atoi(d.c_str());
                akt->pkt=atoi(e.c_str());
                akt->nast=NULL;
                og->nast=akt;
                og=akt;
            }
    
        }
        else pocz=NULL;
        we.close();
    
        return pocz;
    }
    

    }@

    Niestety to sprawdzenie zawsze pokazuje, że coś poszło nie tak, mimo że gra działa normalnie. Dodam, że w wersji konsolowej, napisanej strukturalnie takie sprawdzenie działało.

    1 Reply Last reply
    0
    • 8 Offline
      8 Offline
      8majkel8
      wrote on last edited by
      #2

      nie lepiej skorzystać z QGraphicsView (nawet jeżeli ma nieć wygląd retro) ?

      1 Reply Last reply
      0
      • T Offline
        T Offline
        truemop
        wrote on last edited by
        #3

        To projekt na studia i już jest za późno na taką zmianę, bo oddałem projekt formatki którego nie mogę zmienić

        1 Reply Last reply
        0
        • A Offline
          A Offline
          ariwez
          wrote on last edited by
          #4

          Na wstępie program ten z Qt za wiele wspólnego nie ma, ale postaram się Ci pomóc.

          Używając w kodzie Sleepa blokujesz główny wątek GUI, dlatego w czasie animacji eventy nie są obslugiwane, między innymi event odpowiadający za rysowanie PlainTextEdit, dlatego musisz wywołać go ręcznie, w metodzie MainWindow::drukujplanszegui() za ostatnią linijką dopisz

          @ ui->ptePlansza->repaint();@

          O wiele lepiej by to działało i wyglądało gdybyś użył do "animacji" "QTimer'a":http://qt-project.org/doc/qt-4.8/qtimer.html

          Jeśli chodzi o drugi problem to zmieniłem w MainWindow::drukujplanszeanimacja() na i < 6 (bo tyle jest wierszy chyba) i zeton komputera spada do ostatniej linii, ale czy to jest przyczyną tego buga to stuprocentowej pewności nie mam z powodu bliskiej zeru czytelności kodu ;) Jeśli ktoś ma czytać Twój kod w przyszłości to polecam używać komentarzy oraz rozsądnych nazw zmiennych (CamelCase ftw, zapomnij o notacji węgierskiej).

          U mnie po takich poprawkach działa i nawet jest grywalne :D

          1 Reply Last reply
          0
          • A Offline
            A Offline
            Alek Śmierciak
            wrote on last edited by
            #5

            bq. Jeśli ktoś ma czytać Twój kod w przyszłości to polecam używać komentarzy oraz rozsądnych nazw zmiennych

            Proponuję również używanie w całości języka angielskiego w kodzie źródłowym.

            1 Reply Last reply
            0
            • T Offline
              T Offline
              truemop
              wrote on last edited by
              #6

              O, wielkie dzięki, animacja działa :D Za komentarze już się zabieram, po prostu jeszcze nie mam nawyku pisania ich na bieżąco.
              Co do MainWindow::drukujplanszeanimacja(), w wypadku podania i < 6, gdy dojdziemy do i=5 metoda odwołuje się do nieistniejącego elementu tablicy w momencie
              @if(pozycja[i+1][kolumna1]!=0)
              break;@

              Chociaż po tej zmianie działa, wolałbym tego uniknąć.

              Z założenia miało to tak działać:

              @void MainWindow::drukujplanszeanimacja(int kolumna1, int gracz5)
              {
              for(int i=0;i<5;i++) //przeszukiwanie wierszy poza ostatnim
              {
              pozycja[i][kolumna1]=gracz5; //w wybranej kolumnie wstawia pionek w i-tym wierszu
              drukujplanszegui(); //drukuje plansze
              Sleep(300); //czeka
              if(pozycja[i+1][kolumna1]!=0) //jeżeli w następnym wierszu w wybranej kolumnie jest pionek to wychodzi z pętli (pionek jest już na swoim miejscu)
              break;
              else
              pozycja[i][kolumna1]=0; //jeśli nie to kasuje wcześniej wstawiony pionek i przechodzi do następnego wiersza
              }
              if(pozycja[5][kolumna1]==0) //sprawdzenie pominiętego w pętli ostatniego wiersza.
              pozycja[5][kolumna1]=gracz5; //jeżeli w wybranej kolumnie w ostatnim wierszu nie ma pionka to go tam wstawia

              }@

              Nie macie może jeszcze jakiegoś pomysłu co do tego sprawdzania czy lista się wczytała z pliku? Kod do sprawdzania jednej z list jest na początku mainwindow.cpp w domyślnym konstruktorze w komentarzu (nie chciałem żeby mnie to wkurzało, ani żebym o tym zapomniał). Jak już wcześniej pisałem sprawdzanie to zawsze wyrzuca błąd, mimo że lista się wczytała.

              Jest jeszcze jedna rzecz która mnie prześladuje, aczkolwiek nie wiem czy to wina kodu, Qt, czy jeszcze czegoś innego. Otóż czasem gra jakby wykrywała dwa kliknięcia na przycisk zamiast jednego, bo po umiejscowieniu mojego pionka i pionka komputera wrzuca mój pionek tam gdzie poprzedni.

              1 Reply Last reply
              0
              • T Offline
                T Offline
                truemop
                wrote on last edited by
                #7

                Przerobiłem tę metodę animacji, tak żeby działało logicznie i jest wszystko w porządku:

                @void MainWindow::drukujplanszeanimacja(int kolumna1, int gracz5)
                {
                int n;
                for(int i=5;i>=0;i--) //wyszukiwanie miejsca do wstawienia pionka
                {
                if(pozycja[i][kolumna1]==0)
                {
                n=i;
                break;
                }
                }

                for(int i=0;i<n;i++)
                {
                    pozycja[i][kolumna1]=gracz5;    //w wybranej kolumnie wstawia pionek w i-tym wierszu
                    drukujplanszegui();     //drukuje plansze
                    Sleep(180);     //czeka
                    pozycja[i][kolumna1]=0;     //kasuje wcześniej wstawiony pionek i przechodzi do następnego wiersza
                }
                pozycja[n][kolumna1]=gracz5; //wstawia pionek w odpowiednie miejsce
                drukujplanszegui(); //drukuje plansze
                

                }@

                A sprawdzanie czy pliki się wczytały wciąż nie działa z przyczyn tajemniczych :(

                1 Reply Last reply
                0
                • A Offline
                  A Offline
                  ariwez
                  wrote on last edited by
                  #8

                  Gdzie masz umieszczony plik do wczytania? Jeśli uruchamiasz przez QtCreatora working directory nie jest koniecznie tam gdzie plik wykonywalny ;]

                  1 Reply Last reply
                  0
                  • T Offline
                    T Offline
                    truemop
                    wrote on last edited by
                    #9

                    Ustawiłem working directory gdzie trzeba. Problem jest w tym, że program działa bez zarzutu, a sprawdzenie mimo wszystko sądzi że listy się nie wczytały

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      ariwez
                      wrote on last edited by
                      #10

                      bq. Ustawiłem working directory gdzie trzeba.

                      Używasz shadow buildów, więc jeśli to Twoja ścieżka, to tam powinny sie znalezc:

                      @C:/Users/ZAP/Desktop/Connect4_gui/Connect4_gui-build-Desktop_Qt_5_0_1_MinGW_32bit-Release@

                      A nie w katalogu z projektem lub buildami (release/debug z małej litery).

                      U mnie plansze się wczytują po odkomentowaniu sprawdzania.

                      1 Reply Last reply
                      0
                      • T Offline
                        T Offline
                        truemop
                        wrote on last edited by
                        #11

                        O kurcze, wielkie dzięki. Miałem straszny błąd w myśleniu. Wydawało mi się, że w ustawieniach Qt przestawiłem katalog roboczy na katalog z kodem, w którym mam pliki do wczytania, a tego nie zrobiłem. Sądziłem, że mam jakiś błąd sprawdzania, bo gra działała i wygrywała ze mną często, a większość jej 'inteligencji' opierała się na tych właśnie plikach. Jednak po prostu program sobie radził bez plików.
                        Sprawdzanie oczywiście przerobiłem już tak, żeby nie pozwalało na grę bez plików :)

                        A coś mi z tyłu głowy siedziało, że mój przeciwnik stał się głupszy po przeniesieniu aplikacji na okienka.

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved