Eure Meinung (Snake C++)



  • Hallo an alle,
    ich programmiere noch nicht so lange C++ und würde gern eure Meinungen und Verbesserungsvorschläge zum Aufbau, Programmierstill usw. hören.
    Ich habe es mit MVC++ 2008 Express Edition geschrieben.
    Der Code ist etwas umfangreich 😉 :

    #include <iostream>
    #include <conio.h>
    #include <string>
    #include <ctime>
    #include <windows.h>
    #include <deque>
    #include <string>
    
    #define UP 'w'
    #define DOWN 's'
    #define LEFT 'a'
    #define RIGHT 'd'
    #define ESC 27
    
    using namespace std;
    
    struct Pos_t
    {
      int x,y;
      bool operator ==(Pos_t& pos)
      {
        return pos.x==x && pos.y==y;
      }
    };
    
    class Spielfeld_t //Singleton
    {
      Pos_t Spielfeld;
      Spielfeld_t(int x,int y){
        Spielfeld.x=x;
        Spielfeld.y=y;
      }
      static Spielfeld_t* instance;
    public:
      static Spielfeld_t* getInstance();
      int getSizeX();
      int getSizeY();
      void draw();
    };
    
    class Futter_t
    {
      Pos_t pos;
      char Zeichen;
    public:
      Futter_t(){
        Zeichen='X';
      }
      void set(int x,int y);
      Pos_t getPos();
      void draw();
    };
    
    class Snake_t
    {
    protected:
      deque<Pos_t> pos;
    private:
      int Laenge;
      char Koerper;
      char Kopf;
    public:
      void set(int x,int y,int laenge,char koerper,char kopf);
      void move(char r);
      void draw();
      bool istKollision(Futter_t &f);
      bool istKollision(Snake_t &s);
      bool istAufWand();
      void fressen(){Laenge++;}
    };
    
    class Profil_t
    {
      string Name;
      int Punkte;
    public:
      Profil_t(std::string name);
      string getName();
      int getPunkte();
      void addPunkte(int n);
      void show();
    };
    
    class Highscore_t
    {
      std::deque<Profil_t*> Profile;
    public:
      void Add(Profil_t* profil);
      void show();
      ~Highscore_t(){
        std::deque<Profil_t*>::iterator i;
       for (i = Profile.begin(); i != Profile.end(); ++i)
         delete *i;
      }
    };
    
    class Screen_t //Singleton
    {
      char Screen[200][200];
      int xSize,ySize;
      Screen_t(){}
      static Screen_t* instance;
    public:
      static Screen_t* getInstance();
      void clear();
      void init(int x,int y);
      void set(int x,int y,char c);
      void show();
    };
    
    void gotoXY(int x, int y) {
    	HANDLE hStdout; 
    	COORD coordScreen = { 0, 0 }; 
    	hStdout = GetStdHandle(STD_OUTPUT_HANDLE); 
    
    	coordScreen.X = x;
    	coordScreen.Y = y;
    	SetConsoleCursorPosition( hStdout, coordScreen );
    }
    
    //------------------------Screen_t----------------------------------------
    
    Screen_t* Screen_t::instance=0;
    
    Screen_t* Screen_t::getInstance()
    {
      if(!instance)
        instance=new Screen_t();
      return instance;
    }
    
    void Screen_t::clear()
    {
      for(int x=0;x<=xSize;x++){
        for(int y=0;y<=ySize;y++){
          Screen[x][y]=' ';
        }
      }
    }
    
    void Screen_t::init(int x,int y)
    {
      xSize=x;
      ySize=y;
    }
    
    void Screen_t::set(int x,int y,char c)
    {
      Screen[x][y]=c;
    }
    
    void Screen_t::show()
    {
      gotoXY(0,0);
      for(int y=0;y<=ySize;y++){
        for(int x=0;x<=xSize;x++){
          cout<<Screen[x][y];
        }
        cout<<endl;
      }
    }
    
    //------------------------Spielfeld_t----------------------------------------
    
    const int SpielfeldX=40;
    const int SpielfeldY=20;
    
    Spielfeld_t* Spielfeld_t::instance=0;
    
    Spielfeld_t* Spielfeld_t::getInstance()
    {
      if(!instance)
        instance=new Spielfeld_t(SpielfeldX,SpielfeldY);
      return instance;
    }
    
    int Spielfeld_t::getSizeX()
    {
      return Spielfeld.x;
    }
    
    int Spielfeld_t::getSizeY()
    {
      return Spielfeld.y;
    }
    
    void Spielfeld_t::draw()
    {
      Screen_t* Screen=Screen_t::getInstance();
      for(int x=0;x<=Spielfeld.x;x++){
        Screen->set(x,0,'-');
        Screen->set(x,Spielfeld.y,'-');
      }
      for(int y=0;y<=Spielfeld.y;y++){
        Screen->set(0,y,'|');
        Screen->set(Spielfeld.x,y,'|');
      }
    }
    
    //------------------------Futter_t----------------------------------------
    
    void Futter_t::set(int x,int y)
    {
      pos.x=x;
      pos.y=y;
    }
    
    Pos_t Futter_t::getPos()
    {
      return pos;
    }
    
    void Futter_t::draw()
    {
      Screen_t* Screen=Screen_t::getInstance();
      Screen->set(pos.x,pos.y,Zeichen);
    }
    
    //------------------------Snake_t----------------------------------------
    
    void Snake_t::set(int x, int y, int laenge, char koerper,char kopf)
    {
      pos.clear();
      Pos_t p;
      p.x=x;
      p.y=y;
      pos.push_front(p);
      Laenge=laenge;
      Koerper=koerper;
      Kopf=kopf;
    }
    
    void Snake_t::move(char r)
    {
      Pos_t p=pos[0];
      switch(r)
      {
      case UP:
        p.y-=1;
        break;
      case DOWN:
        p.y+=1;
        break;
      case RIGHT:
        p.x+=1;
        break;
      case LEFT:
        p.x-=1;
        break;
      }
      pos.push_front(p);
      if(pos.size()>(unsigned int)Laenge)
        pos.pop_back();
    }
    
    void Snake_t::draw()
    {
      Screen_t* Screen=Screen_t::getInstance();
      for(unsigned int i=0;i<pos.size();i++){
        if(!i){
          Screen->set(pos[i].x,pos[i].y,Kopf);
        }
        else{
          Screen->set(pos[i].x,pos[i].y,Koerper);
        }
      }
    }
    
    bool Snake_t::istKollision(Futter_t &f)
    {
      return pos[0]==f.getPos();
    }
    
    bool Snake_t::istAufWand()
    {
      Spielfeld_t* Spielfeld=Spielfeld_t::getInstance();
      return pos[0].x==0
        || pos[0].x==Spielfeld->getSizeX()
        || pos[0].y==0
        || pos[0].y==Spielfeld->getSizeY();
    }
    
    bool Snake_t::istKollision(Snake_t &s)
    {
      bool Kollision=false;
      for(unsigned int i=1;i<s.pos.size();i++)
        if(s.pos[i]==s.pos[0])
          Kollision=true;
      return Kollision;
    }
    
    //------------------------Profil_t----------------------------------------
    
    Profil_t::Profil_t(string name) : Name(name),Punkte(0)
    {
      cout<<"Profil "<<Name<<" erstellt"<<endl;
    }
    
    string Profil_t::getName()
    {
      return Name;
    }
    
    int Profil_t::getPunkte()
    {
      return Punkte;
    }
    
    void Profil_t::addPunkte(int n)
    {
      Punkte+=n;
    }
    
    void Profil_t::show()
    {
      cout<<"Spieler "<<Name<<" : "<<Punkte<<" Punkte."<<endl;
    }
    
    //------------------------Highscore_t----------------------------------------
    
    void Highscore_t::Add(Profil_t *profil)
    {
      Profile.push_front(profil);
    }
    
    void Highscore_t::show()
    {
      int max=0;
      for(unsigned int i=0;i<Profile.size();i++){
        if(Profile[i]->getPunkte()>max){
          max=Profile[i]->getPunkte();
        }
      }
      deque<Profil_t*> p;
      for(int r=0;r<=max;r++){
        for(unsigned int i=0;i<Profile.size();i++){
          if(r==Profile[i]->getPunkte()){
            p.push_front(Profile[i]);
          }
        }
      }
      for(unsigned int i=0;i<p.size();i++){
        cout<<i+1<<". :";
        p[i]->show();
      }
    }
    
    //------------------------main----------------------------------------
    
    void setFutter(Futter_t &f);
    
    void showIntro();
    
    int main()
    {
      showIntro();
      srand((unsigned int)time(0));
      Spielfeld_t *Spielfeld=Spielfeld_t::getInstance();
      Screen_t* Screen=Screen_t::getInstance();
      Screen->init(Spielfeld->getSizeX(),Spielfeld->getSizeY());
      Futter_t futter;
      setFutter(futter);
      Snake_t snake;
      Highscore_t highscore;
      char key;
      do{
        system("cls");
        cout<<"Bitte geben sie ihren Namen ein :"<<endl;
        string name;
        getline(cin,name);
        Profil_t* profil=new Profil_t(name);
        highscore.Add(profil);
        snake.set(20,10,4,'x','O');
        key=UP;
        while(true)
        {
          Screen->clear();
          if(_kbhit()){
            key=_getch();
          }
          snake.move(key);
          if(snake.istKollision(futter)){
            setFutter(futter);
            snake.fressen();
            profil->addPunkte(1);
          }
          if(snake.istAufWand()){
            cout<<"Snake hat die Wand gerramt !"<<endl;
            _getch();
            system("cls");
            break;
          }
          if(snake.istKollision(snake)){
            cout<<"Snake hat sich angefressen !"<<endl;
            _getch();
            system("cls");
            break;
          }
          futter.draw();
          snake.draw();
          Spielfeld->draw();
          Screen->show();
          cout<<profil->getPunkte();
          Sleep(100);
        }
        highscore.show();
        getchar();
        system("cls");
        cout<<"Um das Spiel zu beenden Esc druecken !"<<endl
          <<"Um ein neues Spiel zu starten Enter druecken !"<<endl;
      }while(_getch()!=ESC);
      cout<<"S N A K E  C L O N E\n"<<endl;
      _getch();
      delete Screen;
      return 0;
    }
    
    void setFutter(Futter_t &f)
    {
      Spielfeld_t* Spielfeld=Spielfeld_t::getInstance();
      f.set(rand()%(Spielfeld->getSizeX()-2)+2,
        rand()%(Spielfeld->getSizeY()-2)+2);
    }
    
    void showIntro()
    {
      char IntroText[]="S N A K E  C L O N E\n"
        "\nSteuerung mit \n"
        "w, a, s und d";
      for(int i=0;i<sizeof(IntroText);i++){
        Sleep(100);
        cout<<IntroText[i];
      }
      getchar();
      system("cls");
    }
    


  • Funktioniert gut! Weiter so!

    Anmerkungen:

    bool Snake_t::istKollision(Futter_t &f)
    {
     Pos_t p=f.getPos();
      return pos[0]==f.getPos();
     && pos[0].y==p.y;
    }
    

    Hier willst du sicherlich das Semikolon hinter f.getPos() wegmachen. Sollte der Compiler in der Form auch nicht schlucken.

    void addPunkte(int n);

    Entscheide dich für eine Sprache (am besten Englisch).

    Generell wäre eine Unterteilung des Codes in Header- (.h) und Implementierungsdateien (.cpp) besser, da übersichtlicher.

    Bugs habe ich nur einen gefunden: Das Futter kann auch innerhalb der Schlange spawnen.



  • danke für den Beitrag 😃


Anmelden zum Antworten