(Un-)Sinn von Exceptions

Algorithmen, Sprachunabhängige Diskussionen zu Konzepten, Programmiersprachen-Design
Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 12:07 pm

Kerli hat geschrieben:Dann lassen wir das am Besten mit der Diskussion, weil ich glaub das würde sonst nie zu einem Ende kommen, bei diesen so verschiedenen Standpunkten ;)
Ich werde mir immer mal wieder Exceptions ansehen und gucken, was ich damit machen kann, genauso wie ich mir immer wieder andere Konstrukte neu ansehe.
Ich beschränke mich allerdings nicht darauf, mir Konstrukte anzusehen, die C++ oder andere Sprachen anbieten, sondern ich gucke mir auch Konstrukte an, die in keiner (mir bekannten) Sprache formulierbar sind und probiere aus, was damit machbar ist.
Ich habe zum Beispiel mal Funktionen ausprobiert, die vom Compiler (nicht vom Benutzer) gerufen werden, wenn gewisse Vorbedingunen erfüllt sind. Der Compiler pflanzt den Aufruf einfach vor oder hinter die Bedingung. Sehr praktisch, wenn man mal eben was zwischen den Code schreiben möchte, aber eben nicht 1000 Änderunge machen will. Spannend wird es, wenn der Compiler sich dann rekursiv aufruft. Dann landet man in einer Rekusions-Endlos-Schleife, die man nichtmals bewußt aufgerufen hat. Kann mir gut vorstellen, dass da einige Entwickler nicht verstehen, was sie da eigentlich tun.
Keine Ahnung, ob man das Sprachfeature auf die Menschheit loslassen kann, oder ob die Mehrzahl der Entwickler es nicht kapieren wird, es deswegen meist falsch angewendet wird und es später heißt, das ist wäre ein katastrophales Feature, das macht reihenweise Software kaputt.
Was auch passieren könnte ist, dass es als Meilenstein abstrakter Programmierung gefeiert wird, AOP gilt ja als der kommende Hype nach OOP.

Ich habe mir meine Gedanken gemacht, was man mit diesem Feature machen kann als ich es entwickelte, andere Entwickler werden es vielleicht für andere Dinge gebrauchen - oder missbrauchen.
Für mich zählt nur, ob das Feature mir das Leben vereinfacht oder nicht.
Exceptions vereinfachen mein Leben nur dann, wenn ich sie als Ausnahme benutze und nicht als Goto, wie es in der Regel verwendet wird.
Kerli hat geschrieben:Ich möchte aber nur noch anmerken, dass gerade bei meinem letzten Projekt ein Code vorgekommen ist wo ich wie in meinem Beispiel ein paar Speicheranforderungen direkt hintereinander gehabt habe, und da war es mit Exceptions sicher die schönere Lösung.
Schön... Du initialisiert Variablen vor, damit Du erkennen kannst, was Du anschließend wieder freigeben kannst. Ein vollkommen überflüssiger Schritt, aber das sind ja nur ein paar Takte, wie es immer nur ein paar Takte sind, die sich zu vielen Takten summieren... keine Ahnung, was daran schön ist, Variablen so zu manipulieren, dass man damit delete aufrufen kann, wenn man dafür keinen Speicher bekommen hat, delete also auch nicht rufen müsste. Für mich klingt das nicht schön, sondern überflüssig und Algorithmen, die überflüssige Dinge tun, fallen bei mir definitiv nicht in die Kategorie 'schön', das tendiert in meinem Verständnis eher in die Richtung 'falsch'.
Algorithmen, die Dinge tun, die für die Erledigung der Aufgabe unter den gegebenen Umständen nicht erforderlich sind, sind in meinen Augen falsch.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 2:19 pm

Xin hat geschrieben:
Kerli hat geschrieben:Ich möchte aber nur noch anmerken, dass gerade bei meinem letzten Projekt ein Code vorgekommen ist wo ich wie in meinem Beispiel ein paar Speicheranforderungen direkt hintereinander gehabt habe, und da war es mit Exceptions sicher die schönere Lösung.
Schön... Du initialisiert Variablen vor, damit Du erkennen kannst, was Du anschließend wieder freigeben kannst. Ein vollkommen überflüssiger Schritt, aber das sind ja nur ein paar Takte, wie es immer nur ein paar Takte sind, die sich zu vielen Takten summieren... keine Ahnung, was daran schön ist, Variablen so zu manipulieren, dass man damit delete aufrufen kann, wenn man dafür keinen Speicher bekommen hat, delete also auch nicht rufen müsste. Für mich klingt das nicht schön, sondern überflüssig und Algorithmen, die überflüssige Dinge tun, fallen bei mir definitiv nicht in die Kategorie 'schön', das tendiert in meinem Verständnis eher in die Richtung 'falsch'.
Algorithmen, die Dinge tun, die für die Erledigung der Aufgabe unter den gegebenen Umständen nicht erforderlich sind, sind in meinen Augen falsch.
Nein ich brauch am Anfang nur ein paar Speicherblöcke um das Programm zum Laufen zu bringen. Wenn ich diese Speicherblöcke nicht bekommen kann, dann ist mein Programm nicht in der Lage ordentlich zu Laufen. Und anstatt jetzt nach jeder Speicheranforderung zu kontrollieren ob ich den Speicher auch wirklich bekommen habe, überprüfe ich das mit einem catch Block, der um das ganze herum ist.

Hier ist noch der Code den ich gemeint habe:

Code: Alles auswählen

void GameHandler::run()
{
  /* ... */
  try
  {
    /* ... */
    bank_  = new Owner( "bank", START_CAPITAL_BANK );
    board_ = new Board( bank_ );

    // generate players with pieces
    for(int loop = 0; loop < PLAYER_COUNT; ++loop)
    {
      Player *new_player = new Player( PLAYER_NAMES[loop],
                                       START_CAPITAL_PLAYER );
      new_player->setPiece(
                   // piecename is first letter of playername
                   new Piece( PLAYER_NAMES[loop].at(0) ) );

      board_->setPieceToStart( new_player->getPiece() );

      // all players are not bankrupt at the beginn of a new game
      players_.push_back(        new_player );
      players_liquid_.push_back( new_player );
    }

    /* ... */
  }
  catch(std::bad_alloc&)
  {
    cout << msg_( "ERR_OUT_OF_MEM" ) << endl;
  }
  catch(std::exception& ex)
  {
    cout << msg_( "ERR_UNEXPECTED" )
           .setParam( "what", ex.what() ) << endl;
  }
  /* ... */
}
So ist es doch viel schöner gelöst, als jedes Mal kontrollieren, ob ich meinen Speicher bekommen habe.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 3:51 pm

@Kerli: Dein Code liefert den selben Informationswert, wie das Posting davor. Den Kommentar zu dem Code kannst Du meinen vorherigen Post entnehmen.
Meine Kritikpunkte finden sich in Deinem Code unter /* ... */.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 4:12 pm

Xin hat geschrieben:@Kerli: Dein Code liefert den selben Informationswert, wie das Posting davor. Den Kommentar zu dem Code kannst Du meinen vorherigen Post entnehmen.
Meine Kritikpunkte finden sich in Deinem Code unter /* ... */.
Naja, deine Kritik hat so ziemlich gar nichts mit dem Code aus meinem vorigen Posting zu tun. Und versuch einmal die gleiche Funktionalität ohne Exceptions hinzubekommen. Da würde dann nur eine Ansammlung von ifs herauskommen, was man mit Exceptions elegant umgehen kann.
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 4:34 pm

Kerli hat geschrieben:Meine Kritikpunkte finden sich in Deinem Code unter /* ... */.
Naja, deine Kritik hat so ziemlich gar nichts mit dem Code aus meinem vorigen Posting zu tun.[/quote]
?

Warum sagst Du mir nicht vorher, dass Du meine Postings nicht liest, dann brauch ich sie auch nicht zu schreiben.
Meinst Du ich sauge mir aus den Fingern, dass Du die Schwierigkeiten in die /* ... */ Bereiche verschiebst?

Sowas kotzt mich dann doch etwas an (man entschuldige die Wortwahl), den das macht jegliche Diskussion sinnfrei.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 4:42 pm

Xin hat geschrieben:Warum sagst Du mir nicht vorher, dass Du meine Postings nicht liest, dann brauch ich sie auch nicht zu schreiben.
Ich hab bis jetzt jeden Post gelesen...
Xin hat geschrieben: Meinst Du ich sauge mir aus den Fingern, dass Du die Schwierigkeiten in die /* ... */ Bereiche verschiebst?
Welche Probleme? In diesen Bereichen ist nur die Spiellogik drinnen, die absolut nichts mit dem Thema zu tun hat. Ich hab sie nur deshalb entfernt, damit der Codeausschnitt nicht zu lang wird.
Xin hat geschrieben: Sowas kotzt mich dann doch etwas an (man entschuldige die Wortwahl), den das macht jegliche Diskussion sinnfrei.
Gut, hier ist der ganze Code:

Code: Alles auswählen

void GameHandler::run()
  {
    //Generates objects and catch std::bad_alloc
    try
    {
      // if loading failed (quit_ = true) return.
      if( quit_ ) return;

      cout << msg_( "MSG_WELCOME" ) << endl;

      // init objects and print welcome message
      initObjects();

      //enable main loop
      quit_ = false;

      // reset ( for player bankruptcy )
      remove_current_player_   = false;

      // we want to use the chance and community fields
      enable_chance_community_ = true;

      //main loop
      do
      {
        if( next_player_ )
        {
          // get next player ( remove current one if needed and loop
          // through list )
          if( remove_current_player_ )
          {
            // remove player from the list of liquid players
            current_player_ = players_liquid_.erase( current_player_ );

            // only one player is left
            if( players_liquid_.size() <= 1 ) break;

            remove_current_player_ = false;
          }
          else
            ++current_player_;

          if( current_player_ == players_liquid_.end() )
            current_player_ = players_liquid_.begin();

          // reset for next player
          count_doubles_ = 0;
          next_player_   = false;

          //ask player in jail whether he wants to pay
          if( (*current_player_)->isInJail() )
          {
            // next round in jail
            (*current_player_)->stayOneMoreRoundInJail();

            if( askYesNo( msg_( "ASK_PAY_JAIL" )
                         .setParam( "player",
                                    (*current_player_)->getName() )
                         .setParam( "round",
                                    (*current_player_)
                                    ->getRoundsInJail() ) )  )
            {
              (*current_player_)->getAccount()
                                  ->transferTo( bank_->getAccount(),
                                                JAIL_PAY_VALUE );
              (*current_player_)->setFreeFromJail();

              cout << msg_( "MSG_LEAVE_JAIL" ) << endl;

              // check if player gets bankrupt through paying for the
              // jail
              if( !checkCurrentPlayerLiquid() ) continue;
            }
            else
            {
              //player does not want to pay
              cout << msg_( "MSG_JAIL_INFO" ) << endl;
            }
          } // if( (*current_player_)->isInJail() )
        } // if( next_player_ )

        nextCommand();

        // check for bankrupcy of the bank
        checkBankLiquid();


      } while( !quit_ );

      if( show_summary_ ) showSummary();

    }
    catch(std::bad_alloc&)
    {
      cout << msg_( "ERR_OUT_OF_MEM" ) << endl;
    }
    catch(std::exception& ex)
    {
      cout << msg_( "ERR_UNEXPECTED" )
             .setParam( "what", ex.what() ) << endl;
    }
  }
Und wo sind ja jetzt irgendwelche verschobenen Schwierigkeiten?
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 5:00 pm

Kerli hat geschrieben:Welche Probleme? In diesen Bereichen ist nur die Spiellogik drinnen, die absolut nichts mit dem Thema zu tun hat. Ich hab sie nur deshalb entfernt, damit der Codeausschnitt nicht zu lang wird.
Du hast die ganze Steuerungslogik entfernt, die notwendig ist, um die Objekte wieder abzubauen.
Kerli hat geschrieben:
Xin hat geschrieben: Sowas kotzt mich dann doch etwas an (man entschuldige die Wortwahl), den das macht jegliche Diskussion sinnfrei.
Gut, hier ist der ganze Code:
Und wo sind ja jetzt irgendwelche verschobenen Schwierigkeiten?
Wo werden die Objekte denn angelegt? Nirgendwo tritt ein new im Code auf. Kein new Board, kein new Owner, Wird das in initObjects() abgehalndelt? Wenn ja, wo werde die Objekte abgebaut?
Der Code hat keine Ähnlichkeit mit dem Code über den wir reden.

Aktuell fühle ich mich ein wenig veräppelt.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 5:10 pm

Xin hat geschrieben:
Kerli hat geschrieben:Welche Probleme? In diesen Bereichen ist nur die Spiellogik drinnen, die absolut nichts mit dem Thema zu tun hat. Ich hab sie nur deshalb entfernt, damit der Codeausschnitt nicht zu lang wird.
Du hast die ganze Steuerungslogik entfernt, die notwendig ist, um die Objekte wieder abzubauen.
Durch die Exceptions brauche ich keine ausgefallene Steuerungslogik, es reichen nur ein paar deletes:

Code: Alles auswählen

GameHandler::~GameHandler()
  {
    while( !players_.empty() )
    {
      delete players_.front()->getPiece();
      delete players_.front();
      players_.pop_front();
    }

    delete save_game_;
    delete bank_;
    delete board_;
    delete first_dice_;
    delete second_dice_;
    delete input_logger_;
  }
Und das ist alles...
Xin hat geschrieben:
Kerli hat geschrieben:
Xin hat geschrieben: Sowas kotzt mich dann doch etwas an (man entschuldige die Wortwahl), den das macht jegliche Diskussion sinnfrei.
Gut, hier ist der ganze Code:
Und wo sind ja jetzt irgendwelche verschobenen Schwierigkeiten?
Wo werden die Objekte denn angelegt? Nirgendwo tritt ein new im Code auf. Kein new Board, kein new Owner, Wird das in initObjects() abgehalndelt? Wenn ja, wo werde die Objekte abgebaut?
Hier werden die Objekte erzeugt:

Code: Alles auswählen

void GameHandler::initObjects()
  {
    // log inputs for generating testfiles
    // (open no file yet and disable logging)
    if( !input_logger_)
    input_logger_ = new InputLogger( "", false );

    first_dice_     = new Dice( time(0) );
    second_dice_    = new Dice( time(0) );

    // init random generator (maybe it hasn't if using testdices)
    srand( time(0) );

    // init scripting
    script_functions_[ "msg"      ] = &GameHandler::scriptMessage;
    script_functions_[ "transfer" ] = &GameHandler::scriptTransfer;
    script_functions_[ "jumpto"   ] = &GameHandler::scriptJumpTo;
    script_functions_[ "moveto"   ] = &GameHandler::scriptMoveTo;
    script_functions_[ "move"     ] = &GameHandler::scriptMove;

    script_variables_[ "debug"    ] = "0";

    if( save_game_ )
      initObjectsLoad();
    else
      initObjectsNew();
  }

  //--------------------------------------------------------------------
  void GameHandler::initObjectsNew()
  {
    bank_  = new Owner( "bank", START_CAPITAL_BANK );
    board_ = new Board( bank_ );

    // generate players with pieces
    for(int loop = 0; loop < PLAYER_COUNT; ++loop)
    {
      Player *new_player = new Player( PLAYER_NAMES[loop],
                                       START_CAPITAL_PLAYER );
      new_player->setPiece(
                   // piecename is first letter of playername
                   new Piece( PLAYER_NAMES[loop].at(0) ) );

      board_->setPieceToStart( new_player->getPiece() );

      // all players are not bankrupt at the beginn of a new game
      players_.push_back(        new_player );
      players_liquid_.push_back( new_player );
    }

    current_player_             = players_liquid_.begin();
  }

  //--------------------------------------------------------------------
  void GameHandler::initObjectsLoad()
  {
    XmlHandle root  ( save_game_->getRootElement() );

    bank_  = new Owner( "bank", root.firstChild("bank")
                                    .getAttribute("balance") );
    board_ = new Board( bank_ );


    //--------------
    // load players:
    //--------------

    XmlHandle current( root.firstChild( "current_player" ) );

    count_doubles_            = current.getAttribute( "doubles" );
    std::string current_player(
                          current.getAttribute<string>( "name" ) );

    XmlHandle player( root.firstChild("players").firstChild("player") );

    // set to default value
    current_player_ = players_liquid_.begin();

    // generate players with pieces
    while( player )
    {
      Player *new_player =
        new Player( player.getAttribute( "name"    ),
                    player.getAttribute( "balance" ) );

      new_player->setPiece(
                  new Piece( player.getAttribute<char>( "piece" ) ) );

      board_->getField( player.getAttribute("position") )
              ->addPiece( new_player->getPiece() );

      new_player->setRoundsInJail( player.getAttribute("jailrounds") );

      players_.push_back(          new_player );

      if( new_player->getAccount()->getBalance() >= 0 )
        players_liquid_.push_back( new_player );

      if( new_player->getName() == current_player )
        current_player_ = --players_liquid_.end();

      ++player;
    }

    //-------------
    // load fields:
    //-------------

    XmlHandle field( root.firstChild( "fields" ).firstChild( "field") );

    if( field )
    {
      do
      {
        BuyableField *load_field = dynamic_cast<BuyableField*>(
          board_->getField( field.getAttribute( "position" ) )  );

        if( !load_field ) continue;

        Player *owner = NULL;

        // search for owner in the list of liquid players
        for( std::list<Player*>::iterator it = players_liquid_.begin();
             it != players_liquid_.end(); ++it )
        {
          if( (*it)->getName() == field.getAttribute<string>("owner") )
          {
            owner = *it;
            break;
          }
        }

        if( !owner ) continue;

        load_field->setOwner( owner );
        load_field->setMortgaged( field.getAttribute("mortgaged") );

        // if morgaged reality worth only increased half the price
        if( load_field->getMortgaged() )
          owner->increaseRealityWorth( load_field->getPrice() / 2 );
        else
          owner->increaseRealityWorth( load_field->getPrice() );

        Street *street = dynamic_cast<Street*>( load_field );

        if( street )
        {
          street->setHouseCount( field.getAttribute("houses") );
          owner->increaseRealityWorth(   street->getHouseCount()
                                       * street->getHousePrice() );
        }

      }while( ++field );
    }
  }
Xin hat geschrieben: Der Code hat keine Ähnlichkeit mit dem Code über den wir reden.

Aktuell fühle ich mich ein wenig veräppelt.
So jetzt ist alles da, nichts versteckt...
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Benutzeravatar
Xin
nur zu Besuch hier
Beiträge: 8858
Registriert: Fr Jul 04, 2008 11:10 pm
Wohnort: /home/xin
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Xin » So Jul 27, 2008 5:47 pm

Kerli hat geschrieben:
Xin hat geschrieben:
Kerli hat geschrieben:Welche Probleme? In diesen Bereichen ist nur die Spiellogik drinnen, die absolut nichts mit dem Thema zu tun hat. Ich hab sie nur deshalb entfernt, damit der Codeausschnitt nicht zu lang wird.
Du hast die ganze Steuerungslogik entfernt, die notwendig ist, um die Objekte wieder abzubauen.
Durch die Exceptions brauche ich keine ausgefallene Steuerungslogik, es reichen nur ein paar deletes:
....
Und das ist alles...
...das will ich nicht hoffen, ansonsten fliegt Dir der Code im Fehlerfall um die Ohren.
Kerli hat geschrieben:
Xin hat geschrieben:Der Code hat keine Ähnlichkeit mit dem Code über den wir reden.
So jetzt ist alles da, nichts versteckt...
Vorher war's der ganze Code, jetzt ist nichts versteckt, wo ist der Konstruktor, wo sind die Variablendeklarationen?
Aus dem Code ist nicht nachvollziehbar, ob er funktioniert oder im Fehlerfall abschmiert.
Merke: Wer Ordnung hellt ist nicht zwangsläufig eine Leuchte.

Ich beantworte keine generellen Programmierfragen per PN oder Mail. Dafür ist das Forum da.

Benutzeravatar
Kerli
Beiträge: 1456
Registriert: So Jul 06, 2008 10:17 am
Wohnort: Österreich
Kontaktdaten:

Re: (Un-)Sinn von Exceptions

Beitrag von Kerli » So Jul 27, 2008 5:56 pm

Xin hat geschrieben:
Kerli hat geschrieben: Durch die Exceptions brauche ich keine ausgefallene Steuerungslogik, es reichen nur ein paar deletes:
....
Und das ist alles...
...das will ich nicht hoffen, ansonsten fliegt Dir der Code im Fehlerfall um die Ohren.
Warum? Wenn eines der news fehlschlägt, wird der restliche Code nicht mehr ausgeführt, und nachher alles im Destruktur wieder gelöscht.
Xin hat geschrieben:
Kerli hat geschrieben:
Xin hat geschrieben:Der Code hat keine Ähnlichkeit mit dem Code über den wir reden.
So jetzt ist alles da, nichts versteckt...
Vorher war's der ganze Code, jetzt ist nichts versteckt, wo ist der Konstruktor, wo sind die Variablendeklarationen?
Aus dem Code ist nicht nachvollziehbar, ob er funktioniert oder im Fehlerfall abschmiert.
Er funktioniert, wir haben so ziemlich jeden Fehlerfall und auch einiges automatisch getestet, und auch unser Tutor hat nichts gefunden :)
Soll ich wirklich alles posten? Das wären dann so ca. 4000 Zeilen Code...
"Make it idiot-proof and someone will invent an even better idiot." (programmers wisdom)

OpenGL Tutorials und vieles mehr rund ums Programmieren: http://www.tomprogs.at

Antworten