Collections (vorerst nur Listen)
Übersicht![](/themes/Standard/arrow.png)
![](/themes/Standard/arrow.png)
![]() |
DAKBetreff: Collections (vorerst nur Listen) |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich habe ja wo anders versprochen, dass ich mich um eine DLL für Listen und Maps kümmere. Zu den Maps bin ich noch nicht gekommen, aber die Listen sind fertig und funktionieren toll.
Mal als Erstes den Download-Link (5 kb): https://www.blitzforum.de/upload/file.php?id=12885 Jetzt zur Verwendung: Der Einfachheit halber habe ich nur einen Listentyp gemacht: Integerlisten. In die können aber auch Floats, Strings und Objekte gespeichert werden, nur werden sie intern als Integer abgespeichert. Das ist kein Problem, solange man sie mit den richtigen Befehlen wieder ausliest. Wenn man also z.B. einen String reinspeichert, aber ihn dann als Int ausliest, dann bekommt man natürlich nicht den String sondern seine Adresse im Speicher. Wenn man ein Float als Int ausliest (oder umgekehrt) dann bekommt man nur Blödsinn und wenn man ein Int als String ausliest, dann kann eventuell sogar das Programm abstürzen. Also am Besten ist es, wenn man in einer Liste nur Daten eines Typs speichert, und andere Daten in anderen Listen. Um Type-Objekte in Listen zu speichern muss man zuerst mit Handle() ihr Integer-Handle holen, dass dann als Int in der Liste abspeichern und dann beim Auslesen den gelesenen Integer-Handle mittels Object() wieder in ein Objekt umwandeln. Anders ging's leider nicht. Jetzt zu den Befehlen: Code: [AUSKLAPPEN] list_createList%()
Erstellt eine neue Liste und gibt den Pointer darauf zurück. list_clear(listptr%) Löscht den Listeninhalt. list_size%(listptr%) Gibt die Größe der Liste (=Anzahl der Elemente in der Liste) zurück. list_addInt(listptr%, val%) list_addFloat(listptr%, val#) list_addString(listptr%, val$) Fügt der Liste einen Integer/Float/String hinzu. list_getInt%(listptr%, index%) list_getFloat%(listptr%, index#) list_getString%(listptr%, index$) Gibt den index'ten Wert in der Liste als Int/Float/String zurück. list_setInt(listptr%, index%, val%) list_setFloat(listptr%, index%, val#) list_setString(listptr%, index%, val$) Setzt den Wert an der Stelle Index auf den gegebenen Int/Float/String-Wert. list_removeFirstInt(listptr%, val%) list_removeFirstFloat(listptr%, val#) list_removeFirstString(listptr%, val$) Löscht das erste Vorkommen des Wertes val in der Liste. list_removeAllInt(listptr%, val%) list_removeAllFloat(listptr%, val#) list_removeAllString(listptr%, val$) Löscht alle Vorkommen des Wertes val aus der Liste. list_removeIndex(listptr%, index%) Löscht den index'ten Wert aus der Liste. list_getFirstInt%(listptr%) list_getFirstFloat%(listptr%) list_getFirstString%(listptr%) Gibt den ersten Wert der Liste als Int/Float/String zurück. list_getLastInt%(listptr%) list_getLastFloat%(listptr%) list_getLastString%(listptr%) Gibt den letzten Wert der Liste als Int/Float/String zurück. list_getIterator%(listptr%) Liefert einen Iterator für die Liste zurück. Dieser kann verwendet werden, um alle Elemente der Liste nacheinander abzurufen. list_resetIterator(listptr%, iterator%) Setzt den Iterator auf das erste Element der Liste zurück um ihn wiederverwenden zu können. list_deleteIterator(listptr%, iterator%) Löscht den gegebenen Iterator. WICHTIG: Jeder Iterator darf nur maximal ein Mal gelöscht werden, da das Programm sonst abstürzen kann. Es ist besser einen Iterator zurückzusetzen als ihn zu löschen und neu zu erstellen! list_hasNext%(listptr%, iterator%) Gibt an, ob der Iterator der Liste noch weitere Elemente hat. list_nextInt%(listptr%, iterator%) list_nextFloat#(listptr%, iterator%) list_nextString$(listptr%, iterator%) Gibt den nächsten Wert der Liste an der Stelle des Iterators als Int/Float/String zurück. Codebeispiel: BlitzBasic: [AUSKLAPPEN] Include "collections.bb" Sourcecode: collections.bb BlitzBasic: [AUSKLAPPEN] Function list_removeFirstString(listptr%, val$) collectionsDLL.h Code: [AUSKLAPPEN] #ifdef POINTERSDLL_EXPORTS #include <map> #include <vector> #define COLLECTIONSDLL_API extern "C" __declspec(dllexport) #else #define POINTERSDLL_API __declspec(dllimport) #endif COLLECTIONSDLL_API int __stdcall createList(); COLLECTIONSDLL_API void __stdcall listClear(int listptr); COLLECTIONSDLL_API int __stdcall listGetIterator(int listptr); COLLECTIONSDLL_API int __stdcall listHasNext(int listptr, int iterator); COLLECTIONSDLL_API void __stdcall listResetIterator(int listptr, int iterator); COLLECTIONSDLL_API void __stdcall listDeleteIterator(int listptr, int iterator); COLLECTIONSDLL_API void __stdcall listRemoveIndex(int listptr, int index); COLLECTIONSDLL_API int __stdcall listSize(int listptr); COLLECTIONSDLL_API int __stdcall listGetInt(int listptr, int index); COLLECTIONSDLL_API void __stdcall listAddInt(int listptr, int val); COLLECTIONSDLL_API void __stdcall listRemoveFirstInt(int listptr, int val); COLLECTIONSDLL_API void __stdcall listRemoveAllInt(int listptr, int val); COLLECTIONSDLL_API void __stdcall listSetInt(int listptr, int index, int val); COLLECTIONSDLL_API int __stdcall listGetFirstInt(int listptr); COLLECTIONSDLL_API int __stdcall listGetLastInt(int listptr); COLLECTIONSDLL_API int __stdcall listNextInt(int listptr, int iterator); COLLECTIONSDLL_API float __stdcall listGetFloat(int listptr, int index); COLLECTIONSDLL_API void __stdcall listAddFloat(int listptr, float val); COLLECTIONSDLL_API void __stdcall listRemoveFirstFloat(int listptr, float val); COLLECTIONSDLL_API void __stdcall listRemoveAllFloat(int listptr, float val); COLLECTIONSDLL_API void __stdcall listSetFloat(int listptr, int index, float val); COLLECTIONSDLL_API float __stdcall listGetFirstFloat(int listptr); COLLECTIONSDLL_API float __stdcall listGetLastFloat(int listptr); COLLECTIONSDLL_API float __stdcall listNextFloat(int listptr, int iterator); COLLECTIONSDLL_API char* __stdcall listGetString(int listptr, int index); COLLECTIONSDLL_API void __stdcall listAddString(int listptr, char* val); COLLECTIONSDLL_API void __stdcall listRemoveFirstString(int listptr, char* val); COLLECTIONSDLL_API void __stdcall listRemoveAllString(int listptr, char* val); COLLECTIONSDLL_API void __stdcall listSetString(int listptr, int index, char* val); COLLECTIONSDLL_API char* __stdcall listGetFirstString(int listptr); COLLECTIONSDLL_API char* __stdcall listGetLastString(int listptr); COLLECTIONSDLL_API char* __stdcall listNextString(int listptr, int iterator); collectionsDLL.c Code: [AUSKLAPPEN] #include "stdafx.h"
#include "collectionsDll.h" COLLECTIONSDLL_API int __stdcall createList() { return (int)new std::vector<int>(); } COLLECTIONSDLL_API int __stdcall listGetInt(int listptr, int index) { std::vector<int> *list = (std::vector<int>*) listptr; if (list->size()<=index || index<0) { return 0; } return list->at(index); } COLLECTIONSDLL_API void __stdcall listAddInt(int listptr, int val) { std::vector<int> *list = (std::vector<int>*) listptr; list->push_back(val); } COLLECTIONSDLL_API void __stdcall listRemoveIndex(int listptr, int index) { std::vector<int> *list = (std::vector<int>*) listptr; list->erase(list->begin()+index); } COLLECTIONSDLL_API void __stdcall listSetInt(int listptr, int index, int val) { std::vector<int> *list = (std::vector<int>*) listptr; if (list->size()<=index || index<0) { return; } *(list->begin()+index) = val; } COLLECTIONSDLL_API void __stdcall listRemoveFirstInt(int listptr, int val) { std::vector<int> *list = (std::vector<int>*) listptr; bool found=false; for (unsigned int i=0;i<list->size();i++) { if (list->at(i)==val) { list->erase(list->begin()+i); return; } } } COLLECTIONSDLL_API void __stdcall listRemoveAllInt(int listptr, int val) { std::vector<int> *list = (std::vector<int>*) listptr; bool found=false; for (unsigned int i=0;i<list->size();i++) { if (list->at(i)==val) { list->erase(list->begin()+i); i--; } } } COLLECTIONSDLL_API void __stdcall listClear(int listptr) { std::vector<int> *list = (std::vector<int>*) listptr; list->clear(); } COLLECTIONSDLL_API int __stdcall listGetFirstInt(int listptr) { std::vector<int> *list = (std::vector<int>*) listptr; return list->front(); } COLLECTIONSDLL_API int __stdcall listGetLastInt(int listptr) { std::vector<int> *list = (std::vector<int>*) listptr; return list->back(); } COLLECTIONSDLL_API int __stdcall listGetIterator(int listptr) { std::vector<int> *list = (std::vector<int>*) listptr; std::vector<int>::iterator* it = new std::vector<int>::iterator(list->begin()); return (int)(it); } COLLECTIONSDLL_API int __stdcall listNextInt(int listptr, int iterator) { std::vector<int> *list = (std::vector<int>*) listptr; std::vector<int>::iterator *it = (std::vector<int>::iterator*) iterator; if ((*it)==list->end()) { return 0; } int out = **(it); *it = *it+1; return out; } COLLECTIONSDLL_API int __stdcall listHasNext(int listptr, int iterator) { std::vector<int> *list = (std::vector<int>*) listptr; std::vector<int>::iterator *it = (std::vector<int>::iterator*) iterator; if ((*it)==list->end()) { return 0; } else { return 1; } } COLLECTIONSDLL_API void __stdcall listResetIterator(int listptr, int iterator) { std::vector<int> *list = (std::vector<int>*) listptr; std::vector<int>::iterator* it = (std::vector<int>::iterator*) iterator; (*it) = list->begin(); } COLLECTIONSDLL_API void __stdcall listDeleteIterator(int listptr, int iterator) { delete (std::vector<int>::iterator*) iterator; } COLLECTIONSDLL_API int __stdcall listSize(int listptr) { std::vector<int> *list = (std::vector<int>*) listptr; return list->size(); } COLLECTIONSDLL_API float __stdcall listGetFloat(int listptr, int index) { int intval = listGetInt(listptr, index); return *((float*)(&intval)); } COLLECTIONSDLL_API void __stdcall listAddFloat(int listptr, float val) { int intval = *((int*)(&val)); listAddInt(listptr, intval); } COLLECTIONSDLL_API void __stdcall listSetFloat(int listptr, int index, float val) { int intval = *((int*)(&val)); listSetInt(listptr, index, intval); } COLLECTIONSDLL_API void __stdcall listRemoveFirstFloat(int listptr, float val) { int intval = *((int*)(&val)); listRemoveFirstInt(listptr, intval); } COLLECTIONSDLL_API void __stdcall listRemoveAllFloat(int listptr, float val) { int intval = *((int*)(&val)); listRemoveAllInt(listptr, intval); } COLLECTIONSDLL_API float __stdcall listNextFloat(int listptr, int iterator) { int intval = listNextInt(listptr, iterator); return *((float*)(&intval)); } COLLECTIONSDLL_API float __stdcall listGetFirstFloat(int listptr) { int intval = listGetFirstInt(listptr); return *((float*)(&intval)); } COLLECTIONSDLL_API float __stdcall listGetLastFloat(int listptr) { int intval = listGetLastInt(listptr); return *((float*)(&intval)); } COLLECTIONSDLL_API char* __stdcall listGetString(int listptr, int index) { int intval = listGetInt(listptr, index); return *((char**)(&intval)); } COLLECTIONSDLL_API void __stdcall listAddString(int listptr, char* val) { int intval = *((int*)(&val)); listAddInt(listptr, intval); } COLLECTIONSDLL_API void __stdcall listSetString(int listptr, int index, char* val) { int intval = *((int*)(&val)); listSetInt(listptr, index, intval); } COLLECTIONSDLL_API void __stdcall listRemoveFirstString(int listptr, char* val) { int intval = *((int*)(&val)); listRemoveFirstInt(listptr, intval); } COLLECTIONSDLL_API void __stdcall listRemoveAllString(int listptr, char* val) { int intval = *((int*)(&val)); listRemoveAllInt(listptr, intval); } COLLECTIONSDLL_API char* __stdcall listNextString(int listptr, int iterator) { int intval = listNextInt(listptr, iterator); return *((char**)(&intval)); } COLLECTIONSDLL_API char* __stdcall listGetFirstString(int listptr) { int intval = listGetFirstInt(listptr); return *((char**)(&intval)); } COLLECTIONSDLL_API char* __stdcall listGetLastString(int listptr) { int intval = listGetLastInt(listptr); return *((char**)(&intval)); } Wenn es wer braucht (bitte sagen!), dann mach ich vielleicht auch noch die Maps. Für die, die nicht wissen was das ist, bei Maps kann man Key-Value-Paare speichern, wobei für jeden Key genau ein Value drinnen stehen kann. Dann kann man über den Key (kann ein Int, Float, String oder gar Objekt sein) den passenden Value in sehr geringer Zeit bekommen. Sehr gut, wenn man z.B. zu jedem Einheitennamen das passende Objekt bekommen will oder so. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hmm... wieder keine Reaktion. Irgendwie enttäuschend. | ||
Gewinner der 6. und der 68. BlitzCodeCompo |
Hangman |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Nein! Lobenswerte Arbeit! Ich würde zwar jedem zu BMax raten, aber für die BB Fans ein großer Vorteil. | ||
Ich habe Berthold gebrochen. |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich mach ja normalerweise auch nix in Blitz sondern eher in Java. Ich mach diese Userlibs ja nicht für mich sondern für Leute, die's brauchen.
Meine andere Userlib/DLL hat 37 Downloads aber kein einziges Kommentar. Für die hab ich inklusive Testen gute 5 Stunden gebraucht, bis alles genau so funktioniert hat, wie es sollte. Für diese Userlib/DLL (die ich eigentlich nur gemacht hab, weil in einem anderen Thread jemand Listen gebraucht hat, und BR gemeint hat, ich solls machen) habe ich auch ein paar Stunden gebraucht (wieder runde 5), und auch hier gab es keine Kommentare. Das macht hald einfach keine Lust darauf, noch weitere zu machen. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
![]() |
Thunder |
![]() Antworten mit Zitat ![]() |
---|---|---|
BlitzBasic lockt vielleicht noch manchmal Anfänger, aber die brauchen keine Userlibs (am Anfang sind Funktionen und Types schon schwer genug zu verstehen). Und diejenigen, die noch da sind, und fortgeschrittener sind, machen entweder was mit BlitzMax/Monkey oder überhaupt mit anderen Sprachen, so wie du mit Java.
Die Nische, für die du die Lib programmiert hast, gibt es nicht mehr - traurig aber wahr. Ich verwende auch kein BlitzBasic mehr, sondern BlitzMax, C und Assembler. Habe jetzt aber noch einen Blick über deinen Code geworfen. Was mich anfangs irritiert hat waren (ich schreibe es allgemein) die Ausdrücke "*((type*) (&val))" was im Wesentlichen übereinstimmt mit "(type) val". Es hätte glaub ich sogar gereicht, nur die Int-Funktionen zu implementieren und die anderen dann in der Decls einfach auf Int-Funktionen umzubiegen: Code: [AUSKLAPPEN] list_addInt(listptr%, val%):"_listAddInt@8"
list_addFloat(listptr%, val#):"_listAddInt@8" list_addString(listptr%, val$):"_listAddInt@8" ... Ich sage nicht, dass deine Arbeit schlecht ist oder so, ich zweifle nur, ob es noch Verwendung findet.. :/ |
||
![]() |
BladeRunnerModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
Zitat: ...und auch hier gab es keine Kommentare.
Das macht hald einfach keine Lust darauf, noch weitere zu machen. Es war schon immer so: mach was gutes, und keiner sagt was dazu. Mach was mieses und die Unkenrufe schiessen wie Pilze aus dem Boden. Mach Dir da nichts draus. B3D wird nur noch von wenigen genutzt. So what? Wenn es nur zwei Leuten die es noch nutzen was bringt hast Du schon was Gutes getan. Mein Clone-Modul für BMax wurde weit über tausend mal runtergeladen, das Feedback ist weiter gleich null. Mir hat es Spass gemacht das Ding zu basteln, und ich habe einiges dabei gelernt. Ich finde es auch schade dass kein Feedback kam, aber das wird mich nicht davon abhalten neue Module zu schrauben und zu veröffentlichen, wenn mir wieder mal was einfällt. |
||
Zu Diensten, Bürger.
Intel T2300, 2.5GB DDR 533, Mobility Radeon X1600 Win XP Home SP3 Intel T8400, 4GB DDR3, Nvidia GF9700M GTS Win 7/64 B3D BMax MaxGUI Stolzer Gewinner des BAC#48, #52 & #92 |
EisbaerBetreff: re |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Die DLL hat sicherlich Vorteile, wenn man sie benötigt.
Danke für deine Arbeit. Es ist immer gut wenn einige C Funktion nach BlitzBasic Konvertiert wird. Es gibt auch inzwischen den Quellcode von B3D zum Download ect. lassen sich gewisse Funktion gleich direkt Integrieren. |
||
Eigene Webseite:
http://www.eisbaer-studios.de |
Sirrus |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
[quote="BladeRunner"]Zitat: ...B3D wird nur noch von wenigen genutzt. So what? Wenn es nur zwei Leuten die es noch nutzen was bringt hast Du schon was Gutes getan...
mehr als zwei Leute nutzen mit Sicherheit noch B3D, ich verwende nur B3D und B+ Jedoch ist mir nicht ganz klar, wozu diese Collections gut sein sollen, bzw welchen Vorteil sie bringen. |
||
![]() |
TimBo |
![]() Antworten mit Zitat ![]() |
---|---|---|
danke für die Arbeit, aber möchtest du den Source nicht open source machen ?
Vergiss es: habe erwartet es wäre in der zip sorry ![]() Grüße, TimBo |
||
mfg Tim Borowski // CPU: Ryzen 2700x GPU: Nvidia RTX 2070 OC (Gigabyte) Ram: 16GB DDR4 @ 3000MHz OS: Windows 10
Stolzer Gewinner des BCC 25 & BCC 31 hat einen ersten Preis in der 1. Runde beim BWInf 2010/2011 & 2011/12 mit BlitzBasic erreicht. |
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Sirrus hat Folgendes geschrieben: BladeRunner hat Folgendes geschrieben: Dann bin ich der zweite, der nur B3D und B+ verwendet.
...B3D wird nur noch von wenigen genutzt. So what? Wenn es nur zwei Leuten die es noch nutzen was bringt hast Du schon was Gutes getan... mehr als zwei Leute nutzen mit Sicherheit noch B3D, ich verwende nur B3D und B+
Jedoch ist mir nicht ganz klar, wozu diese Collections gut sein sollen, bzw welchen Vorteil sie bringen. Ich verstehe auch nicht, wozu die Collections gut sein sollen, da ein Type bereits eine Collection ist. Warum sollte man denn Zeiger auf eine Collection in Integerwerte umwandeln um sie in einer anderen Collection zu speichern? Das ist ja wie "Bäume in den Wald tragen" ![]() |
||
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Es hat schon mehrere Vorteile dazu, einfach Types zu verwenden.
Types sind ja Structs und eine Liste, wo alle Structs eines Typs rein kommen. Einige Nachteile davon sind folgende: -) Will man zwei Listen eines Typs haben, muss man den Type zwei mal erstellen, also zwei mal den gleichen Type mit den gleichen Feldern machen. -) Macht man das, dann sind die Types nicht mehr mit einander kompatibel. Beispiel: Es gibt eine Liste mit abzuarbeitenden Objekten und eine Liste mit schon fertig abgearbeiteten Objekten. In Blitz müsste man dazu zwei Types erstellen und nach dem Abarbeiten eines Objekts selbiges manuell in den anderen Type kopieren und dann das Original löschen. -) Ein Type-Objekt kann nicht in zwei verschiedenen Type-Listen gleichzeitig sein. -) Es ist nicht möglich, eine Liste mit Primitiven (Ints, Floats, Strings) zu erstellen. -) Types verwenden Linked Lists statt Array Lists, weswegen ein direkter Zugriff auf das Objekt an Stelle X nicht möglich ist. Wenn man z.B. das 10. Objekt aus einer Liste haben will, muss man erst die ersten 9 Objekte durchgehen (mittels First und dann After). Hier sind die Array Lists wesentlich schneller, da sie direkt auf das X. Objekt zugreifen können. Alle diese Probleme werden durch die externen Listen beseitigt. Wenn es eine Nachfrage dazu gegeben hätte, dann hätte ich noch Hashmaps eingebaut. Die sind eine Collection aus Key-Value-Paaren, wobei man einen Wert durch den Schlüssel abrufen kann. Die sind sehr gut, wenn man z.B. immer einem String einen anderen Wert zuteilen möchte. Schlägt beim Suchen jede List (vor allem Linked Lists) um Längen (Look-Up geht bei einer Linked List mit O(n), also bei einer Liste mit n Einträgen braucht man in der Größenordnung von n Abfragen. Eine Hashmap schafft das in O(1), das heißt, unabhängig davon, wie viele Objekte in der Map sind braucht es immer annähernd die gleiche Zeit um ein Objekt zu finden). Andere Collections, die man noch einbauen könnte, wären z.B. Priority Queues, die z.B. einen Pathfinding-Algorithmus um einen quadratischen Faktor beschleunigen können (mit anderen Worten: Verdammt schnell!) Und wenn Bedarf existiert, dann könnte ich die auch einbauen. Nur war das leider bisher nicht so. |
||
Gewinner der 6. und der 68. BlitzCodeCompo |
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAK hat Folgendes geschrieben: -) Will man zwei Listen eines Typs haben, muss man den Type zwei mal erstellen, also zwei mal den gleichen Type mit den gleichen Feldern machen.
Warum kompliziert mit zwei Listen, wenn das auch einfach mit einer Liste geht.DAK hat Folgendes geschrieben:-) Macht man das, dann sind die Types nicht mehr mit einander kompatibel. Beispiel: Es gibt eine Liste mit abzuarbeitenden Objekten und eine Liste mit schon fertig abgearbeiteten Objekten. In Blitz müsste man dazu zwei Types erstellen und nach dem Abarbeiten eines Objekts selbiges manuell in den anderen Type kopieren und dann das Original löschen. -) Ein Type-Objekt kann nicht in zwei verschiedenen Type-Listen gleichzeitig sein. Warum auch? Ich habe noch keinen Fall gehabt, wo ich ein Type in 2 Listen haben müsste.DAK hat Folgendes geschrieben:-) Es ist nicht möglich, eine Liste mit Primitiven (Ints, Floats, Strings) zu erstellen. Warum nicht?DAK hat Folgendes geschrieben:-) Types verwenden Linked Lists statt Array Lists, weswegen ein direkter Zugriff auf das Objekt an Stelle X nicht möglich ist. Wenn man z.B. das 10. Objekt aus einer Liste haben will, muss man erst die ersten 9 Objekte durchgehen (mittels First und dann After). Hier sind die Array Lists wesentlich schneller, da sie direkt auf das X. Objekt zugreifen können. Wenn man sich den Index 10 speichert aber davor Einträge hinzufügt oder löscht, bekommt man mit dem Index 10 ein anderes Objekt. Verwendet man dagegen einen Pointer auf das Objekt, so ist das egal wieviel davor eingefügt oder gelöscht wird
Aber egal, wer mit Types nicht umgehen kann, kann ja jetzt deine Listen wenden.... |
||
![]() |
Eingeproggt |
![]() Antworten mit Zitat ![]() |
---|---|---|
Wir reden von BlitzBasic-Types.
Tut mir leid wenn das jetzt missverstanden werden kann, aber du behauptest mit 2 Beiträgen hier im Forum dass DAK nicht mit Types umgehen kann? Die Sache mit 2 Listen ist schnell erklärt. Nehmen wir eine einfache Struktur an wo du "Spieler" hast und dann "Arten von Spielern", wie zB menschliche und KI. Bei den Menschen speicherst du zB die Keyboard-Belegung, bei der KI interne Werte zur Berechnung des nächsten Schrittes. Jetzt kannst du beide in einen Type hauen, damit beide Spieler von der Spiellogik gleich verarbeitet werden (zB gezeichnet, bewegt etc.) Willst du aber die KI-Berechnungen ausführen, musst du über alle SPieler, auch die menschlichen iterieren und das kann in größeren Beispielen dann sehr unerwünscht sein. Wenn du aber KI und Menschen trennst, musst du die "gemeinsamen Funktionen" doppelt implementieren. Alles auf BlitzBasic bezogen. Ich weiß schon dass viiiieeele andere Sprachen schönere Verberbung und das Gedöhns bieten. Auch mit den primitiven Typen hat DAK recht. Es geht ja in der Liste um ein "Insert After" und ähnlichem. Die hast du in einem Array (wo du int, float etc. reintun kannst) nicht. Nur bei den Types. Und die sind eben nicht primitiv. Ich möcht nochmal hervor heben, dass meine Erklärungen auf BlitzBasic zutreffen, weil in der heutigen Zeit wohl fast jeder Programmierer der Java oder ähnliches gewohnt ist hier zurecht widerspricht. mfG, Christoph |
||
Gewinner des BCC 18, 33 und 65 sowie MiniBCC 9 |
![]() |
DAK |
![]() Antworten mit Zitat ![]() |
---|---|---|
Mirco1989 hat Folgendes geschrieben: Warum kompliziert mit zwei Listen, wenn das auch einfach mit einer Liste geht.
Die Aufgabenstellung war: Zwei Listen eines Types. Und du sagst, warum nicht mit einer Liste. Also deine Lösung für die Aufgabenstellung ist Selbige einfach zu ignorieren. Auch gut. Mirco1989 hat Folgendes geschrieben: DAK hat Folgendes geschrieben:
-) Ein Type-Objekt kann nicht in zwei verschiedenen Type-Listen gleichzeitig sein. Warum auch? Ich habe noch keinen Fall gehabt, wo ich ein Type in 2 Listen haben müsste.Ich habe dir gerade einen Fall gezeigt. Du hast eine Liste von Objekten, die abgearbeitet werden muss. Jedes fertig abgearbeitete Objekt muss in einer anderen Liste abgespeichert werden. Sowas kommt z.B. bei effizienten Pathfinding-Algos vor. Ja, kannst es dort auch ohne machen, wäre dann aber in vielen Fällen sehr langsam. Mirco1989 hat Folgendes geschrieben: DAK hat Folgendes geschrieben:
-) Es ist nicht möglich, eine Liste mit Primitiven (Ints, Floats, Strings) zu erstellen. Warum nicht?Da du mir scheinbar nicht glaubst, dass ich weiß wie Types funktionieren würde ich gerne sehen, wie das denn geht. Ich habe vor 10 Jahren mit Blitz begonnen. Ich habe begonnen einen Compiler zu schreiben (eingefroren bei ~50% Projektfortschritt), der BlitzBasic-Code nach Java umkompiliert. Aber wenn du mir eine Methode zeigst, wie du in BlitzBasic eine Liste aus Primitiven machst, ohne Types/Objekte zu verwenden, dann glaub ich dir gerne. Mirco1989 hat Folgendes geschrieben: DAK hat Folgendes geschrieben:
-) Types verwenden Linked Lists statt Array Lists, weswegen ein direkter Zugriff auf das Objekt an Stelle X nicht möglich ist. Wenn man z.B. das 10. Objekt aus einer Liste haben will, muss man erst die ersten 9 Objekte durchgehen (mittels First und dann After). Hier sind die Array Lists wesentlich schneller, da sie direkt auf das X. Objekt zugreifen können. Wenn man sich den Index 10 speichert aber davor Einträge hinzufügt oder löscht, bekommt man mit dem Index 10 ein anderes Objekt. Verwendet man dagegen einen Pointer auf das Objekt, so ist das egal wieviel davor eingefügt oder gelöscht wirdSo, wieder mal ein guter Fall von nicht verstanden, worum es geht. Hast du schon mal von Sortieralgos gehört? Zum Beispiel dem Quicksort. Kennst du den? Hast du sowas schon mal programmiert? Bei dem Algo ist ein Direktzugriff auf jedes einzelne Objekt in einer Liste oder einem Array notwendig. Wenn du einen Sortieralgo ohne Direktzugriff programmieren willst, also einen der nur iteriert, wie es mit den Standard-Types möglich ist, dann braucht der gezwungenermaßen wesentlich länger. Um genau zu sein, um einen linearen Faktor länger. Ein Quicksort der iteriert würde somit statt O(n log n) stattdessen O(n² log n) Vergleiche brauchen. Weiß nicht, ob dir die Landau-Notation was sagt. Schau mal auf Wiki danach. Mirco1989 hat Folgendes geschrieben: Aber egal, wer mit Types nicht umgehen kann, kann ja jetzt deine Listen wenden....
Ok, ich mach sowas normalerweise nicht, aber schauen wir uns mal unsere Referenzen an. Wie lange programmierst du schon? Wie lange hast du Blitz im Spezifischen schon verwendet? Welches Semester bist du in deinem Informatikstudium? Wie viele Vorlesungen zu den Themen Datenstrukturen, Algorithmen und Objektorientierung hast du schon hinter dir? Wie viele Jahre arbeitest du schon als Programmierer? Wie viele vorzeigbare Projekte hast du hinter dir? Schon mal ein Tutorial zu dem Thema geschrieben, oder zumindest Nachhilfe über eines der relevanten Themen gegeben? Schon mal eine Vorlesung gehalten? |
||
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Eingeproggt hat Folgendes geschrieben: Tut mir leid wenn das jetzt missverstanden werden kann, aber du behauptest mit 2 Beiträgen hier im Forum dass DAK nicht mit Types umgehen kann? Nein, das behaupte ich nicht!
In meinem ersten Beitrag zu diesem Thema habe ich geschrieben, das ich nicht sehe, wozu die Collections gut sein sollen, und im zweiten Beitrag habe ich geschrieben, das andere die mit Types nicht umgehen können, die Collections von DAK nutzen können. Es hat bei mir auch einige Zeit gedauert, bis ich mit Types zurecht kam. Aber inzwischen geht das recht gut und ich mache sehr viel mit Types. Ich sehe die Collections von DAK als eine Alternative, bis man Types gut verwenden kann. Eingeproggt hat Folgendes geschrieben: Nehmen wir eine einfache Struktur an wo du "Spieler" hast und dann "Arten von Spielern", wie zB menschliche und KI. Bei den Menschen speicherst du zB die Keyboard-Belegung, bei der KI interne Werte zur Berechnung des nächsten Schrittes.
wie ich das mit Types machen würde, läßt sich wohl am besten meit einem Beispiel-Code zeigen:Code: [AUSKLAPPEN] Jetzt kannst du beide in einen Type hauen, damit beide Spieler von der Spiellogik gleich verarbeitet werden (zB gezeichnet, bewegt etc.) Willst du aber die KI-Berechnungen ausführen, musst du über alle SPieler, auch die menschlichen iterieren und das kann in größeren Beispielen dann sehr unerwünscht sein. ; Code-Beispiel zur Verwendung von beliebigen Spielern (menschlich und KI) in einem Type
Abschliessend noch ein kurzes funktionsfähiges Programm, das belegt, das diese Handhabung funktioniert:Code: [AUSKLAPPEN] ; als Beispiel nehme ich ein Multiplayerspiel im Stil von "Twee World"(http://www.blitzforum.de/showcase/516/) ; mit Spielern, Schüssen, Monstern, NPCs, einsammelbaren Gegenständen usw. die man alle über eine Type-Collection ; verwalten kann, weil ich selber an etwas ähnlichem arbeite. ; Für die Darstellung kann man die ganze Type-Collection durchlaufen, aber für die unterschiedliche Steuerung(Mensch/KI) ; Kann man auch nur Types eines Typs einzeln bearbeiten, ohne die ganze Type-Collection zu durchlaufen ; HINWEIS: das ist nur ein Beispiel mit Types und Functionen, aber kein ausführbares Programm Type KeyMouseJoy ;Für die Steuerung von menschlichen Spielern Field Vor, Zurück, Links, Rechts, Feuern End Type Type Monster ;Ki-Gegner ;Fields zur Handhabung der KI End Type ; weitere Types z.B. Questgeber(NPC), einsammelbare Gegenstände(Item) usw. Type Spieler ;für Menschen und KI Field Image Field PosX,PosY Field SpielerTyp ; 1=Mensch, 2=Monster (, 3=NPC, 4=Item ...) Field ExtraDaten ; Hierher kommt ein Handle auf den entsprechenden Type End Type ;In der Initialisierung lege ich leer Types an um die verschiedenen SpielerTypen zu sortieren ;Dazu muss ich die leeren Types global verfügbar haben Global GrenzeMenschMonster.Spieler ;(, GrenzeMonsterNPC.Spieler, GrenzeNpcItem.Spieler) Function Init() GrenzeMenschMonster.Spieler = New Spieler ;GrenzeMonsterNPC.Spieler = New Spieler ;usw. End Function ;Jetzt kann ich belibige Spieler(Mensch, Monster, NPC...) hinzufügen und an bestimmten Positionen einsortieren Function AddSpieler(Image,x,y,Typ,Extra) Neu.Spieler = New Spieler Neu\Image = Image Neu\PosX = x Neu\PosY = y Neu\SpielerTyp = Typ Neu\ExtraDaten = Extra ;Handle auf Typ-spezifische Types Select Typ Case 1 ;Mensch Insert Neu Before GrenzeMenschMonster Case 2 ;Monster Insert Neu Before GrenzeMonsterNPC ;Da ein neuer Type erst einmal am Ende der Type-Collection erstellt wird brauche ich ;ich den letzten Spieler-Typ nicht mit INSERT verschieben End Select ; ich gebe ein Handle für weitere Einstellungen zurück Return Handle(Neu) End Function ; mit FOR EACH kann ich alle Spieler zeichnen Function AlleSpielerZeichnen() For Count.Spieler = Each Spieler DrawImage Count\Image, Count\PosX, Count\PosY Next End Function ;Da FOR EACH keinen Start- oder End-Type unterstützt, muss ich die simulieren Function SteuerungMenschen() Count.Spieler = First Spieler ;Ersten Spieler auswählen While Count.Spieler <> GrenzeMenschMonster.Spieler ;nur Menschen Mensch.KeyMouseJoy = Object.KeyMouseJoy(Count\ExtraDaten) ;Steuerung-Type holen ;Hier Steuerung verarbeiten Count.Spieler = After Count ;Dann nächsten Spieler auswählen Wend End Function ;Ebenso kann ich weitere Spieler-Types behandeln Function SteuerungMonster() Count.Spieler = After GrenzeMenschMonster.Spieler ;Erstes Monster auswählen While Count.Spieler <> GrenzeMonsterNPC.Spieler ;nur Monster Gegner.Monster = Object.Monster(Count\EXtraDaten) ;KI behandeln Count.Spieler = After Count Wend End Function ;beim letzten Spielertyp muss WHILE bis zu einem ungüliten Type durchlaufen ; ---> While Count.Spieler <> Null Type Test Field Wert End Type
Diese Form würde ich auch in dem Beispiel von DAK verwenden
Global Grenze.Test ;------------------------------------------Hauptprogramm Init() AusgabeAlles() Print "--------" AusgabeVorGrenze() AusgabeNachGrenze() WaitMouse() End ;-------------------------------------------Functionen Function Init() Grenze.Test = New Test ;leerer Hilfs-Type For n= 1 To 5 zeiger.test = New Test ;einige test-Types erstellen If N<4 Then Insert zeiger Before Grenze ;einige vor die Grenze verschieben zeiger\Wert = N Next End Function Function AusgabeAlles() For c.Test = Each Test If c\Wert = 0 Then Print "Grenze" Else Print "Wert="+c\wert EndIf Next End Function Function AusgabeVorGrenze() c.Test = First Test While c.Test <> Grenze.test Print "VorGrenzeWert="+c\wert c.Test = After c Wend End Function Function AusgabeNachGrenze() c.test = After Grenze.test While c.Test <> Null Print "NachGrenzeWert="+c\wert c.test = After c Wend End Function DAK hat Folgendes geschrieben: Beispiel: Es gibt eine Liste mit abzuarbeitenden Objekten und eine Liste mit schon fertig abgearbeiteten Objekten. In Blitz müsste man dazu zwei Types erstellen und nach dem Abarbeiten eines Objekts selbiges manuell in den anderen Type kopieren und dann das Original löschen. Man muß in Blitz keine zwei Types erstellen, sondern kann abzuarbeitende Objekte und schon fertig abgearbeitete Objekte in einer Type-Collection (vor und hinter einem "Grenztype") verwenden. Man kann dann nur die abzuarbeitenden Objekte durchlaufen und sie danach mit INSERT an die andere Seite der Grenze verschieben. (Das "manuell in den anderen Type kopieren und dann das Original löschen" entfällt)
Noch Fragen? |
||
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAK hat Folgendes geschrieben: Wie lange programmierst du schon? Wie lange hast du Blitz im Spezifischen schon verwendet? Welches Semester bist du in deinem Informatikstudium? Wie viele Vorlesungen zu den Themen Datenstrukturen, Algorithmen und Objektorientierung hast du schon hinter dir? Wie viele Jahre arbeitest du schon als Programmierer? Wie viele vorzeigbare Projekte hast du hinter dir? Schon mal ein Tutorial zu dem Thema geschrieben, oder zumindest Nachhilfe über eines der relevanten Themen gegeben? Schon mal eine Vorlesung gehalten? Ich habe nicht behauptet, das ich ein perfekter Programmierer /Informatiker wäre, sonern nur das ich bisher alles mit Types machen konnte und daher keine Verwendung für deine Collektion sehe.
Vielleicht kommt das irgendwann später noch, aber dann werde ich möglicherweise kein Blitz mehr verwenden... |
||
Sirrus |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
@DAK wenn man hier nur Kritik äußern darf, wenn Informatik studiert hat und Vorlesungen gehalten hat, bin ich im falschen Forum. Ich mache das so ähnlich wie Mirco und habe auch noch nichts gehabt, was ich nicht irgendwie mit Types machen kann, aber vieleicht sollte ich (als Rentner) noch ein Studium anfangen um mir Probleme zu schaffen für die du eine Lösung anbietest.
Nach meiner bisherigen Erfahrung gibt es beim Programmieren nicht die eine einzig richtige Lösung, sondern es gibt immer mehrere Möglichkeiten um ans Ziel zu kommen. @Mirco Das mit dem "Grenz"-Type ist prima, ich hab mir bisher immer "erster Spieler/letzter Spieler" usw. als Global gemacht. Das hatte aber den Nachteil, das "erster Spieler" immer ändern mußte, wenn ich einen neuen Spieler hinzu gefügt habe. Mit den Grenz-Types geht das viel einfacher. ![]() |
||
![]() |
XeresModerator |
![]() Antworten mit Zitat ![]() |
---|---|---|
@DAK: Das ist der Grund, warum du so wenige Rückmeldungen erhältst. Die Schnittmenge der Leute, die noch mit BlitzBasic arbeiten aber andererseits etwas mit Collections anfangen kann, dürfte gegen 0 gehen.
Wenn ich mit richtigen Klassen und Vererbung arbeiten kann/will würde ich das auch nicht per DLL in BlitzBasic nachrüsten sondern gleich eine andere Sprache wählen... Wenn ihr weiter über die (un)zulänglichkeiten von Types diskutieren wollt, bleibt zivil - danke. |
||
Win10 Prof.(x64)/Ubuntu 16.04|CPU 4x3Ghz (Intel i5-4590S)|RAM 8 GB|GeForce GTX 960
Wie man Fragen richtig stellt || "Es geht nicht" || Video-Tutorial: Sinus & Cosinus THERE IS NO FAIR. THERE IS NO JUSTICE. THERE IS JUST ME. (Death, Discworld) |
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAK hat Folgendes geschrieben: -) Types verwenden Linked Lists statt Array Lists, weswegen ein direkter Zugriff auf das Objekt an Stelle X nicht möglich ist. Wenn man z.B. das 10. Objekt aus einer Liste haben will, muss man erst die ersten 9 Objekte durchgehen (mittels First und dann After). Hier sind die Array Lists wesentlich schneller, da sie direkt auf das X. Objekt zugreifen können. Auch das kann ich wiederlegen:
Aus der Beschreibung in der Hilfe bei Handle(https://www.blitzforum.de/help/Handle) hatte angenommen, das Handle möglicherweise die Speicheradresse eines Types zurück gibt. Das wollte ich genau wissen und habe darum ein kleines Testprogramm geschrieben: Code: [AUSKLAPPEN] Type Test Field Wert$ End Type
Ergebnis:
For Count=1 To 5 zeiger.Test = New Test zeiger\Wert = Count+".Type" Next For Zeiger.Test = Each Test Print ">"+zeiger\wert+" Handle="+Handle(zeiger) Next WaitMouse End Handle enthält scheinbar den Index eines Types in der Collection. Doch mit "scheinbar" geb ich mich nicht zufrieden, das wollte ich genau wissen. Ich habe folgende 2 Zeilen zwischen die beiden For-Schleifen gesetzt:Code: [AUSKLAPPEN] zeiger.test = Last Test
Damit kamen die Handle-Werte durcheinander und schon war meine schöne Theorie zum Teufel Print Handle(zeiger) ![]() Aber ich bin auch hartnäckig, wenn ich etwas wissen will. Also neue Theorie: Möglicherweise wird der Index wird einem Type erst durch die Handle-Function zugewiesen??? Also Testprogramm geändert: Code: [AUSKLAPPEN] Type Test Field Wert$ End Type
Das funktionierte! egal welchen Type ich jetzt zwischendurch aufrufe, die Handle-Werte bleiben in der Reihenfolge der Types in der Collection.
For Count=1 To 5 zeiger.Test = New Test n=Handle(zeiger) ;bei der Erstellung des Type gleich Handle aufrufen zeiger\Wert = Count+".Type" Next For Zeiger.Test = Each Test Print ">"+zeiger\wert+" Handle="+Handle(zeiger) Next WaitMouse End so kann man auch mit einem Index auf ein Type zugreifen, ohne sich mit first und after durchhangeln zu müssen. Das geht einfach mit:Code: [AUSKLAPPEN] Zeiger.Test = Object.Test(Index) Auch die Anzahl der Types in der Collection kann man ermitteln mit:Code: [AUSKLAPPEN] Function Anzahl()
Bloß wenn man INSERT verwendet, bringt das die Reihenfolge wieder durcheinander, aber Insert ist bei den Collections von DAK auch nicht dabei.
zeiger.test = Last Test Return Handle(zeiger) End Function HINWEIS: BEVOR DAS JEMAND VERWENDET, BITTE TESTEN OB DAS GENAUSO GUT GEHT WIE BEI MIR |
||
Mirco1989 |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
DAK hat Folgendes geschrieben: Hast du schon mal von Sortieralgos gehört? Zum Beispiel dem Quicksort. Kennst du den? Hast du sowas schon mal programmiert? Nein, habe ich noch nicht, aber ich bin immer an neuen Herausforderungen interessiert. Wenn du einigermaßen verständlich erklären kannst, wie Quicksort geht, will ich das gerne mal versuchen.
(zum "verständlich erklären": bin Schüler, 8.Klasse, Mathe 1) |
||
Übersicht
![](/themes/Standard/arrow.png)
![](/themes/Standard/arrow.png)
Powered by phpBB © 2001 - 2006, phpBB Group