Programmieren mit dem Taschenrechner TI-85

e-mail: Alfred Nussbaumer

Zum Inhaltsverzeichnis zurück

6. Programmieren von Spielen

Im Gegensatz zum Spielen selbst ist das Schreiben von Spielprogrammen meistens relativ anspruchsvoll, da oft mehrere zeitgleiche Eingaben verarbeitet werden müssen. Zusätzlich soll etwa eine Spielfigur auf neue Situationen reagieren und ein Spielstand ermittelt und gespeichert werden.. Um solche Aktivitäten korrekt ablaufen zu lassen, is es zunächst notwendig, die jeweilige Spielsituation richtig zu kennen (etwa indem man ein Spiel selbst entwirft), und dann muss ein entsprechender Taschenrechner-tauglicher Algorithmus entworfen und codiert werden.

Grundsätzlich müssen Spiele, die auf dem TI-85 laufen sollen, mit der geringen Auflösung des Textbildschirmes das Auslangen finden: Es stehen 8 Zeilen zu je 21 Spalten zur Verfügung. Für den Hintergrund und für die Spielfiguren können nur Zeichen ("Characters") verwendet werden, die im ROM des Taschenrechners gespeichert sind.

Im Folgenden sollen drei Spielideen realisiert werden:

  1. Bucht - "Nuggets sammeln" - Download "bucht.85.p"
  2. Invert - "Quadrate invertieren" Download "invert.85p"
  3. Miner - "Schätze im Labyrinth suchen" Download "miner.85p"

Beispiel: Bucht

Eine "Bucht" wird aus "Größer" und "Kleiner"-Zeichen und mit Hilfe der Anweisung 'outpt(Z,S,"<")' dargestellt. Von oben allen während des Spieles entweder Nuggets ("@") oder Vogelexkremente ("*") auf die Wasseroberfläche. Die Spielidee besteht nun darin, möglichst viele Nuggets aufzufangen und den Exkrementen auszuweichen. Dazu kann das Boot ("-") mit den Pfeiltasten nach links und nach rechts verschoben werden. Ein aufgefangenes Nugget bringt 10 Pluspunkte, ein Vogel-Patzer zieht 7 Punkte ab. Befindet man sich direkt unter einem Kotsternchen, so kann dieses mit Hilfe der "Pfeil nach oben"-Taste "weggeblasen werden - dabei gewinnt man 3 Punkte, muss aber für das "Blasrohr" 5 Punkte abgeben (trifft man also das Sternchen, so verliert man insgesamt nur 2 Punkte). Der Spielstand wird in der linken oberen Ecke angezeigt. Übertrifft das Spielergebnis den gespeicherten Wert der Highscore-Tabelle, so wird der Name es neuen "Helden" eingegeben und gespeichert...

	:ClLCD
	:0->C		Initialisieren des Punktezählers
	:10->S		Initialisieren der Spalte des Bootes
	:1->ZN		Initialisieren der Zeile des Nuggets
	:-3->ZS		Initialisieren der Zeile des Patzers
	:8->ZP		Initialisieren der Zeile des Pfeils
	:0->P		0 ... kein Pfiel, 1 ... Pfeil abgeschossen
	:Outpt(4,1,">")
	:Outpt(5,1,">")
	:Outpt(6,2,">")
	:Outpt(7,3,">")
	:Outpt(8,3,">")
	:Outpt(3,21,"<")
	:Outpt(4,20,"<")
	:Outpt(5,20,"<")
	:Outpt(6,20,"<")
	:Outpt(7,19,"<")
	:Outpt(8,19,"<")
	:int (rand*15+4)->SS	Zufallswert für Spalte des Nuggets
	:int (rand*15+4)->SN 	... für Spalte des Patzers
	:While (S>3) and (S<19) Programmschleife
	:Outpt(1,1,C)		Ausgabe des Punktestandes
	:S->SP
	:Outpt(8,S,"-")		Darstellung des Bootes
	:Outpt(ZN,SN,"@")	Darstellung des Nuggets
	:If Z>0
	:Outpt(ZS,SS,"*")	Darstellung des Patzers
	:If (P==1) and (ZP>0)
	:Outpt(ZP,SP,"^")	Darstellung des Pfeiles
	:If ZP==1
	:Then
	:Outpt(1,SP," ")
	:8->ZP
	:0->P
	:End
	:For(I,1,50)		Verzögerungsschleife
	:End
	:getKy->K		Tastendruck abfragen
	:If K==25		Pfeil nach oben
	:Then
	:C-5->C		Zählerstand verringern
	:1->P	
	:End
	:Outpt(ZN,SN," ")
	:If ZS>0
	:Outpt(ZS,SS," ")
	:Outpt(8,S," ")
	:If (P==1) and (ZP>0)
	:Outpt(ZP,SP," ")
	:If K==24		Pfeil nach links
	:Then
	:S-1->S
	:End
	:If K==26
	:Then
	:S+1->S
	:End
	:If (SN==S) and (ZN==7)
	:Then
	:0->ZN
	:C+10->C
	:End
	:If (SS==S) and (ZS==8) Nugget aufgefangen
	:Then
	:0->ZS
	:C-7->C
	:End
	:If (SP==SS) and (ZP==ZS)
	:Then
	:0->ZS
	:C+3->C
	:8->ZP
	:0->P
	:End
	:If P==1
	:ZP-1->ZP
	:If ZS<8
	:ZS+1->ZS
	:If ZN==7
	:Then
	:int (rand*15+4)->SN
	:1->ZN		
	:End
	:If ZS>7
	:Then
	:int (rand*15+4)->SS
	:1->ZS
	:End
	:If ZN<7
	:ZN+1->ZN
	:
	:End
	...
	:Return
          

Beispiel: Invert

Das Spielfeld besteht aus 9 Quadraten, die entweder weiß oder schwarz ("#") eingefärbt werden können. Das Spielziel besteht darin, alle 9 Quadrate, die den Positionen der Zifferntasten am Taschenrechner entsprechen, sichtbar zu machen. Dazu werden die Zifferntasten des Taschenrechners verwendet:

	[7]  [8]  [9]
	[4]  [5]  [6]
	[1]  [2]  [3]
          
  • [1] invertiert die Quadrate, die den Zifferntasten 1, 2, 4, 5 entsprechen
  • [2] invertiert die Quadrate 1, 2, 3
  • [3] invertiert die Quadrate 2, 3, 5, 6
  • [4] invertiert die Quadrate 1, 4, 7
  • [5] invertiert alle 9 Quadrate
  • [6] invertiert die Quadrate 3, 6, 9
  • [7] invertiert die Quadrate 4, 5, 7, 8
  • [8] invertiert die Quadrate 7, 8, 9
  • [9] invertiert die Quadrate 5, 6, 8, 9
  • [0] beendet das Spiel.

Zu Spielbeginn werden die Positionen der markierten Quadrate zufällig festgelegt. Die jeweilige Farbinformation jedes der 9 Quadrate wird in einer 3x3-Matrix gespeichert.

	:ClLCD
	:Fix 0
	:0->D
	:{3,3}->dim V
	:For(Z,1,3)		Spielstand ausgeben
	:For(S,1,3)	
	:If rand*100<50
	:Then
	:0->V(Z,S)
	:Outpt(Z+1,S+1," ")
	:Else
	:1->V(Z,S)
	:Outpt(Z+1,S+1,"#")
	:End			Ende von if
	:End			Ende von if
	:End			Ende von if
	:1->K
	:While K<>102	Solange nicht 0 gedrückt wurde...
	:Outpt(8,1,D)		Anzahl der Züge ausgeben
	:getKy->K		Taste einlesen
	:If K==92		Falls 1 gedrückt...
	:Then
	:D+1->D		Anzahl der Spielzüge inkrementieren
	:If V(2,1)==0		1. Quadrat in 2. Reihe invertieren
	:Then
	:1->V(2,1)
	:Else
	:0->V(2,1)
	:End
	:If V(2,2)==0		2. Quadrat in 2. Reihe invertieren
	:Then
	:1->V(2,2)
	:Else
	:0->V(2,2)
	:End
	:If V(3,1)==0		1. Quadrat in 3. Reihe invertieren
	:Then
	:1->V(3,1)
	:Else
	:0->V(3,1)
	:End
	:If V(3,2)==0		2. Quadrat in 3. Reihe invertieren
	:Then
	:1->V(3,2)
	:Else
	:0->V(3,2)	
	:End
	:End
	:If K==93
	:Then
	:D+1->D
	:If V(3,1)==0	
	:Then
	:1->V(3,1)
	:Else
	:0->V(3,1)
	:End
	:If V(3,2)==0
	:Then
	:1->V(3,2)
	:Else
	:0->V(3,2)
	:End
	:If V(3,3)==0	
	:Then
	:1->V(3,3)
	:Else
	:0->V(3,3)
	:End
	:End
	:If K==94
	:Then
	:D+1->D
	:If V(3,2)==0
	:Then
	:1->V(3,2)
	:Else
	:0->V(3,2)
	:End
	:If V(3,3)==0
	:Then
	:1->V(3,3)
	:Else
	:0->V(3,3)
	:End
	:If V(2,2)==0
	:Then
	:1->V(2,2)
	:Else
	:0->V(2,2)	
	:End
	:If V(2,3)==0
	:Then
	:1->V(2,3)
	:Else
	:0->V(2,3)
	:End
	:End
	:If K==82
	:Then
	:D+1->D
	:If V(1,1)==0
	:Then
	:1->V(1,1)
	:Else
	:0->V(1,1)
	:End
	:If V(2,1)==0
	:Then
	:1->V(2,1)
	:Else
	:0->V(2,1)
	:End
	:If V(3,1)==0
	:Then
	:1->V(3,1)
	:Else
	:0->V(3,1)
	:End
	:End
	:If K==83
	:Then
	:D+1->D
	:If V(1,1)==0
	:Then
	:1->V(1,1)
	:Else
	:0->V(1,1)
	:End
	:If V(1,2)==0
	:Then
	:1->V(1,2)
	:Else
	:0->V(1,2)
	:End
	:If V(1,3)==0
	:Then
	:1->V(1,3)
	:Else
	:0->V(1,3)
	:End
	:If V(2,1)==0
	:Then
	:1->V(2,1)
	:Else
	:0->V(2,1)
	:End
	:If V(2,2)==0
	:Then
	:1->V(2,2)
	:Else
	:0->V(2,2)
	:End
	:If V(2,3)==0
	:Then
	:1->V(2,3)
	:Else
	:0->V(2,3)
	:End
	:If V(3,1)==0
	:Then
	:1->V(3,1)
	:Else
	:0->V(3,1)
	:End
	:If V(3,2)==0
	:Then
	:1->V(3,2)
	:Else
	:0->V(3,2)
	:End
	:If V(3,3)==0
	:Then
	:1->V(3,3)
	:Else
	:0->V(3,3)
	:End
	:End
	:If K==84
	:Then
	:D+1->D
	:If V(3,3)==0
	:Then
	:1->V(3,3)
	:Else
	:0->V(3,3)
	:End
	:If V(2,3)==0	
	:Then
	:1->V(2,3)
	:Else
	:0->V(2,3)
	:End
	:If V(1,3)==0
	:Then	
	:1->V(1,3)
	:Else
	:0->V(1,3)
	:End
	:End
	:If K==72
	:Then
	:D+1->D
	:If V(1,1)==0
	:Then
	:1->V(1,1)
	:Else
	:0->V(1,1)
	:End
	:If V(1,2)==0
	:Then
	:1->V(1,2)
	:Else
	:0->V(1,2)
	:End
	:If V(2,1)==0
	:Then
	:1->V(2,1)
	:Else
	:0->V(2,1)
	:End
	:If V(2,2)==0
	:Then
	:1->V(2,2)
	:Else
	:0->V(2,2)
	:End
	:End
	:If K==73
	:Then
	:D+1->D
	:If V(1,1)==0
	:Then
	:1->V(1,1)
	:Else
	:0->V(1,1)
	:End
	:If V(1,2)==0
	:Then
	:1->V(1,2)
	:Else
	:0->V(1,2)
	:End
	:If V(1,3)==0
	:Then
	:1->V(1,3)
	:Else
	:0->V(1,3)
	:End
	:End
	:If K==74
	:Then
	:D+1->D
	:If V(1,2)==0
	:Then
	:1->V(1,2)
	:Else
	:0->V(1,2)
	:End
	:If V(1,3)==0
	:Then
	:1->V(1,3)
	:Else
	:0->V(1,3)
	:End
	:If V(2,2)==0
	:Then
	:1->V(2,2)
	:Else
	:0->V(2,2)
	:End
	:If V(2,3)==0
	:Then
	:1->V(2,3)
	:Else
	:0->V(2,3)
	:End
	:End
	:For(Z,1,3)		Neuen Spielstand ausgeben
	:For(S,1,3)
	:If V(Z,S)==0
	:Then
	:Outpt(Z+1,S+1," ")
	:Else
	:Outpt(Z+1,S+1,"#")
	:End
	:End
	:End
	:End
	:Return
          

Beispiel: Miner

Mit der Spielfigur "*" sollen wertvolle "Mineralien", die durch ihren "Wert", einer einstelligen Zahl dargestellt werden, aus dem Berg geholt werden. Allerdings versperreen zahlreiche Monster den Weg zwischen dem Bergmann und dem Schatz. Mit den Pfeiltasten wird nun der Bergmann zwischen den Monstern zu den Ziffern gesteuert - das Spiel endet sofort, wenn er auf ein Feld zu stehen kommt, das von einem Monster besetzt ist...

Zu Beginn werden per Zufall 10 Monster über das Spielfeld verstreut, der erste Schatz erhält einen Wert zwischen 1 und 9 und wird zufällig positioniert. Sobald der Bergmann den Schatz gehoben hat, wird der Zahlenwert als Punkteguthaben gespeichert und es werden weitere 10 Monster zufällig im Spielfeld positioniert, sodass almmählich ein regelrechtes Labyrinth entsteht. Mit Hilfe der [F5]-Taste kann der Bergmann (ab einem bestimmten Mindestpunktestand) rings um seine Position sitzende Monster entfernen - dies kostet aber 5 Punkte vom Guthaben...

Nach dem Spielende wird das Guthaben mit dem gespeicherten HighScore verglichen und gegebenenfalls der Name des neuen Helden gespeichert. Achtug: Ab einem bestimmten Spielstand ist es nicht mehr möglich, einen Nettogewinn zu erzielen!

Das Spielfeld ist "als Torus" aufgerollt: Der Bergmann kann über den Rand des Spielfelds hinaus zur gebenüberliegenden Seite des Feldes gelangen (und auf diese Weise einigen Monstern entkommen).

	PROGRAM:MINER
	:ClLCD
	:Disp "Best:",HH
	:Disp "Score:",H
	:Pause 	
	:ClLCD
	:Fix 0			Nur Ganzzahl anzeigen
	:{8,21}->dim M	Matrix für 8 Zeilen und 21 Spalten
	:For(Z,1,8)		
	:For(S,1,21)
	:0->M(Z,S)		Matrixelemente auf 0 setzen
	:End
	:End
	:1->X
	:0->C
	:1->Z
	:1->S
	:0->D
	:While X<>0	Programmschleife	
	:For(I,1,10)		An 10 zufällig gewählten
				Positionen "Monster" setzen
	:int (rand*8+1)->A
	:int (rand*21+1)->B
	:1->M(A,B)
	:Outpt(A,B,"Ê")
	:End
	:int (rand*9+1)->F	Zufallszahl an Zufallsposition ("Schatz")
	:int (rand*8+1)->A
	:int (rand*21+1)->B
	:F->M(A,B)
	:Outpt(A,B,F)
	:Outpt(Z,S,"*")
	:1->L
	:While L<>0	Schleife für Bewegen des "Bergmanns"
	:getKy->K		Tastaturabfrage
	:If K==102		Abbruch mit Taste [0]
	:0->L
	:If K==15		Monster mit Taste [F5] entfernen
	:Then
	:If C>30		... aber nur, falls mehr als 30 Gutpunkte
	:Then
	:For(I,0,3)
	:If Z-I>=1
	:Then
	:0->M(Z-I,S)
	:Outpt(Z-I,S," ")	
	:End
	:If Z+I<=8
	:Then
	:0->M(Z+I,S)
	:Outpt(Z+I,S," ")
	:End
	:If S-I>=1
	:Then
	:0->M(Z,S-I)
	:Outpt(Z,S-I," ")
	:End
	:If S+I<=21
	:Then
	:0->M(Z,S+I)
	:Outpt(Z,S+I," ")
	:End
	:End
	:C-5->C		... Monster entfernen kostet 5 Gutpunkte
	:End
	:End
	:If K==24		Falls [Pfeil nach links] gedrückt...
	:Then
	:Outpt(Z,S," ")		... löche "*"
	:D+1->D		... erhöhe die Anzahl der Schritte
	:S-1->S		... verringere die Spaltenposition
	:End
	:If K==26		analog "nach rechts"
	:Then
	:Outpt(Z,S," ")
	:D+1->D
	:S+1->S
	:End
	:If K==25		analog "nach oben"
	:Then
	:Outpt(Z,S," ")
	:D+1->D
	:Z-1->Z
	:End
	:If K==34		analog "nach unten"
	:Then
	:Outpt(Z,S," ")
	:D+1->D
	:Z+1->Z
	:End
	:If S<1		Test ob der Rand des Bildschirms erreicht
	:21->S
	:If S>21		detto
	:1->S
	:If Z<1		detto
	:8->Z
	:If Z>8		detto
	:1->Z
	:If M(Z,S)==F		Falls ein Feld mit einem Schatz 
					betreten wurde...
	:Then
	:C+F->C		... addiere den Wert zu Gutpunkten
	:0->L		... beende innere Schleife
	:0->M(Z,S)		... gib das Feld frei	
	:End
	:If M(Z,S)==0		Falls das Feld leer ist...
	:Then
	:Outpt(Z,S,"*")		... gib das "*" ("Bergmann") aus
	:Else
	:If M(Z,S)==1		... falls dort aber ein "Monster" sitzt...
	:Then
	:0->X		... Abbruch der äußeren  Schleife
	:0->L		... Abbruch der inneren Schleife	
	:End
	:End
	:End
	:End
	:ClLCD			Ausgabe des Spielergebnisses...
	:If C>H
	:Then
	:C->H
	:InpSt "Best:",HH
	:Else
	:Disp 
	:Disp "   Sorry - Looser"
	:End
	:Pause 
	:Return