Konsolen Snake, aber die globalen Variablen stören mich...

Snake92

Grünschnabel
Hi,
ich bin neu im Forum und habe erst letzte Woche angefangen mit dem Programmieren von C++.

Habe mich nun an ein Snake gewagt und dieses denke ich mal auch ganz gut hinbekommen. Allerdings stören mich die globalen Variablen und ich würde gerne wissen:
Was gibt es für eine Möglichkeit die globalen Variablen zu entfernen.

Ich habe einen Win7 Professional 64 bit System und verwende MS Visual C++ Express 2010.

Ich Danke für jede Hilfe. Bei Rückfragen einfach Fragen :)

C++:
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <windows.h>
#include <conio.h>
#include <time.h>

int Field();
int Head();
int Snake(int Eingabe, int KopfX, int KopfY);
int Fruit(int KopfX, int KopfY);
int Score();
int GameBreak(int Pause);
int GameOver(int Verloren, int KopfX, int KopfY);

int KoerperX;
int KoerperY;
int FruchtX = 4;
int FruchtY = 4;
int Verloren = 1;
int Schlange = 1;
int Richtung[600];

int main()
{
    Field();
    Head();

    std::cin.clear();
    std::cin.ignore(std::cin.rdbuf()->in_avail());
    std::cin.get();

    return 0;
}

int Field()
{
    COORD Feld;
    Feld.X = 0;

    for (int x=0;x<23;x++)
    {
        Feld.Y = x-1;

        if (Feld.Y==0)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"________________________________",32,Feld,0);

        else if (Feld.Y>=1&&Feld.Y<=20)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"|                              |",32,Feld,0);

        else if (Feld.Y==21)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",32,Feld,0);
    }
    COORD Cursor = {0,23};
    SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),Cursor);
   
    COORD Score = {33,10};
    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"Score: ",7,Score,0);

    return 0;
}

int Head()
{
    int Richtung = 97;
    int Eingabe = 32;
    COORD Kopf = {15,10};

    while (Verloren)
    {   
        STOP:
        if (_kbhit())
            Eingabe = _getch();

        if (Eingabe==32||Eingabe==0)
        {
            GameBreak(1);
            goto STOP;
        }

        else if (Eingabe!=32)
            GameBreak(0);

        if (Eingabe==97&&Richtung==100)
            Eingabe=100;

        else if (Eingabe==100&&Richtung==97)
            Eingabe=97;

        else if (Eingabe==115&&Richtung==119)
            Eingabe=119;

        else if (Eingabe==119&&Richtung==115)
            Eingabe=115;

        switch (Eingabe)
        {
        case 97:
            Kopf.X--;
            if (Kopf.X==0)
                Kopf.X=30;
            Richtung = 97;
            break;

        case 100:
            Kopf.X++;
            if (Kopf.X==31)
                Kopf.X=1;
            Richtung = 100;
            break;

        case 115:
            Kopf.Y++;
            if (Kopf.Y==21)
                Kopf.Y=1;
            Richtung = 115;
            break;

        case 119:
            Kopf.Y--;
            if (Kopf.Y==0)
                Kopf.Y=20;
            Richtung = 119;
            break;
        }

        int KopfX = Kopf.X;
        int KopfY = Kopf.Y;

        Snake(Richtung, KopfX ,KopfY);
        Fruit(KopfX, KopfY);
        Score();

        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"O",1,Kopf,0);

        Sleep(75);
    }
   
    return 0;
}

int Snake(int Eingabe, int KopfX, int KopfY)
{
    COORD Koerper;
    COORD Loesche;

    for(int n=600;n>0;n--)
    {
        Richtung [n] = Richtung [n-1];
    }
    Richtung [0] = Eingabe;

    KoerperX = KopfX;
    KoerperY = KopfY;

    for(int n=0;n<Schlange;n++)
    {   
        switch (Richtung [n])
        {
            case 97:
                KoerperX++;
                if (KoerperX==31)
                    KoerperX=1;
                break;

            case 100:
                KoerperX--;
                if (KoerperX==0)
                    KoerperX=30;
                break;

            case 115:
                KoerperY--;
                if (KoerperY==0)
                    KoerperY=20;
                break;

            case 119:
                KoerperY++;
                if (KoerperY==21)
                    KoerperY=1;
                break;
        }
        Loesche.X = KoerperX;
        Loesche.Y = KoerperY;
        Koerper.X = KoerperX;
        Koerper.Y = KoerperY;

        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"o",1,Koerper,0);

        if (KoerperX==KopfX&&KoerperY==KopfY)
            Verloren = 0;
    }
    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE)," ",1,Loesche,0);

    GameOver(Verloren, KopfX, KopfY);

    return 0;
}

int Fruit(int KopfX, int KopfY)
{
    COORD Frucht;
   
    if (KopfX==FruchtX&&KopfY==FruchtY)
    {
        srand((unsigned)time(NULL));
        FruchtX = rand()%30;
        FruchtY = rand()%20;
       
        if (FruchtX==0)
        {
            FruchtX = 1;
        }
       
        if (FruchtY==0)
        {
            FruchtY = 1;
        }
       
        Schlange++;
    }

    Frucht.X = FruchtX;
    Frucht.Y = FruchtY;

    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"X",1,Frucht,0);
   
    return 0;
}

int Score()
{
    int PunkteWert=Schlange-1;
    COORD Score = {40,10};
   
    std::stringstream strs;
      strs << PunkteWert;
      std::string temp_str = strs.str();
    char* char_type = (char*) temp_str.c_str();
    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),char_type,3,Score,0);
   
    if (PunkteWert<10)
    {
        COORD Score = {42,10};
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE)," ",1,Score,0);
    }
   
    return 0;
}

int GameBreak(int Pause)
{
    COORD SpielPause = {12,22};
   
    if (Pause==1)
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"-Pause-",7,SpielPause,0);

    else if (Pause==0)
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"       ",7,SpielPause,0);

    return 0;
}

int GameOver(int Verloren, int KopfX, int KopfY)
{
    int Ende = 5;
    COORD Dead = {12,22};
    COORD Kopf = {KopfX,KopfY};

    if (Verloren==0)
    {
        while(Ende)
        {
            Sleep(150);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"         ",9,Dead,0);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"O",1,Kopf,0);
            Sleep(75);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"X",1,Kopf,0);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"Game Over",9,Dead,0);
            Ende--;
        }
    }

    return 0;
}
 
Hi und Willkommen bei tutorials.de,

vor einer Woche angefangen? Nicht schlecht :eek:

Da du schon Funktionsparameter verwendest, frag ich mich aber, wo das Problem liegt?
Die derzeitigen globalen Variablen könnten im main gemacht und auch als Parameter verteilt werden.

Drei Sachen, die mir grad auffallen:

Soll es C oder C++ werden?

Das return 0; und der Returntyp int statt void ist sinnlos, falls es nur dafür da ist, um eben 0 zu returnen. Wenn man der aufrufenden Stelle nichts mitteilen will kann das weg. Nur bei main machts Sinn, das ist ein Sonderfall.

EIn goto, das zum Schleifenanfang (der dort einzigen oder innersten Schleife) springen soll, kann einfach mit continue; ersetzt werden. Ohne Label. Dann muss man als Leser das Label nicht suchen :p
Bzw., continue springt eigentlich vor die Schleife, so dass die Bedingung auch wieder ausgewertet wird (was bei deiner Platzierung vom Label ja nicht passiert). Aber in deinem Fall sollte das keinen Unterschied machen; die Variable Verloren ändert sich ja bis zum goto nicht (falls es ausgeführt wird)
 
Zuletzt bearbeitet:
Danke für die schnelle Antwort.

Für KoerperX,Y, FruchtX,Y, Verloren und Richtung[600] kann ich das vielleicht einbringen in main, habe ich wohl übersehen.
Für Schlange Probiere ich nochmal und sende dann den Code falls ich was herausbekommen habe.

Soll C++ werden, habe ich da etwa irgendwo etwas unbewusst in C-Stil geschrieben?

Okay, dass mit void habe ich jetzt endlich verstanden, hatte den Sinn vorher nicht ganz verstanden (hat mir oft Fehler ausgeworfen).

Hast du vielleicht mal ein Beispiel für das continue;? Würde da gerne die Funktion verstehen lernen.
 
Soll C++ werden, habe ich da etwa irgendwo etwas unbewusst in C-Stil geschrieben?
Von den einzelnen Befehlen usw. passt eigentlich alles.
Bzw. die Windows-spezifischen Funktionen wie WriteConsoleOutputCharacter gibts nur im C-Stil,
da kann man eh nichts anderes machen und alles wo man die Wahl hat schaut C++-mäßig aus.

(Im größeren Maßstab könnte man etwas Objektorientierung verwenden,
aber das eilt nicht, wenn man erst eine Woche dabei ist)

Okay, dass mit void habe ich jetzt endlich verstanden, hatte den Sinn vorher nicht ganz verstanden (hat mir oft Fehler ausgeworfen).
Der Returnwert ist ja nur sowas wie ein "Gegenparameter": So, wie die Funktionsparameter von außen in die Funktion reinkommen kann die Funktion auch wieder etwas nach außen zurückgeben. Wenn das bei einer Funktion aber immer nur "Null, Null, Null..." ist, ohne das sich daran was ändert, macht das eben keinen Sinn. Und "void" bedeutet an der Stelle eben einfach "kein Returnwert". Dann darf es auch kein return irgendwas;, sonst bekommt man Compilerfehler (umgekehrt, kein void aber auch kein return, sollte auch zumindest gewarnt werden)

Hast du vielleicht mal ein Beispiel für das continue;? Würde da gerne die Funktion verstehen lernen.
Ziemlich einfach (Zeile 9, 16 und 17 anders):
C++:
int Head()
{
    int Richtung = 97;
    int Eingabe = 32;
    COORD Kopf = {15,10};

    while (Verloren)
    {   
//      STOP:				// *************** Das hier weg 
        if (_kbhit())
            Eingabe = _getch();

        if (Eingabe==32||Eingabe==0)
        {
            GameBreak(1);
//          goto STOP;					// *************** Das hier weg 
			continue;					// *************** Dafür das.
			//Ist eben nur sowas wie goto, das immer zum Anfang der aktuellen Schleife geht
        }

        else if (Eingabe!=32)
            GameBreak(0);

        if (Eingabe==97&&Richtung==100)
            Eingabe=100;

        else if (Eingabe==100&&Richtung==97)
            Eingabe=97;

        else if (Eingabe==115&&Richtung==119)
            Eingabe=119;

        else if (Eingabe==119&&Richtung==115)
            Eingabe=115;

        switch (Eingabe)
        {
        case 97:
            Kopf.X--;
            if (Kopf.X==0)
                Kopf.X=30;
            Richtung = 97;
            break;

        case 100:
            Kopf.X++;
            if (Kopf.X==31)
                Kopf.X=1;
            Richtung = 100;
            break;

        case 115:
            Kopf.Y++;
            if (Kopf.Y==21)
                Kopf.Y=1;
            Richtung = 115;
            break;

        case 119:
            Kopf.Y--;
            if (Kopf.Y==0)
                Kopf.Y=20;
            Richtung = 119;
            break;
        }

        int KopfX = Kopf.X;
        int KopfY = Kopf.Y;

        Snake(Richtung, KopfX ,KopfY);
        Fruit(KopfX, KopfY);
        Score();

        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"O",1,Kopf,0);

        Sleep(75);
    }
 
Da ist jetzt mein veränderter Code habe aber noch das Problem, dass ich das Array Richtung[600] nicht vernünftig hin bekomme der haut mir ständig Fehler raus oder wenn es zu kompilieren geht haut der ne Windows Fehlermeldung raus... Beim Debuggen konnte ich da auch nichts brauchbares feststellen.

Gibt es da vielleicht einen Weg?

Nach meinem Programm muss ich das Array außerhalb der while Schleife initialisieren und dann während der Schleife in eine int() Funktion übertragen und die Werte von dort wieder zurück an das ursprüngliche Array außerhalb der Schleife bringen.

Zeile 17(int Richtung[600],
Zeile 140 (Dort wäre die mögliche Übertragen zur int() Funktion),
Zeilen 150-194 (Benutzung des Array zum setzen des Körpers)

Ich kann das Array nicht in der Funktion Snake() initialisieren da er dann keine Richtung ab dem zweiten Körperteil hat.

C++:
#include <iostream>
#include <sstream>
#include <cstdlib>
#include <windows.h>
#include <conio.h>
#include <time.h>

void Field();
void Head();
int Snake(int Eingabe, int KopfX, int KopfY, int Schlange, int Verloren, int KoerperX, int KoerperY, int *ZeigerX, int *ZeigerY);
int Fruit(int KopfX, int KopfY, int Schlange, int *ZeigerX, int *ZeigerY);
void Score(int Schlange);
void GameBreak(int Pause);
void GameOver(int Verloren, int KopfX, int KopfY);

int Richtung[600];

class FRUIT
{
public:
    int Schlange;
    int FruchtX;
    int FruchtY;
};

int main()
{
    Field();
    Head();

    std::cin.clear();
    std::cin.ignore(std::cin.rdbuf()->in_avail());
    std::cin.get();

    return 0;
}

void Field()
{
    COORD Feld;
    Feld.X = 0;

    for (int x=0;x<23;x++)
    {
        Feld.Y = x-1;

        if (Feld.Y==0)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"________________________________",32,Feld,0);

        else if (Feld.Y>=1&&Feld.Y<=20)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"|                              |",32,Feld,0);

        else if (Feld.Y==21)
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~",32,Feld,0);
    }
    COORD Cursor = {0,23};
    SetConsoleCursorPosition (GetStdHandle(STD_OUTPUT_HANDLE),Cursor);
  
    COORD Score = {33,10};
    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"Score: ",7,Score,0);
}

void Head()
{
    int FruchtX = 4;
    int FruchtY = 4;
    int KoerperX = 0;
    int KoerperY = 0;
    int Schlange = 1;
    int Richtung = 97;
    int Eingabe = 32;
    int Verloren = 1;
    int *ZgrKoerperX = &KoerperX;
    int *ZgrKoerperY = &KoerperY;
    int *ZgrFruchtX = &FruchtX;
    int *ZgrFruchtY = &FruchtY;
    COORD Kopf = {15,10};

    while (Verloren)
    {  
        if (_kbhit())
            Eingabe = _getch();

        if (Eingabe==32||Eingabe==0)
        {
            GameBreak(1);
            continue;
        }

        else if (Eingabe!=32)
            GameBreak(0);

        if (Eingabe==97&&Richtung==100)
            Eingabe=100;

        else if (Eingabe==100&&Richtung==97)
            Eingabe=97;

        else if (Eingabe==115&&Richtung==119)
            Eingabe=119;

        else if (Eingabe==119&&Richtung==115)
            Eingabe=115;

        switch (Eingabe)
        {
        case 97:
            Kopf.X--;
            if (Kopf.X==0)
                Kopf.X=30;
            Richtung = 97;
            break;

        case 100:
            Kopf.X++;
            if (Kopf.X==31)
                Kopf.X=1;
            Richtung = 100;
            break;

        case 115:
            Kopf.Y++;
            if (Kopf.Y==21)
                Kopf.Y=1;
            Richtung = 115;
            break;

        case 119:
            Kopf.Y--;
            if (Kopf.Y==0)
                Kopf.Y=20;
            Richtung = 119;
            break;
        }

        int KopfX = Kopf.X;
        int KopfY = Kopf.Y;

        Verloren = Snake(Richtung, KopfX ,KopfY, Schlange, Verloren, 0, 0, ZgrKoerperX, ZgrKoerperY);
        Schlange = Fruit(KopfX, KopfY, Schlange, ZgrFruchtX, ZgrFruchtY);
        Score(Schlange);

        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"O",1,Kopf,0);

        Sleep(75);
    }
}

int Snake(int Eingabe, int KopfX, int KopfY, int Schlange, int Verloren, int KoerperX, int KoerperY, int *ZeigerX, int *ZeigerY)
{
    COORD Koerper;
    COORD Loesche;

    KoerperX = *ZeigerX;
    KoerperY = *ZeigerY;

    for(int n=600;n>0;n--)
    {
        Richtung [n] = Richtung [n-1];
    }
    Richtung [0] = Eingabe;

    KoerperX = KopfX;
    KoerperY = KopfY;

    for(int n=0;n<Schlange;n++)
    {  
        switch (Richtung [n])
        {
            case 97:
                KoerperX++;
                if (KoerperX==31)
                    KoerperX=1;
                break;

            case 100:
                KoerperX--;
                if (KoerperX==0)
                    KoerperX=30;
                break;

            case 115:
                KoerperY--;
                if (KoerperY==0)
                    KoerperY=20;
                break;

            case 119:
                KoerperY++;
                if (KoerperY==21)
                    KoerperY=1;
                break;
        }
        Loesche.X = KoerperX;
        Loesche.Y = KoerperY;
        Koerper.X = KoerperX;
        Koerper.Y = KoerperY;
        *ZeigerX = KoerperX;
        *ZeigerY = KoerperY;

        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"o",1,Koerper,0);

        if (KoerperX==KopfX&&KoerperY==KopfY)
            Verloren = 0;
    }

    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE)," ",1,Loesche,0);

    GameOver(Verloren, KopfX, KopfY);

    return Verloren;
}

int Fruit(int KopfX, int KopfY, int Schlange, int *ZeigerX, int *ZeigerY)
{
    int FruchtX = *ZeigerX;
    int FruchtY = *ZeigerY;
  
    COORD CoordFrucht;

    if (KopfX==FruchtX&&KopfY==FruchtY)
    {
        srand((unsigned)time(NULL));
        FruchtX = rand()%30;
        FruchtY = rand()%20;
      
        if (FruchtX==0)
        {
            FruchtX = 1;
        }
      
        if (FruchtY==0)
        {
            FruchtY = 1;
        }
      
        Schlange++;
    }
        CoordFrucht.X = FruchtX;
        CoordFrucht.Y = FruchtY;
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"X",1,CoordFrucht,0);

        *ZeigerX = FruchtX;
        *ZeigerY = FruchtY;

        return Schlange;
}

void Score(int Schlange)
{
    int PunkteWert=Schlange-1;
    COORD Score = {40,10};
  
    std::stringstream strs;
      strs << PunkteWert;
      std::string temp_str = strs.str();
    char* char_type = (char*) temp_str.c_str();
    WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),char_type,3,Score,0);
  
    if (PunkteWert<10)
    {
        COORD Score = {42,10};
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE)," ",1,Score,0);
    }
}

void GameBreak(int Pause)
{
    COORD SpielPause = {12,22};
  
    if (Pause==1)
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"-Pause-",7,SpielPause,0);

    else if (Pause==0)
        WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"       ",7,SpielPause,0);
}

void GameOver(int Verloren, int KopfX, int KopfY)
{
    int Ende = 5;
    COORD Dead = {12,22};
    COORD Kopf = {KopfX,KopfY};

    if (Verloren==0)
    {
        while(Ende)
        {
            Sleep(150);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"         ",9,Dead,0);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"O",1,Kopf,0);
            Sleep(75);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"X",1,Kopf,0);
            WriteConsoleOutputCharacter (GetStdHandle(STD_OUTPUT_HANDLE),"Game Over",9,Dead,0);
            Ende--;
        }
    }
}
 
Hallo und willkommen!
Ich habe mir deinen Quelltext nur auf die schnelle überflogen, von daher wären weitere Ratschläge sinnvoll.
Was mir aber direkt aufgefallen ist:
while(Ende) (Zeile 287) ist meiner Meinung nach eher unsauber. Man verlässt sich dort auf die implizite Konvertierung von int auf bool und muss dabei auch wissen, dass 0 als false und alles andere als true bewertet wird.
Schöner ist daher while(Ende > 0) oder while(Ende != 0).

"Richtung" hat Platz für 600 Elemente, wenn du int Richtung[600]; schreibst. Unten verwendest du im Zugriff allerdings Richtung[n=600] = ... in Zeile 158ff. Da Arrays 0-index-basiert sind, kannst du nur auf die Elemente [0..599] zugreifen. Alles andere ist undefiniert. Vielleicht passiert gar nichts, vielleicht etwas seltsames oder vielleicht stürzt dein Programm ab. Solche Probleme werden dir in C++ häufiger begegnen ;)

Statt
C++:
class FRUIT
{
public:
    int Schlange;
    int FruchtX;
    int FruchtY;
};
kannst du auch (aus meiner Sicht schöner)
C++:
struct FRUIT
{
    int Schlange;
    int FruchtX;
    int FruchtY;
};
schreiben. Der Unterschied zwischen einem struct und einer class sind zT marginal. Die Entscheidung hier ein struct statt eine class zu nehmen ist eine Design Frage. Funktional hier egal.

Viele Grüße
K


#edit: Ich finde deinen Quelltext für eine Woche neu dabei sein schon ausgesprochen gut. Nicht das du meine kleinen Vorschläge oben falsch verstehst ;)
 
Vielleicht lag es an den "n=600" jetzt funktioniert es auf jeden Fall. Dies sind die Änderungen

C++:
void Head()
{
    int ARichtung[600];
    ...
    int *ZgrRichtung=new int [600];
    ...
  
    for (int n=599;n>0;n--)
    {
        ZgrRichtung[n] = ARichtung[n];
    }
  
    while (Verloren!=0)
    ...
    Verloren = Snake(Richtung, KopfX ,KopfY, Schlange, Verloren, 0, 0, ZgrKoerperX, ZgrKoerperY, ZgrRichtung);
    ...
}

int Snake(int Eingabe, int KopfX, int KopfY, int Schlange, int Verloren, int KoerperX, int KoerperY, int *ZeigerX, int *ZeigerY, int Richtung[600])
{
    ...
    for(int n=599;n>0;n--)
    {
        Richtung [n] = Richtung [n-1];
    }
    Richtung [0] = Eingabe;
    ...
}

Habe auch bei den zwei while Schleifen die Design Änderung angenommen und statt class --> struct genommen.

Danke für die tollen Tipps!

Falls gewollt kann ich auch nochmal den ganzen Code hochladen.
Für Verbesserungen der Programmierung bin ich immer zu haben.

Mein Ziel ist es irgendwann Richtung Spieleprogrammierung zu kommen, was wäre da sinnvoll weiter zu machen? Ich weiß ja dass es sehr lange dauert und auch viel Erfahrung benötigt, daher die Frage des nächsten Gebietes.
- Sollte es eher Richtung Windows Fenster gehen?
- Oder eher in Richtung von Grafik?
- Oder Vielleicht irgend etwas, dass ich jetzt nicht auf dem Schirm habe?
 
Hallo Snake92,
zuerst mal muss ich kickerxy123 zustimmen, dein Code ist für einen Anfänger wirklich sehr sauber und gut formatiert. Viele Anfänger achten darauf noch nicht besonders, aber wenn du ein Programm entwirfst verbringst du die meiste Zeit damit, alte Code-Passagen zu lesen. Deshalb: Je lesbarer du den Code schreibst, desto effizienter kannst du später damit arbeiten :D.

Da dein eigentliches Problem ja mittlerweile gelöst ist, brauche ich dazu nichts mehr zu schreiben. Aber du hast noch weitere Fragen gestellt, deshalb möchte ich dir kurz meine Erfahrungen erläutern.
Mein Ziel ist es irgendwann Richtung Spieleprogrammierung zu kommen, was wäre da sinnvoll weiter zu machen?
Naja, wer nicht programmieren kann, kann logischerweise auch keine Spiele programmieren... ;)
Also wenn du in die Richtung gehen möchtest kommst du wohl nicht darum herum.
Ich weiß ja dass es sehr lange dauert und auch viel Erfahrung benötigt, [...]
Absolut! Ich muss dir gestehen, dass ich damals auch mit dem Ziel Spiele zu programmieren in die C/C++-Welt eingestiegen bin. Mir hatte man damals auch versichert, dass das sehr viel Zeit braucht bis man da "ein Ergebnis sieht". In meiner jugendlichen Naivität dachte ich dann so: Ach komm, das dauert 4-6 Monate und dann läuft das Zeuch, vielleicht kann man ja sogar ein paar Exemplare davon verkaufen?
Ich habe dann aber ziemlich schnell gemerkt, dass man wirklich Jahre - viele Jahre - Erfahrung und Weiterbildung braucht, um sinnvoll Spiele entwickeln zu können. Ich möchte dir kurz den Entstehungsprozess eines Computerspieles skizzieren, damit du ungefähr siehst worauf es ankommt:

Die Hardware-Entwickler bauen Grafikkarten mit sogenannten Vektorprozessoren, die für die Verarbeitung großer vektorisierbarer Datenmengen (z.B. 3D-Koordinaten) konzipiert sind.
Die Treiber-Entwickler des Herstellers implementieren für die gängigen Plattformen (z.B. Windows, Linux, OS) die vom DirectX-Standard (und meist auch vom OpenGL-Standard, wobei die Funktionen nahezu die gleichen sind) geforderten Funktionen. Eine grobe Übersicht darüber, findest du hier: https://msdn.microsoft.com/en-us/library/windows/hardware/ff570595(v=vs.85).aspx
Die Implementierung erfolgt hier in C oder sogar Assembler.
Die Treiber-Entwickler des Betriebssystems schreiben Treiber, die diese Funktionen ansprechen können und stellen ein Interface dazu bereit (damit ist eine standardisierte Schnittstelle wie DirectX oder OpenGL gemeint). Diese Treiber sind fast immer in C geschrieben, deshalb steht dieses Interface auch "nur" in C oder C++ zur Verfügung. Der Vorteil ist: Man hat einen Standard, und kann damit alle Grafikkarten von jedem Hersteller ansprechen.
Die Engine-Entwickler des Spieleherstellers benutzen die Grafikschnittstelle um ein Grundgerüst (sog. Framework) zu schaffen, das in der Lage ist bestimmte Modell-, Textur-, und sonstige Spiel-Dateien zu laden und anzuzeigen. Außerdem kümmert sich die Engine um Ton, um die Interaktion mit dem Benutzer (durch Tastatur, Controller, etc.), um Netzwerkkommunikation und um sonst jeden Kram der beim Spielen anfällt. Da die Schnittstellen meistens nur in Form von C-Funktionen vorliegen, wird beim Schreiben der Engine oft C++ eingesetzt (da es einerseits nicht so maschinennah wie C ist, und andererseits objektorientiert(!!) ist). Wie du siehst, sind alle performancekritischen Teile eines Spiels in C/C++ geschrieben. Damit aber die Entwicklung des Spiels einfacher ist, wird hierfür meistens keine Programmiersprache, sondern eine Skriptsprache verwendet. Gängig ist z.B., dass die Engine ein Lua-Skript aufruft und dann über Lua angesteuert wird. Es gibt aber auch Engines (z.B. Panda3D), bei denen der C-Teil als Bibliothek für z.B. Python exportiert wird. Die "Skriptsprache" ist dann Python, von dem aus man auf alle Funktionen der Engine zugreifen kann.
Die Spiele-Entwickler des Spieleherstellers entwickeln oder besser entwerfen nun ein Spiel, mit einer Geschichte, einer Handlung und allem drum und dran.
Die Spiele-Programmierer setzen dieses Spiel dann um, indem sie die Spiellogik und den Ablauf mit Hilfe der Engine programmieren. Dabei machen sie extensiven Gebrauch von den vorgefertigten Funktionen der Engine (z.B. irgendwas wie "LoadModel("../Models/model.mod");"). Außerdem arbeiten sie in enger Zusammenarbeit mit
den Spiele-Designern. Diese entwerfen die Modelle, die Texturen, die Spielwelten, usw. Sie kümmern sich um die gesamte Grafik, um den Ton und alles was sonst noch so anfällt (z.B. Menüs).
Und schließlich kommt am Schluss noch das Marketing und ggf. das Merchandise dazu.

Das ist natürlich nur ein grober Überblick, aber ich wollte dir deutlich machen wie lange die Entwicklungskette eigentlich ist. Jede einzelne Station stellt eine ganze Berufsgruppe dar, und oftmals werden in jedem Bereich solide Grundkenntnisse verlangt. Wenn du an der Entwicklung eines Spiels sitzt, und z.B. die o.g. Funktion "LoadModel(...);" aufrufst, dann wandert dein Befehl diese ganze Kette runter. Bis in den Vektorprozessor der Grafikkarte hinein. Je mehr du also über die gesamte Kette weißt, ein desto besserer Programmierer bist du (und damit begehrter am Markt). Vor allem wenn du vorhast alles alleine zu machen (was imho verrückt ist :)) musst du dich mit all diesen Sachen beschäftigen ---> jede Menge Zeitaufwand.
Ich denke aber, es ist ein guter erster Schritt, wenn du deine C++-Kenntnisse ausbaust. Du scheinst zwar schnell zu lernen, aber es wird trotzdem Monate dauern bis du allein die Standard-Bib von C++11 kannst (das ist keine Warnung, du sollst dir das bloß vor Augen halten). Danach wird wohl noch boost kommen, dann vielleicht mal OpenGL, naja, das musst du dann sehen. Du kannst ja zum Glück immer nachfragen wenn dir mal etwas unklar ist.

[...] daher die Frage des nächsten Gebietes.
- Sollte es eher Richtung Windows Fenster gehen?
- Oder eher in Richtung von Grafik?
- Oder Vielleicht irgend etwas, dass ich jetzt nicht auf dem Schirm habe?
Wenn du nur Spiele-Programmierer werden willst brauchst du über Fenster und Grafik nur die Basics. Falls du vorhast auch an Teilen der Engine mitzuwirken isses einfach: beides :p.
Und die Sachen die du noch nicht auf'm Schirm hast, um die kümmern wir uns wenn es soweit ist.

Ich hoffe ich habe dich jetzt nicht verschreckt, ich wollte dir bloß zeigen dass es wirklich lange dauert und viel Erfahrung erfordert.

Gruß Technipion
 
Und für die nächsten größeren Sachen zB. ...
Objektorientierung,
bisschen was über Patterns,
wie Technipion sagt das Wissen über die C++-Lib und paar weitere Sprachfeatures selber
(das Inhaltsverzeichnis von zB. http://en.cppreference.com/w/ durchmachen
um einigermaßen einen Überblick zu bekommen, was es gibt),
Themen der Plattformunabhängigkeit können auch nicht schaden
(int-größen, float-Datenformate, ordentliche struct-Serialisierung usw.usw.)...

Sorry, alles noch unabhängig von Spielen oder überhaupt Grafik :D
 
Zuletzt bearbeitet:
@ technipion
danke für diese aufschlüsselung hatte das ganze schon kurz mal überflogen auf nem wiki und dort stand auch dass es bei großen teams ca 5 jahre dauert für ein modernes solides spiel und die pprogrammierarbeit an sich nur vill 10 leute in die hand nehmen und der rest dann grafiker usw machen

@sheel
Danke für diese weiteren themen dann weiß ich jetzt wo ich weiter lernen sollte und kann mir dazu passende tutorials suchen und ich denke dieses thema hier ist dann auch beendet fürs erste.
 
Zurück