sterowaniem strzałkami w C++

0

Hej, problem jest z funkcją w grze saper odpowiadającą za ruch po dynamicznej dwuwymiarowe tablicy struktur za pomocą strzałek, więcej szczegółów jest w komentarzu nad funkcją. Dodam, że jestem raczej początkujący w programowaniu. Za wszelką pomoc bardzo dziękuję bo męczę się z tym od dłuższego czasu :/

//nowagra1 to struktura z wymiarami tablicy
//na początku funkcji są petle do wyświetlania tablicy, każde pole jest strukturą i ma wartość liczbową i czy jest zasłonięte czy odkryte (false/ true). Na początku wszystkie są zasłonięte
// potem sprawdza czy przycisk jest przyciskiem specjalnym (strzałki) jeżeli tak, zmienia wspólrzedne(aktualny_x,aktualny_y) w zależności jaka strzałka jak nie to sprawdza czy jest enter
// enter zmienia pole tablicy o tych wspołrzednych na których jest kursor na odkryte chyba ze pole ma wartosc 9 to kończy funckje
// strzałki działają dobrze bo przed każdym enterem sprawdzam aktualne współrzędne kursora i zmieniają się dobrze
// jedyny błąd jest po wciśnięciu entera bo wtedy odkrywa w ogóle inne pola np zamiast 3,2 to 3,0
// tablica jest w poprawny sposób wypełniona i stworzona, sprawdziłem na parę sposób

void ruch (pola**&t, nowagra &nowagra1)
{
bool koniec = false;
int aktualny_x=0, aktualny_y=0;
while( koniec == false )
{ system ("cls"); //czyść ekran
cout<<aktualny_x<<" "<<aktualny_y;
cout<<endl;

       cout<<" ";
           for (int j = 0; j<nowagra1.M; j++)
               cout<<"----";
           cout<<endl;

       for (int i = 0; i<nowagra1.N; i++)
         {

           for (int j = 0; j<nowagra1.M; j++)
               {
               if(j==0)
                   cout<<"| ";

               if(t[i][j].odkryte==true)
               cout<<t[i][j].wartosc<<" | ";


           }
       cout<<'\n';
       }



       cout<<" ";
           for (int j = 0; j<nowagra1.M; j++)
               cout<<"----";
           cout<<endl;



     unsigned char znak = getch();
          switch( znak )
       {
        case 0:  
         {
          case 13: //enter
          t[aktualny_x][aktualny_y].odkryte=true;
          if(t[aktualny_x][aktualny_y].wartosc==9)
           {
              cout<<t[aktualny_x][aktualny_y].wartosc;
              koniec=true;
              break;
           }

          else
          break;


          case 27: //ESC
          koniec = true;
          break;
        }
         case 224: //klawisze specjalne
           znak = getch();
           switch( znak )
           {
           case 72: //strzałka w górę
               aktualny_x--;
               if(aktualny_x<0)
               aktualny_x=nowagra1.N-1;
               break;

           case 80: //strzałka w dół
               aktualny_x++;
               if(aktualny_x>nowagra1.N-1)
               aktualny_x=0;
               break;
           case 75: //strzałka w lewo
               aktualny_y--;
               if(aktualny_y<0)
               aktualny_y=nowagra1.M-1;
               break;
           case 77: //strzałka w prawo
               aktualny_y++;
               if(aktualny_y>nowagra1.M-1)
               aktualny_y=0;
               break;

         }
      }

}

}

0

Sorki źle się kod wkleił. Tutaj jest w lepszej wersji ;)

http://codepad.org/DDkH8R54

0
  1. Zapoznaj się z pojęciem formatowania kodu: http://4programmers.net/Forum/998482
  2. Zapoznaj się z inkrementacją, bo jej nie rozumiesz: http://4programmers.net/Forum/1101404
  3. Nie używaj innego niż angielskie nazewnictwa: http://4programmers.net/Forum/1208091
  4. Wklejaj kod w znaczniki <``code=cpp> * tu twój kod * <``/code>
0

Trochę taki offtop.
Mam pytanie do @_13th_Dragon do punktu 2. post/pre inkrementacja
Troszkę sobie deassembluje pewne rzeczy i sprawdzam, z optymalizacją i bez niej. Różne przypadki. Mógłbyś podać jakiś przykład (z tą dodatkową zmienną), oraz sposób kompilacji abym mógł zobaczyć różnicę?

0
#include <iostream>
using namespace std;

int main()
  {
   int a,b;
   a=2; b=++a; cout<<"a="<<a<<"; b="<<b<<";"<<endl;
   a=2; b=a++; cout<<"a="<<a<<"; b="<<b<<";"<<endl;
   return 0;
  }

http://ideone.com/gob7T6 już masz ewidentną różnice.

0

Dzieki za przykład, w końcu to zrozumiałem dokładnie. O ile w pętlach for,while nie ma to kompletnie znaczenia o tyle taki przykład jest swoistym dowodem, jeszcze raz dzieki!

0
struct pola{
    int wartosc;
    bool odkryte;
};

void ruch (pola**&t, nowagra &nowagra1)
{
       bool finish = false;
       int current_x=0, current_y=0;
       while( finish == false )
       {    system ("cls"); //czyść ekran
           cout<<current_x<<"  "<<current_y;
           cout<<endl;


           cout<<" ";
               for (int j = 0; j<nowagra1.M; j++)
                   cout<<"----";
               cout<<endl;

           for (int i = 0; i<nowagra1.N; i++)
             {

               for (int j = 0; j<nowagra1.M; j++)
                   {
                   if(j==0)
                       cout<<"| ";

                   if(t[i][j].odkryte==true)
                   cout<<t[i][j].wartosc<<" | ";


                   }
                cout<<'\n';
             }



               cout<<" ";
               for (int j = 0; j<nowagra1.M; j++)
               cout<<"----";
               cout<<endl;



         unsigned char znak = getch();
              switch( znak )
           {


              case 13: //enter
              t[current_x]current_y].odkryte=true;
              if(t[current_x][current_y].wartosc==9)
               {
                   cout<<t[current_x][current_y].wartosc;
                   finish=true;
                   break;
               }

              else
              break;


              case 27: //ESC
              finish = true;
              break;

             case 224: //klawisze specjalne
               znak = getch();
               switch( znak )
               {
               case 72: //go up
                   --current_x;
                   if(current_x<0)
                   current_x=nowagra1.N-1;
                   break;

               case 80: //go down
                   ++aktualny_x;
                   if(current_x>nowagra1.N-1)
                  current_x=0;
                   break;
               case 75: //go left
                   --current_y;
                   if(current_y<0)
                   current_y=nowagra1.M-1;
                   break;
               case 77: //go right
                   ++current_y;
                   if(current_y>nowagra1.M-1)
                   current_y=0;
                   break;

               }
          }
  }

} 
0

Czyli punkty 1, 2, 3 z: http://4programmers.net/Forum/1239695 zwyczajnie olałeś?
Ok, już wiemy jak należy postępować z twoimi postami.

0
  1. "Ni należy używać i++ tam gdzie można użyć ++i" poprawiłem w kodzie po przeczytaniu różnic.
  2. Nie za bardzo rozumiem, chodzi Ci o wcięcia, odstępy itd?
  3. Wszystkie parametry i komentarze po angielsku?
1

Ad 1. for (int j = 0; j<nowagra1.M; j++) - nie wiem co i gdzie poprawiłeś
Ad 2. Pod linkiem przy punkcie w komentarzach automatyczny formater kodu od @kq
Ad 3.

młody_uczeń napisał(a):

Wszystkie parametry i komentarze po angielsku?
Zmienne/funkcje/typy/składowe tak, komentarze - wypadało by ale tu już możesz sobie darować (i pisać po polsku) na początek.

0

Ok, dzięki za wskazanie punktów :

 
struct field {
    int value;
    bool uncovered;
};

void go(field**& t, newgame& newgame1) // in newgame1 are only value to array size. N-verses, M-columns
{
    bool finish = false;
    int current_x = 0, current_y = 0;
    while (finish == false) {
        system("cls"); //clean the screen
        cout << current_x << "  " << current_y;
        cout << endl;

        cout << " ";
        for (int j = 0; j < newgame1.M; ++j)
            cout << "----";
        cout << endl;

        for (int i = 0; i < newgame1.N; ++i) {

            for (int j = 0; j < newgame.M; ++j) {
                if (j == 0)
                    cout << "| ";

                if (t[i][j].uncovered == true)
                    cout << t[i][j].value << " | ";
            }
            cout << '\n';
        }

        cout << " ";
        for (int j = 0; j < newgame1.M; ++j)
            cout << "----";
        cout << endl;

        unsigned char znak = getch();
        switch (znak) {

        case 13: //enter
              t[current_x][current_y].value=true;
              if (t[current_x][current_y].value == 9) {
                  cout << t[current_x][current_y].value;
                  finish = true;
                  break;
              }

              else
                  break;

        case 27: //ESC
            finish = true;
            break;

        case 224: // special keys
            znak = getch();
            switch (znak) {
            case 72: //go up
                --current_x;
                if (current_x < 0)
                    current_x = newgame1.N - 1;
                break;

            case 80: //go down
                ++aktualny_x;
                if (current_x > newgame1.N - 1)
                    current_x = 0;
                break;
            case 75: //go left
                --current_y;
                if (current_y < 0)
                    current_y = newgame1.M - 1;
                break;
            case 77: //go right
                ++current_y;
                if (current_y > newgame1.M - 1)
                    current_y = 0;
                break;
            }
        }
    }
}
0
  1. Po kiego przekazujesz poprzez referencje: field**& t, miało by sens jeżeli przydzielenie pamięci przenieść tu, czyli t=new ... a tak wystarczy samo field **t
  2. Wynieś rysowanie do innej funkcji
  3. Pokaż jak wygłada przydzielenie pamięci, podejrzewam że przydzielasz o jedną komórkę za mało.
  4. t[i][j].uncovered może mieć wartość true lub false ale nie możesz jak człowiek użyć w warunku t[i][j].uncovered więc używasz t[i][j].uncovered==true ale, t[i][j].uncovered==true może mieć wartość true lub false ale nie możesz użyć w warunku t[i][j].uncovered==true więc używasz (t[i][j].uncovered==true)==true ale, (t[i][j].uncovered==true)==true może mieć wartość true lub false ale nie możesz użyć w warunku (t[i][j].uncovered==true)==true więc używasz ((t[i][j].uncovered==true)==true)==true ale, ... mniej niż 16 powtórzeń jakoś zbyt mainstreamowo wygłada, to samo dotyczy finish, wystarczy: while(!finish)
1

A ja się jeszcze przyczepię do tzw. magic numbers w Twoim kodzie. Akurat w WinAPI do klawiszy masz https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx nie wiem w czym piszesz. Jeśli u Ciebie nie są dostępne stałe VK_xxx to już lepiej zrób sobie jakiegoś enuma i się nim posługuj. Nie będziesz musiał wtedy dawać komentarzy, że 27 to Esc itp.

0
_13th_Dragon napisał(a):

Po kiego przekazujesz poprzez referencje: field**& t, miało by sens jeżeli przydzielenie pamięci przenieść tu, czyli t=new ... a tak wystarczy samo field **t

  1. Wynieś rysowanie do innej funkcji
  2. Pokaż jak wygłada przydzielenie pamięci, podejrzewam że przydzielasz o jedną komórkę za mało.
  3. t[i][j].uncovered może mieć wartość true lub false ale nie możesz jak człowiek użyć w warunku t[i][j].uncovered więc używasz t[i][j].uncovered==true ale, t[i][j].uncovered==true może mieć wartość true lub false ale nie możesz użyć w warunku t[i][j].uncovered==true więc używasz (t[i][j].uncovered==true)==true ale, (t[i][j].uncovered==true)==true może mieć wartość true lub false ale nie możesz użyć w warunku (t[i][j].uncovered==true)==true więc używasz ((t[i][j].uncovered==true)==true)==true ale, ... mniej niż 16 powtórzeń jakoś zbyt mainstreamowo wygłada, to samo dotyczy finish, wystarczy: while(!finish)
  1. Wydawało mi się, że jak zmieniam wartości w tablicy to dobrym pomysłem było by pracowanie na jej oryginale niż na kopii ale za dobrze się nie czuję w referencji :/
  2. Done
 field** creatarray(newgame newgame1)
{
    field** t = new field*[newgame1.N];
    for (int i = 0; i < newgame1.N; ++i)
        t[i] = new field[newgame1.M];
    return t;
}
}

wydaje mi się, że dobrze jest stworzona ponieważ sprawdzałem po współrzędnych pól i wartości się zgadzały.
4. Masz rację, poprawiłem

0
Mr.YaHooo napisał(a):

A ja się jeszcze przyczepię do tzw. magic numbers w Twoim kodzie. Akurat w WinAPI do klawiszy masz https://msdn.microsoft.com/en-us/library/windows/desktop/dd375731%28v=vs.85%29.aspx nie wiem w czym piszesz. Jeśli u Ciebie nie są dostępne stałe VK_xxx to już lepiej zrób sobie jakiegoś enuma i się nim posługuj. Nie będziesz musiał wtedy dawać komentarzy, że 27 to Esc itp.

Niestety pierwszy raz słyszę o tych rzeczach :( zaraz postaram się poczytać o tym.

0
młody_uczeń napisał(a):

Niestety pierwszy raz słyszę o tych rzeczach :( zaraz postaram się poczytać o tym.
Piszę jako post, bo nie dostaniesz powiadomienia o komentarzu.

To akurat ważne i zwiększa czytelność programu. Dostałem kiedyś w spadku system po koledze który nawet enumy wbudowane w środowisko porównywał do intów. Tragicznie to się czytało. Pierwszą rzeczą jaką zrobiłem była zmiana na stałe symboliczne.

Tak samo jak chcesz iterować po kodach ascii to możesz posługiwać się tak:

for (int i = 'a'; i <= 'z'; i++)
{

}

O wiele fajniej się to czyta zamiast

for (int i = 97; i <= 122; i++)
{

}
0

Zamień nazewnictwo M/N na Y,X oraz te i,j iterujące po tablice na y,x - może tu gdzieś się kropnąłeś, bo jak zobaczysz i<costam.N to kod jak kod zaś jak zobaczysz x<costam.Y to od razu widać że coś nie gra.
Twój kod wyświetlający wygląda mi na całkiem błędny, powinno być coś na kształt:

for(size_t y=0;y<newgame1.Y;++y,cout<<'\n')
  {
   cout<<"| ";
   for(size_t x=0;x<newgame.X;++x)
     {
      if(t[i][j].uncovered) cout<<t[i][j].value;
      else cout<<' ';
      cout<<" | ";
     }
  }
0
_13th_Dragon napisał(a):

Zamień nazewnictwo M/N na Y,X oraz te i,j iterujące po tablice na y,x - może tu gdzieś się kropnąłeś, bo jak zobaczysz i<costam.N to kod jak kod zaś jak zobaczysz x<costam.Y to od razu widać że coś nie gra.
Twój kod wyświetlający wygląda mi na całkiem błędny, powinno być coś na kształt:

for(size_t y=0;y<newgame1.Y;++y,cout<<'\n')
  {
   cout<<"| ";
   for(size_t x=0;x<newgame.X;++x)
     {
      if(t[i][j].uncovered) cout<<t[i][j].value;
      else cout<<' ';
      cout<<" | ";
     }
  }

Pozmieniałem nazewnictwo, rzeczywiście błąd wynikał z kompletnie błędnego wyświetlania tablicy... Bardzo dziękuję za pomoc bo sam pewnie wciąż bym szukał nie tam gdzie trzeba.

_13th_Dragon, Mr.YaHooo dziękuję również za rady odnośnie samego stylu programowania, na pewno zacznę się ich trzymać bo to bardzo ułatwia pracę i przejrzystość kodu. Dziękuję Panom za pomoc :)

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