Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von Josh »

Meinst du so was in der Art?

Code: Alles auswählen

Structure ACTOR
   x.i
   y.i
EndStructure

Structure MONSTER Extends ACTOR
   name$
   hp.i
EndStructure

Structure OBJECT Extends ACTOR
   type$
   locked.i
EndStructure

Global NewList *act.ACTOR()
Global NewList mon.MONSTER()
Global NewList obj.OBJECT()

AddElement(*act())
*act() = AddElement(mon())
mon()\x = 10
mon()\y = 5
mon()\name$ = "Goblin"
mon()\hp = 20

AddElement(*act())
*act() = AddElement(obj())
obj()\x = 11
obj()\y = 6
obj()\type$ = "Schatztruhe"
obj()\locked = 0

ForEach mon()
   Debug mon()\name$+" ("+mon()\hp+")   "+mon()\x+","+mon()\y
Next
Debug ""

ForEach obj()
   Debug obj()\type$+" ("+obj()\locked+")   "+obj()\x+","+obj()\y
Next
Debug ""

ForEach *act()
  Debug "" + *act()\x + "," + *act()\y
Next
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von diceman »

//EDIT:
Bisonte hat geschrieben:Das wird nicht funktionieren, da es trotz der "Ableitung" immer noch zwei getrennte Listen sind.
On 2nd notice: ja, du hast Recht. Spätestens wenn man versucht Elemente wieder zu löschen, wird mir das Problem offenbar. Ist aber auch nicht so tragisch, war eh ein doofes Beispiel.
Trotzdem danke an Josh: hab von deinem Code trotzdem was lernen können. :)

Und dann darf ich direkt noch die nächste Frage hinterherwerfen?
Gegeben sein ein 3x3 Spielfeld. In der Mitte (Koordinaten 1,1) steht der Spieler (im Beispiel ebenfalls ein Monster-Element).
Dann erzeuge ich 10 Orcs mit zufälligen Koordinaten (x = random(2,0), y = random(2,0) ).
Anschließend möchte ich checken, ob sich einer oder mehrere Orcs auf demselben Feld wie der Spieler befinden.
Abstrakt gesprochen: ich möchte Elemente ein und derselben Liste miteinander vergleichen!

Ich habe dafür folgende Lösung gefunden, aber vielleicht geht ja auch das noch etwas eleganter: :)

Code: Alles auswählen

EnableExplicit

Declare createMonsters()
Declare checkFight()

Structure MONSTER
	index.i
	x.i
	y.i
	name$
EndStructure
Global NewList mon.MONSTER()


createMonsters()
checkFight()


Procedure createMonsters()
	Define m
	
	AddElement(mon())
	mon()\index = 0
	mon()\x = 1
	mon()\y = 1
	mon()\name$ = "Hero"
	
	For m = 1 To 10 
		AddElement(mon())
		mon()\index = m
		mon()\x = Random(2,0)
		mon()\y = Random(2,0)
		mon()\name$ = "Orc"
	Next
EndProcedure



Procedure checkFight()
	Define NewList checkList.MONSTER() ;Lokale Liste
	CopyList(mon(),checkList())
	
	ForEach mon()
		If mon()\name$ = "Hero"
			Debug mon()\name$+" ("+mon()\index+")   "+mon()\x+","+mon()\y
			ForEach checkList()
				If checkList()\name$ = "Orc" And mon()\x = checkList()\x And mon()\y = checkList()\y
					Debug checkList()\name$+" ("+checkList()\index+")   "+checkList()\x+","+checkList()\y
				EndIf
			Next
			Break
		EndIf
	Next
EndProcedure
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
Josh
Beiträge: 1028
Registriert: 04.08.2009 17:24

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von Josh »

Zum löschen gibt es jetzt mehrere Möglichkeiten. Hier mal eine davon:

Code: Alles auswählen

Structure ACTOR
   x.i
   y.i
EndStructure

Structure MONSTER Extends ACTOR
   name$
   hp.i
EndStructure

Structure OBJECT Extends ACTOR
   type$
   locked.i
EndStructure

Global NewList *act.ACTOR()
Global NewList mon.MONSTER()
Global NewList obj.OBJECT()

AddElement(*act())
*act() = AddElement(mon())
mon()\x = 10
mon()\y = 5
mon()\name$ = "Goblin"
mon()\hp = 20

AddElement(*act())
*act() = AddElement(obj())
obj()\x = 11
obj()\y = 6
obj()\type$ = "Schatztruhe"
obj()\locked = 0

ForEach mon()
   Debug mon()\name$+" ("+mon()\hp+")   "+mon()\x+","+mon()\y
Next
Debug ""

ForEach obj()
   Debug obj()\type$+" ("+obj()\locked+")   "+obj()\x+","+obj()\y
Next
Debug ""

ForEach *act()
  Debug "" + *act()\x + "," + *act()\y
Next
Debug ""

;Element löschen

ForEach obj()
   If obj()\x = 11 And obj()\y = 6
     ForEach *act()
       If *act() = @obj()
         Break
       EndIf
     Next
     DeleteElement (obj())
     DeleteElement (*act())
   EndIf
Next

ForEach *act()
  Debug "" + *act()\x + "," + *act()\y
Next
Debug ""
  • In diesem Beispiel bin ich davon ausgegangen, dass du das Element in der List obj() kennst und habe den dazugehörigen Zeiger in der List *act() gesucht.
  • Eine weitere Möglichkeit wäre, dass du dir gleich beim Anlegen deiner Objekte den Pointer der List *act() in einem Feld der List obj() merkst. Dann kannst du dir beim Löschen das suchen ersparen, was aber nur bei wirklich großen Lists eine Rolle spielt.
  • Ein Problem hast du allerdings, wenn du nur das Löschelement in der List *act() kennst, da du nicht weißt, ob dieses Element zur List obj() oder mon() gehört.
Zuletzt geändert von Josh am 08.02.2018 23:36, insgesamt 1-mal geändert.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von Bisonte »

Du willst nur ein Element vergleichen ? Dann musst du nicht die komplette Liste kopieren. Das besagte Element gegen
was geprüft werden soll reicht da aus.

Beisp.:

Code: Alles auswählen

Procedure checkFight()
  
  Protected *p.MONSTER = #Null
  
  ForEach mon()
    If mon()\name$ = "Hero"
      *p = @mon()
      Break
    EndIf
  Next
  
  If *p
    ForEach mon()
      If mon()\name$ = "Orc" And mon()\x = *p\x And mon()\y = *p\y
        Debug mon()\name$+" ("+ mon()\index + ")   " + mon()\x+"," + mon()\y
      EndIf
    Next
  EndIf

EndProcedure
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von diceman »

Sowas in der Art habe ich mir vorgestellt, danke! :)
Das sind Pointer, oder? Zu 100% habe ich deren Funktionsweise noch nicht durchschaut, aber jetzt habe ich schon so einige Beispiel-Snippets gesichtet, wo die in der einen oder anderen Form verwendet wurden - da komme ich auch noch dahinter, das Licht am Ende des Tunnels ist aber bereits sichtbar. Dein Beispiel ist schön knapp gehalten, das kann man gut studieren!
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von Bisonte »

Ja Pointer.

Pointer ist nur ein Zeiger auf eine Adresse.

Ich habe die Konstannte #Null gesetzt, damit die einen garantierten 0 ist (Die konstante nur weil ich wollte das es auffällt! Liest sich schneller als eine Zahl im Wust von Zahlen)

Das ganze ist eigentlich fix erklärt. Am Anfang wird die Variable *p mit der Struktur MONSTER "verknüpft". Damit kann man
im weiteren Verlauf direkt auf die Elemente innerhalb der Struktur zugreifen, wie man es von den Listen kennt *p\Index z.B. ...

Dann wird die Liste nach dem "Hero" durchsucht. (Später fand ich raus, das dieser wohl immer als erstes in der Liste stehen soll,
dazu später mehr)

Wenn Hero gefunden wurde, weise ich der Variable *p den die Adresse des Elementes zu das gerade untersucht wird.
Das geschieht mit dem @ vor dem Listennamen. ( @mon() )
Dann hat der Pointer (*p) die Adresse. Also muss man jetzt nicht mehr weitersuchen und wir verlassen die ForEach Next Schleife
mit einem Break !

Nun sollen ja die Monster gefunden werden die auf dem gleichen Feld wie der Hero stehen, also fragen wir erst ab,
ob denn Hero überhaupt gefunden wurde. (Kann ja sein das der nicht da ist) mit If *p

Dann durchlaufen wir die Liste nochmal und suchen wie vorher auch die entsprechenden monster raus. Fertig.

Somit muss man nur EIN Element vorrätig halten und nicht die komplette Liste !

So nun zum Hero auf der allerersten Position der Liste. Wenn es fest steht das der immer auf der ersten Position sitzt, (weil er als
erstes in die Liste per AddElement() eingetragen wird), dann haben wir ja seine Position schon und müssen die Liste nach dem "Hero"
nicht mehr durchsuchen.

Dazu gibt PB weitere Befehle für Linklists mit. Es würde zum beispiel gehen :

Code: Alles auswählen

  If FirstElement(mon())
    *p = @mon()
  EndIf
oder aber auch

Code: Alles auswählen

  If SelectElement(mon(), 0)
    *p = @mon()
  EndIf
anstelle der ForEach Next Schleife.... Bei SelectElement ist der Indexparameter = 0, weil eine Linklist bei 0 anfängt zu zählen (also erstes Element : Index = 0, zweites Element: Index = 1 usw)
Zuletzt geändert von Bisonte am 09.02.2018 00:17, insgesamt 1-mal geändert.
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von diceman »

:allright: :allright: :allright:
Du solltest ein Buch schreiben!
Ja, das mit dem Hero an erster Stelle war nur so'n Beispiel. Kann ja mal sein, daß man zwei Elemente vergleichen will, deren Position man NICHT kennt, deswegen wollte ich diese Eventualität mit meinem Code-Snippet direkt mit abgedeckt haben. Werde morgen mal ein bißchen mit Pointern rumspielen, Prinzip und Syntax habe ich soweit verstanden, denke ich. Rumprobieren und Routine erledigt den Rest.
Danke liebe Leute, heute habe ich echt viel gelernt!
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
Bisonte
Beiträge: 2427
Registriert: 01.04.2007 20:18

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von Bisonte »

Du solltest ein Buch schreiben!
Mein Lateinlehrer sagte immer : Erklär deiner Oma wie das geht, wenn sie es dann kann, hast du es begriffen :mrgreen: ;)
PureBasic 6.04 LTS (Windows x86/x64) | Windows10 Pro x64 | Asus TUF X570 Gaming Plus | R9 5900X | 64GB RAM | GeForce RTX 3080 TI iChill X4 | HAF XF Evo | build by vannicom​​
Benutzeravatar
diceman
Beiträge: 347
Registriert: 06.07.2017 12:24
Kontaktdaten:

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von diceman »

Ich habe eine Lösung gefunden ... ich behaupte nicht, daß das praktikabel sei oder man das braucht, aber es hat Spaß gemacht, das auszutüfteln, und es war eine gute Übung fürs Verständnis, wie Listen, Strukturen und Elemente miteinander interagieren: :D

Funktionsweise:
- Es werden 2x 6 Actor-Elemente erstellt, und in einer eigenen Liste abgelegt (6 Monster und 6 Objekte). Jedes Element hat eine eigene ID (actorType), mit der man identifizieren kann, auf welche Liste es gehört.
- Wenn ich jetzt ALLE Elemente zusammengefasst in EINER Actor-Liste haben will, rufe ich zuvor einmal mergeActors() auf; in dieser Prozedur werden alle Actors in einer act()-Liste zusammengefasst. Die ursprünglichen monster()- und object()-Listen sind danach leer.
- Wenn ich wieder die einzelnen Listen haben will, rufe ich splitActors() auf, wo die Actors in einer For-Next-Schleife, welche den actorType vom maximalen Index auf 0 herunterzählt, auf die ursprünglichen Listen aufgesplittet werden. Das funktioniert, da bei Merge-Actors die Objekte default-mäßig immer hinten angestellt werden; wenn ich also den höchstmöglichen actorIndex aufrufe, wird immer nur der hintere Teil der act()-Liste abgespalten.
- Selbstverständlich darf man hier, wenn man die act()-Liste aktiv hat, keinerlei Listen-Elemente verschieben oder zufügen, sonst funktioniert das Splitten nicht mehr ordnungsgemäß. :?

Code: Alles auswählen

EnableExplicit

Declare createActors()
Declare mergeActors()
Declare splitActors()

Define a

#actorTypeMax = 1

Structure ACTOR
	actorType.i
	index.i
	x.i
	y.i
	name$
EndStructure

Global NewList act.ACTOR()
Global NewList monster.ACTOR()
Global NewList object.ACTOR()



createActors()

Debug "DEFAULT LIST"
ForEach monster()
	Debug Str(monster()\index)+". "+monster()\name$+" ("+monster()\x+","+monster()\y+")"
Next
ForEach object()
	Debug Str(object()\index)+". "+object()\name$+" ("+object()\x+","+object()\y+")"
Next
Debug ""

mergeActors()
Debug "ACTOR LIST"
ForEach act()
	Debug Str(act()\index)+". "+act()\name$+" ("+act()\x+","+act()\y+")"
Next
Debug ""

splitActors()
Debug "SPLIT LIST"
ForEach monster()
	Debug Str(monster()\index)+". "+monster()\name$+" ("+monster()\x+","+monster()\y+")"
Next
ForEach object()
	Debug Str(object()\index)+". "+object()\name$+" ("+object()\x+","+object()\y+")"
Next





Procedure createActors()
	Define i,o
	
	For i = 1 To 5
		AddElement(monster())
		monster()\actorType = 0
		monster()\index = i
		monster()\x = Random(5,0)
		monster()\y = Random(5,0)
		monster()\name$ = "Goblin"
	Next
	
	For o = 1 To 5
		AddElement(object())
		object()\actorType = 1
		object()\index = o
		object()\x = Random(5,0)
		object()\y = Random(5,0)
		object()\name$ = "Schatztruhe"
	Next
EndProcedure



Procedure mergeActors()
	MergeLists(monster(),act(),#PB_List_Last)
	MergeLists(object(),act(),#PB_List_Last)
EndProcedure



Procedure splitActors()
	Define i
	
	For i = #actorTypeMax To 0 Step -1
		ForEach act()
			If act()\actorType = i
				Select i
					Case 0 : SplitList(act(),monster())
					Case 1 : SplitList(act(),object())
				EndSelect
			EndIf
		Next
	Next
EndProcedure
Zuletzt geändert von diceman am 09.02.2018 16:19, insgesamt 2-mal geändert.
Now these points of data make a beautiful line,
And we're out of Beta, we're releasing on time.
Benutzeravatar
NicTheQuick
Ein Admin
Beiträge: 8675
Registriert: 29.08.2004 20:20
Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti
Wohnort: Saarbrücken
Kontaktdaten:

Re: Hilfe bei Strukturen (Elemente zufügen/löschen/finden)

Beitrag von NicTheQuick »

Und warum machst du das so kompliziert? Wieso packst du das alles nicht in eine Liste und überprüfst dann einfach nur den Typen mit einem kleinen If während du über die Liste läufst? Ständig Elemente hinzuzufügen und zu löschen kostet viel mehr Zeit.

An alle OOP-Hasser: Das hier ist übrigens mal wieder ein schöne Fall dafür. :wink: Das hier könnte man mit Vererbung und Überladung sehr schön bauen können.
Bild
Antworten