Testowy kod z pętlami nie działa.

1

Witam, napisałem ten kod poniżej i skompilowałem do programu konsolowego.
To jest taki mój testowy kod dla gierki strategicznej. Trzeba tam wybrać pole podając koordynaty X oraz Y. Pola są zmiennymi typu int, które mogą reprezentować puste pole (0) lub pole z numerem pionka (1-25).

Jak to powinno działać?
Kiedy wybiorę int area[x][y] wpisując koordynaty, program sprawdza wartość tego pole. Jeśli jest puste (0), program wyświetla mi błąd i powtarza pytanie o koordynaty. Jeśli wartość jest od 1 do 25, program sprawdza puste pola dookoła tego wybranego i prosi mnie o wybranie pustego pola obok, do którego ma przenieść się mój pionek.

Jak to aktualnie działa?
Jeśli wybiorę area[x][y], program informuje mnie o błędzie niezależnie od tego, czy wybrane pole wynosi 0, czy 1-25.

Z góry dzięki za pomoc. :)

Poniższy kod:

#include <iostream>
#include <cstdlib>
#include <windows.h>
#include <time.h>
#include <stdio.h>
#include <iomanip>
#include <conio.h>

using namespace std;

int area[15][15];
int armour[15][15];
int damage[15][15];
int soldier[5];
int vehicle[5];
int tank[5];
int cannon[5];
int rocket[5];
int counter, i, x, y;
bool up;
bool down;
bool l;
bool r;
bool lup;
bool rup;
bool ldown;
bool rdown;

int main()
{
    for (counter = 0; counter <= 4; counter += 1)
    {
        soldier[counter] = counter + 1;
        vehicle[counter] = counter + 6;
        tank[counter] = counter + 11;
        cannon[counter] = counter + 16;
        rocket[counter] = counter + 21;
    }

    for (x = 0; x <= 14; x += 1)
    {
        area[x][13] = 1;
    }

    for (x = 0; x <= 2; x += 1)
    {
        area[x][14] = 6;
    }

    for (x = 3; x <= 4; x += 1)
    {
        area[x][14] = 11;
    }

    for (x = 5; x <= 6; x += 1)
    {
        area[x][14] = 16;
    }

    area[7][14] = 21;

    for (x = 8; x <= 9; x += 1)
    {
        area[x][14] = 16;
    }

    for (x = 10; x <= 11; x += 1)
    {
        area[x][14] = 11;
    }

    for (x = 12; x <= 14; x += 1)
    {
        area[x][14] = 6;
    }

    for (y = 0; y <= 14; y += 1)
    {
        if (y < 10)
        {
            cout << "| Y" << y << "  |";
        }
        else
        {
            cout << "| Y" << y << " |";
        }
        for (x = 0; x <= 14; x += 1)
        {
            if (area[x][y] < 10)
            {
                cout << "| " << area[x][y] << "  |";
            }
            else
            {
                cout << "| " << area[x][y] << " |";
            }
        }
        cout << endl;
    }
    cout << endl << "       ";
    for (x = 0; x <= 14; x += 1)
    {
        if (x < 10)
        {
            cout << "| X" << x << " |";
        }
        else
        {
            cout << "| X" << x << "|";
        }
    }
    cout << endl << endl;

    for (y = 0; y <= 14; y += 1)
    {
        for (x = 0; x <= 14; x += 1)
        {
            if (area[x][y] = 0)
            {
                armour[x][y] = 0;
                damage[x][y] = 0;
            }
            else if (area[x][y] >= 1 && area[x][y] <= 5)
            {
                armour[x][y] = area[x][y];
                damage[x][y] = area[x][y];
            }
            else if (area[x][y] >= 6 && area[x][y] <= 10)
            {
                armour[x][y] = (area[x][y] - 6) * 2;
                damage[x][y] = (area[x][y] - 6) * 2;
            }
            else if (area[x][y] >= 11 && area[x][y] <= 15)
            {
                armour[x][y] = (area[x][y] - 11) * 3;
                damage[x][y] = (area[x][y] - 11) * 3;
            }
            else if (area[x][y] >= 16 && area[x][y] <= 20)
            {
                armour[x][y] = (area[x][y] - 16) * 4;
                damage[x][y] = (area[x][y] - 16) * 4;
            }
            else if (area[x][y] >= 21 && area[x][y] <= 25)
            {
                armour[x][y] = (area[x][y] - 21) * 5;
                damage[x][y] = (area[x][y] - 21) * 5;
            }
        }
    }

    cout << "Choose area (X): ";
    cin >> x;
    cout << endl;
    cout << "Choose area (Y): ";
    cin >> y;
    cout << endl << endl;

    while (area[x][y] == 0)
    {
        cout << "ERROR! Chosen area can not be equal to 0!" << endl << endl;
        cout << "Choose area (X): ";
        cin >> x;
        cout << endl;
        cout << "Choose area (Y): ";
        cin >> y;
        cout << endl << endl;
    }

    if (area[x][y] > 0 && area[x][y] <= 20)
    {
        up = false;
        down = false;
        l = false;
        r = false;
        lup = false;
        rup = false;
        ldown = false;
        rdown = false;
        if (area[x][y-1] == 0)
        {
            up = true;
        }
        if (area[x+1][y-1] == 0)
        {
            rup = true;
        }
        if (area[x+1][y] == 0)
        {
            r = true;
        }
        if (area[x+1][y+1] == 0)
        {
            rdown = true;
        }
        if (area[x][y+1] == 0)
        {
            down = true;
        }
        if (area[x-1][y+1] == 0)
        {
            ldown = true;
        }
        if (area[x-1][y] == 0)
        {
            l = true;
        }
        if (area[x-1][y-1] == 0)
        {
            lup = true;
        }
    }

    cout << "You can move: " << endl;

    if (up == true)
    {
        cout << "up" << endl;
    }
    if (rup == true)
    {
        cout << "up right" << endl;
    }
    if (r == true)
    {
        cout << "right" << endl;
    }
    if (rdown == true)
    {
        cout << "down right" << endl;
    }
    if (down == true)
    {
        cout << "down" << endl;
    }
    if (ldown == true)
    {
        cout << "down left" << endl;
    }
    if (l == true)
    {
        cout << "left" << endl;
    }
    if (lup == true)
    {
        cout << "up left" << endl;
    }
    return 0;
}

Dodatkowe info:
Środowisko programowania: Code::Blocks v20.03
Język: C++
Kompiler: GNU GCC Compiler

1

Ło matko boska programistyczna, sformatuj ten kod, używaj jakiś switchów itd.

7

Robisz podstawienie

 if (area[x][y] = 0)

zamiast porównania

 if (area[x][y] == 0)
5

Jesteś początkujący więc robisz sporo prostych błędów, które czynią kod trudny w pisaniu, czytaniu i poprawianiu.
Są prsote sposoby, by to porpawić (w tej chwili nie będę uzaadniał każdego punktu, boargumenty będą dla ciebie za trudne, więc na razie uwierz mi na słowo):

  1. Nie używać zmiennych globalnych.
  2. Jeśli używasz tablic, to po to by po nich "iterować" (czyli używać ich z jakąś pętlą i indeksem) a nie, żeby ręcznie pisać indeksy.
  3. Nie używać liczb magicznych - czy nigdy bezpośrednio w kodzie nie pisać literałów - zamiast tego definiować odpowiednią stałą.
  4. dziel kod na mniejsze części - funkcje! Nie pisz wszystkiego w main! Osobna funkcja na wczytywanie danych, osobna na ich wypisanie, osobne funkcje na kolejne kroki przeliczeń danych.

I jeszcze najważniejsze, naucz się używać debuggera. Im więcej sie umie tym mniej się go używa, ergo początkujący powinien go używać w zasadzie bez przerwy. To jest nie tylko narzędzie do wyszukiwania błędów w kodzie, ale też doskonałe narzędzie demontujące jak działają poszczególne funkcjonalności języka.

1

nie wiem czym to budujesz ale wpisz w google debbuger c++. I prześledź działanie krok po kroku.

0
MarekR22 napisał(a):

Jesteś początkujący więc robisz sporo prostych błędów, które czynią kod trudny w pisaniu, czytaniu i poprawianiu.
Są prsote sposoby, by to porpawić (w tej chwili nie będę uzaadniał każdego punktu, boargumenty będą dla ciebie za trudne, więc na razie uwierz mi na słowo):

  1. Nie używać zmiennych globalnych.
  2. Jeśli używasz tablic, to po to by po nich "iterować" (czyli używać ich z jakąś pętlą i indeksem) a nie, żeby ręcznie pisać indeksy.
  3. Nie używać liczb magicznych - czy nigdy bezpośrednio w kodzie nie pisać literałów - zamiast tego definiować odpowiednią stałą.
  4. dziel kod na mniejsze części - funkcje! Nie pisz wszystkiego w main! Osobna funkcja na wczytywanie danych, osobna na ich wypisanie, osobne funkcje na kolejne kroki przeliczeń danych.

I jeszcze najważniejsze, naucz się używać debuggera. Im więcej sie umie tym mniej się go używa, ergo początkujący powinien go używać w zasadzie bez przerwy. To jest nie tylko narzędzie do wyszukiwania błędów w kodzie, ale też doskonałe narzędzie demontujące jak działają poszczególne funkcjonalności języka.

Szczerzę mówiąc, trochę się nie zgadzam z pewnymi kwestiami, do pewnych bym coś dodał, a więc:

Ad. 1 Głupotą jest w kółko podawanie zasady "nie używaj zmiennych globalnych" bez głębszego wytłumaczenia dlaczego nie. Ogólnie przyjęte jest, że globalnych zmiennych powinno się unikać ze względu na drastyczne zmniejszanie czytelności kodu bo nie wiadomo na pierwszy rzut oka (a nawet i na drugi) w których miejscach jest jej nadpisywanie oraz czytanie pomijając kwestię data race... W większości przypadkach raczej przekazuje się takie rzeczy przez parametry niemniej jednak są sytuacje gdy globalne zmienne idealnie się nadają np. kod w pytaniu w tym wątku (nie tyczy się to wszystkich zmiennych) lub sytuacje, gdy przez parametry przekazujemy 999 rzeczy no bo w końcu "nie używaj globalnych zmiennych" gdzie w miejsce dłuuugiej listy parametrów zrobienie zmiennej z globalnym scope byłoby znacznie bardziej klarowne.

Ad. 2 Tutaj chciałbym tylko dodać, że kod napisany jest w C++ i można użyć takiej magicznej rzeczy jak std::array.

Ad. 3 Ogólnie tak, świetnie nadaję się do tego constexpr z C++17 lub consteval z C++20 niestety nie wiadomo jakiego standardu językowego używa twórca wątku.

Ad. 4 Również się zgodzę ale warto dodać (szczególnie tłumacząc coś dla osoby początkującej) aby nie przesadzać w stronę dzielenia wszystkiego na osobne funkcje.

Ad Post Scriptum (?) No i co do tego mam bardzo mieszane uczucia bardziej analiza kodu i nauka myślenia jak kompilator zaowocuje w przyszłości aniżeli debugowanie tak prostego kodu, o ile debuggera również używa się aby jakoś przeanalizować działanie programu w runtime to jestem zdania, że samodzielna analiza zwłaszcza tak prostego kodu i wychwycenie błędu przyniesie znacznie bardziej owocne rezultaty w postaci nauki myślenia jak kompilator o której wspominałem wyżej i satysfakcję. Dodam jeszcze, że osobiście debuggera używam w 99% przypadkach kiedy zdarza mi się błąd trudny lub niemożliwy do wychwycenia po prostu patrząc na kod np. błąd związany z żywotnością.

Pozdrawiam i zachęcam do dyskusji

1

Ad 1.:
Jeszcze inaczej — read only zmienne globalne są może nieładne, ale bywają regularnie najlepszym możliwym rozwiązaniem; a większość prób ich obejścia, jakie widziałem, nie miały żadnych praktycznych zalet nad nimi. Zmienne globalne, do których coś zapisujemy to recepta na katastrofę, bo rozwalają lokalne rozumowanie — nagle to, co zrobi dana funkcja zależy od tego, co dzieje się na przeciwnym końcu programu, co mogło się stać wcześniej albo nie, a nawet może się dziać równocześnie, i teraz dochodź biedny programisto, kiedy tak jest, a kiedy nie…

Ad PS:
Ja mam ten problem, że nigdy się nie nauczyłem dobrze używać gdb na właśnie takim prostym kodzie, bo mi zawsze do prostych projektów wystarczała statyczna analiza kodu (w głowie), ew. mogłem kogoś zapytać, kto mi w moment był w stanie powiedzieć, w czym tkwi problem. Efekt? Nie umiem teraz dobrze używać gdb i jak napotykam kod, który przekracza moją zdolność do analizy, to mam do dyspozycji tylko absolutnie najprostsze narzędzia, a o tych wszystkich magicznych możliwościach typu makra albo nie wiem wcale, albo wiem co najwyżej, że istnieją…

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