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

question-closed Nie działa zmienna statyczna mimo zadeklarowania.

Object Storage Arubacloud
0 głosów
192 wizyt
pytanie zadane 31 lipca 2019 w C i C++ przez Bill Jobs Nowicjusz (150 p.)
zamknięte 1 sierpnia 2019 przez Bill Jobs

Piszę sobie snake w konsoli, chciałem użyć zmiennych statycznych do określenia wymiarów planszy, lecz z nie wiadomego powodu nie działa. Pojawia się error że Board nie jest klasą lub przestrzenią nazw, a x i y są niezadeklarowanymi identyfikatorami. Error pojawia się w 135 linijce. Drugą sprawą jest to że że w 126 i 139 wyskakują ostrzeżenia z powodu niezgodności znaku, co powinienem zrobić żeby znikło?

 

#include <vector>
#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <windows.h>

enum side
{
	LEFT,
	RIGHT,
	DOWN,
	UP
};

class Windows
{
private:

public:
	static void ChangeColor(int x)
	{
		HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
		SetConsoleTextAttribute(hConsole, x);
	}
	static void Gotoxy(int x, int y) {
		if (x > 0 && y > 0) {
			COORD kursor;
			kursor.X = x-1;
			kursor.Y = y-1;
			SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), kursor);
		}
	}


};
class Point
{
private:
	int x, y;
public:
	Point(int x, int y)
	{
		this->x = x;
		this->y = y;
	}
	bool IsEqual(Point p)
	{
		if (this->x == p.x && this->y == p.y)
			return true;
		else
			return false;
	}
	int GetX()
	{
		return x;
	}

	int GetY()
	{
		return y;
	}

	void SetX(int x)
	{
		this->x = x;
	}

	void SetY(int y)
	{
		this->y = y;
	}
};
class Snake
	{
	private:
		std::vector<Point> Position;
	public:
		Snake(Point p)
		{
			Position.push_back(p);
		}
		void Move(side p)
		{
			std::vector<Point>::iterator it = Position.begin();
			Point P = *it;
			if (p == LEFT)
				P.SetX(P.GetX() - 1);
			if (p == RIGHT)
				P.SetX(P.GetX() + 1);
			if (p == DOWN)
				P.SetY(P.GetY() + 1);
			if (p == UP)
				P.SetY(P.GetY() - 1);


			Position.insert(Position.begin(), P);
			Position.pop_back();
			
		}
		void Grow(side p)
		{
			std::vector<Point>::iterator it = Position.begin();
			Point P = *it;
			if (p == LEFT)
				P.SetX(P.GetX() - 1);
			if (p == RIGHT)
				P.SetX(P.GetX() + 1);
			if (p == DOWN)
				P.SetY(P.GetY() + 1);
			if (p == UP)
				P.SetY(P.GetY() - 1);
			Position.insert(Position.begin(), P);
		}
		Point GivePositionHead()
		{
			std::vector<Point>::iterator it = Position.begin();
			return *it;
		}

		void Draw()
		{
			Windows::ChangeColor(35);

			for (int i = 0; i <= Position.size() - 1; i++)
			{
				Windows::Gotoxy(Position[i].GetX(), Position[i].GetY());
				std::cout << (char)219;
			}
			
		}
			bool IsTouch()
			{
				if (Position[0].GetX() > Board::x || Position[0].GetX() <= 0 || Position[0].GetY() > Board::y || Position[0].GetY() <= 0)
				{
					return true;
				}
				for (int i = 1; i < Position.size(); i++)
				{
					if (Position[0].GetX() == Position[i].GetX() || Position[0].GetY() == Position[i].GetY())
					return true;
					

				}

				return false;
			}
			

};

class Board
	{
		
	public:
		static int x, y;
		Board(int x, int y)
		{
			this->x = x;
			this->y = y;
		}
		Board()
		{
			x = 30;
			y = 30;
		}
		void Draw()
		{
			Windows::ChangeColor(60);
			Windows::Gotoxy(1,1);
			for (int i = 1; i <= x; i++)
			{
				for (int j = 1; j <= y; j++)
				{
					std::cout << (char)219;
				}
				std::cout << std::endl;
			}
			Windows::ChangeColor(11);
		}
	
};
bool IsRunning = true;
int main()
{
	while (IsRunning)
	{
		Board b(15, 15);
		Snake s(Point(7, 6));
		s.Grow(LEFT);
		s.Grow(UP);
		s.Grow(RIGHT);
		b.Draw();
		s.Draw();
		Sleep(1000);
	}

	return 0;
}

 

komentarz zamknięcia: najlepsza

1 odpowiedź

+1 głos
odpowiedź 31 lipca 2019 przez Storm088 Obywatel (1,460 p.)
edycja 1 sierpnia 2019 przez Storm088
 
Najlepsza

Kod po naprawieniu błędów i ostrzeżeń wygląda tak:

#include <vector>
#include <iostream>
#include <conio.h>
#include <stdio.h>
#include <windows.h>

enum side
{
    LEFT,
    RIGHT,
    DOWN,
    UP
};

class Windows
{
private:

public:
    static void ChangeColor(int x)
    {
        HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
        SetConsoleTextAttribute(hConsole, x);
    }
    static void Gotoxy(int x, int y) {
        if (x > 0 && y > 0) {
            COORD kursor;
            kursor.X = x-1;
            kursor.Y = y-1;
            SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE), kursor);
        }
    }


};
class Point
{
private:
    int x, y;
public:
    Point(int x, int y)
    {
        this->x = x;
        this->y = y;
    }
    bool IsEqual(Point p)
    {
        if (this->x == p.x && this->y == p.y)
            return true;
        else
            return false;
    }
    int GetX()
    {
        return x;
    }

    int GetY()
    {
        return y;
    }

    void SetX(int x)
    {
        this->x = x;
    }

    void SetY(int y)
    {
        this->y = y;
    }
};

class Board
    {

    public:
        static int x, y;
        Board(int x, int y)
        {
            this->x = x;
            this->y = y;
        }

        Board()
        {
            x = 30;
            y = 30;
        }
        void Draw()
        {
            Windows::ChangeColor(60);
            Windows::Gotoxy(1,1);
            for (int i = 1; i <= x; i++)
            {
                for (int j = 1; j <= y; j++)
                {
                    std::cout << (char)219;
                }
                std::cout << std::endl;
            }
            Windows::ChangeColor(11);
        }

};

int Board::x;
int Board::y;

class Snake
    {
    private:
        std::vector<Point> Position;
    public:
        Snake(Point p)
        {
            Position.push_back(p);
        }
        void Move(side p)
        {
            std::vector<Point>::iterator it = Position.begin();
            Point P = *it;
            if (p == LEFT)
                P.SetX(P.GetX() - 1);
            if (p == RIGHT)
                P.SetX(P.GetX() + 1);
            if (p == DOWN)
                P.SetY(P.GetY() + 1);
            if (p == UP)
                P.SetY(P.GetY() - 1);


            Position.insert(Position.begin(), P);
            Position.pop_back();

        }
        void Grow(side p)
        {
            std::vector<Point>::iterator it = Position.begin();
            Point P = *it;
            if (p == LEFT)
                P.SetX(P.GetX() - 1);
            if (p == RIGHT)
                P.SetX(P.GetX() + 1);
            if (p == DOWN)
                P.SetY(P.GetY() + 1);
            if (p == UP)
                P.SetY(P.GetY() - 1);
            Position.insert(Position.begin(), P);
        }
        Point GivePositionHead()
        {
            std::vector<Point>::iterator it = Position.begin();
            return *it;
        }

        void Draw()
        {
            Windows::ChangeColor(35);

            for (size_t i = 0; i <= Position.size() - 1; i++)
            {
                Windows::Gotoxy(Position[i].GetX(), Position[i].GetY());
                std::cout << (char)219;
            }

        }
            bool IsTouch()
            {
                if (Position[0].GetX() > Board::x || Position[0].GetX() <= 0 || Position[0].GetY() > Board::y || Position[0].GetY() <= 0)
                {
                    return true;
                }
                for (size_t i = 1; i < Position.size(); i++)
                {
                    if (Position[0].GetX() == Position[i].GetX() || Position[0].GetY() == Position[i].GetY())
                    return true;


                }

                return false;
            }


};

bool IsRunning = true;
int main()
{
    while (IsRunning)
    {
        Board b(15, 15);
        Snake s(Point(7, 6));
        s.Grow(LEFT);
        s.Grow(UP);
        s.Grow(RIGHT);
        b.Draw();
        s.Draw();
        Sleep(1000);
    }

    return 0;
}

Chodziło w błędach o to że m.in:

1.Klasa Board była pod klasą Snake.

2. Trzeba było zadeklarować zmienną x,y klasy Board na zewnątrz tej klasy jeśli chcesz wykorzystać static.

Za to przy ostrzeżeniach zapoznaj się z typami unsigned i powinno Ci się wyjaśnić.

Sam kod jest napisany z wykorzystaniem bardzo złych praktyk, które powinny zostać zniwelowane jednak nie chce mi się bawić w pisanie tego kodu, aby Ci wszystko wyjaśnić. Dlatego podam Ci pięć przykładów:

1.Po co for(int i = 0; i <= Position.size() - 1; i++) skoro for(int i = 0; i <Position.size() ; i++) działa tak samo

for (int i = 0; i <= Position.size() - 1; i++)
            {
                Windows::Gotoxy(Position[i].GetX(), Position[i].GetY());
                std::cout << (char)219;
            }

2.Pętle powinno dać się przerwać a tu pętla będzie wykonywana cały czas 

bool IsRunning = true;

    while (IsRunning)
    {
        Board b(15, 15);
        Snake s(Point(7, 6));
        s.Grow(LEFT);
        s.Grow(UP);
        s.Grow(RIGHT);
        b.Draw();
        s.Draw();
        Sleep(1000);
    }

3.Nie powinno się deklarować zmiennych globalnych.

bool IsRunning = true;

4.Tak nie powinno się "usypiać" programu poczytaj o wątkach 

Sleep(1000);

PS. exit(0); to również bardzo zła praktyka( wiem, że go nie użyłeś, ale wolę wspomnieć )

5.Dla czystości kodu powinieneś rozpisać go w osobnych plikach .h lub .hpp i .cpp bo tu jest istny misz-masz. Uwierz mi, że gdybyś chciał wrócić do tego kodu po jakimś czasie to byś się złapał za głowę i mówił, że nie jest czytelny, więc lepiej na przyszłość wyrobić sobie nawyk czystości kodu, bo przy większym projekcie niż ten może być naprawdę słabosad.

 

Mam nadzieje, że to pomoże, ale musisz jeszcze popracować nad niektórymi sprawami. Uwierz mi to ułatwi Ci życie. Powodzenia w dalszej pracy i trzymaj się

komentarz 31 lipca 2019 przez Bill Jobs Nowicjusz (150 p.)
Dziękuje bardzo. Z tym sleepem to przejściowo, planuje użyć biblioteki timer. A to co w funkcji main to narazie testowo i nic z tego nie zostanie gdy skończę pisać klasy. A propo pierwszego punktu czytałem ze < to jedna operacja a <= dwie, lecz nie uzwgledniłem że -1 to też operacja, a twój sposób wygląda czytelniej. Co polecasz zamiast tej zmiennej globalnej, stworzyć nową klasę, która będzie odpowiadała za pętle gry?

Ps. Próbowałem zmienić kolejność klas to też był chyba ten błąd, ale jeszcze jutro sprawdzę czy działa.

Ps2. Kompilowałeś to?
komentarz 31 lipca 2019 przez niezalogowany

Trochę się wtrącę: 

1. Działa tak samo - nawet lepiej, bo  gdy size() zwróci 0 to pętla mogłaby się wykonać się nawet kilka trylionów razy.

6.

Point GivePositionHead() {
		std::vector<Point>::iterator it = Position.begin();
		return *it;
	}

Po prostu:

Point GivePositionHead() {
    return Position.front(); 
}
komentarz 1 sierpnia 2019 przez Storm088 Obywatel (1,460 p.)
edycja 1 sierpnia 2019 przez Storm088

@Bill Jobs, 

1.Myślę, że główna klasa programu, która będzie odpowiadał za jego pętle będzie dobrym pomysłem.

2.Najwyraźniej po zmianie kolejności dalej źle były ustawione, poza tym trzeba było również:

2. Trzeba było zadeklarować zmienną x,y klasy Board na zewnątrz tej klasy jeśli chcesz wykorzystać static.

3.Tak kompilowałemsmiley

PS.Do "usypiania" programu najlepiej wykorzystaj wątki lub po prostu bibliotekę <chrono> (bardzo przydatna polecam).

komentarz 1 sierpnia 2019 przez Storm088 Obywatel (1,460 p.)

@Hipcio,  racja z powodu, że pisałem odpowiedź na szybko zapomniałem o tym, więc bardzo dobrze, że o tym wspomniałeś.

PS. Twój przykład jest również jednym z wielu rzeczy, które trzeba poprawić dobrze, że go podałeśyessmiley

Podobne pytania

0 głosów
1 odpowiedź 612 wizyt

92,570 zapytań

141,422 odpowiedzi

319,643 komentarzy

61,958 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!

...