@kbr: Ich gehe da jetzt auch von einer Version ohne Klassen aus, das ändert ja nichts daran wie man vorgeht, sondern nur mit welchen Mitteln man das ausdrücken kann. Wie Hyperion schon sagte wissen wir fast nichts über den einzelnen Spieler. Wahrscheinlich kann man seinen Zustand mit einem einzigen skalaren Wert beschreiben, und seine ”Identität” aus der Position in einer Liste ableiten (Spieler 1, Spieler 2, …). Falls ein skalarer Wert nicht reicht, legt man die Daten für einen Spieler in einer Liste ab. Eigentlich besser ein Tupel, aber das wurde bisher ja nicht erwähnt.
Was auch nicht erwähnt wurde sind Funktionen, aber die setze ich jetzt mal voraus, denn ohne wird das eine Übung in „wie man es nicht macht, und auch gar nicht erst lernen sollte“.
@__deets__: Also man kann das schon mit Funktionen ordentlich und ohne globale Variablen machen würde ich sagen. Das wird dann halt ein wirklich eher funktionaler Ansatz.
SPIEL
- __blackjack__
- User
- Beiträge: 13100
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
@__blackjack__: hmja, das wird sehr dialektisch. Klar kann ich allen Zustand auch immer reingeben. Und den zB auch auf Ebene der main-Funktion deklarieren, statt wirklich Modul-global. Aber das es nun ein empfehlenswertes und signifikant besserer Ansatz waere bei diesem Problem finde ich nicht. Es ist Zustand + ein Sack Funktionen die darauf arbeite, und den zB auch modifizieren. Das ist nun wirklich marginal besser als globale Variablen und konzeptionell wenn man OO haette auch nicht der Ansatz, den man waehlen wuerde. Voll funktional geht natuerlich auch, aber dann wird es schon etwas sehr abgefahren, und ohne tail-Rekursion auch immer ein bisschen gelogen.
@__blackjack__: Sicher, wenn ein Spieler über ein Tupel modelliert wird, geht es auch ohne Spielfeldliste. Für diese Lösung hilft es aber, wenn bereits in Objekten und Eigenschaften gedacht wird – und ich bezweifle, dass der Kurs so weit ist. Aber das ist geraten, denn in der Tat wissen wir einfach zu wenig über den Kenntnisstand, der für die Aufgabe vorausgesetzt wird.
- __blackjack__
- User
- Beiträge: 13100
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
@kbr: Ich hab's nicht bis zum Ende durchgedacht, aber braucht man für einen Spieler zwingend mehr als eine Zahl die den aktuellen Zustand widerspiegelt?
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- Hyperion
- Moderator
- Beiträge: 7478
- Registriert: Freitag 4. August 2006, 14:56
- Wohnort: Hamburg
- Kontaktdaten:
Wenn es zu viele Spieler werden (war die Zahl vorgegeben?) wird eine Liste natürlich mau... ansonsten reicht doch das:
Die Spieler sind dabei nur implizit durch den Index in der Liste bestimmt - nicht schön, aber genügt imho.
Code: Alles auswählen
players = [0, 3, 5, 7, 12]
encoding_kapiert = all(verstehen(lesen(info)) for info in (Leonidas Folien, Blog, Folien & Text inkl. Python3, utf-8 everywhere))
assert encoding_kapiert
assert encoding_kapiert
- __blackjack__
- User
- Beiträge: 13100
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Apropos nicht schön – eine Lösung in einer Programmiersprache in der es keine Funktionen¹, und keine benutzerdefinierten Datentypen, und schon gar keine Objekte gibt – GW-BASIC:
1) Keine Funktionen stimmt nicht so ganz, weil man sich mit DEF FN Funktionen mit definieren kann, die aus einem einzigen Ausdruck bestehen dürfen. Also ähnliche Einschränkungen wie bei Python's ``lambda``-Ausdrücken.
Code: Alles auswählen
10 RANDOMIZE TIMER:INPUT"Anzahl der Spieler";PC:INPUT"Anzahl Spielfelder";FC
20 DIM PP(PC):FOR I=1 TO PC:PP(I)=1:NEXT:PI=1
30 ' Main loop.
40 P$="Spieler"+STR$(PI)+" ":PRINT:PRINT P$;"ist am Zug.":GOSUB 70
50 IF FW THEN PRINT P$;"hat gewonnen!":END
60 PI=(PI MOD PC)+1:GOTO 30
70 ' Play one round with player PI.
80 PP=PP(PI):V=INT(RND*6)+1:NP=PP+V
90 PW$=P$+"hat eine"+STR$(V)+" gewürfelt":PRINT PW$;"."
100 GOSUB 150:IF F THEN PRINT"Zielfeldnummer ist eine Schnapszahl: +5":NP=NP+5
110 IF NP>FC THEN 130
120 PRINT P$;"zieht von";PP;"nach";STR$(NP);".":GOSUB 200:PP(PI)=NP
130 FW=NP=FC:IF FW OR (V<>6) THEN RETURN
140 PRINT PW$;" und ist weiterhin am Zug.":GOTO 70
150 ' Check if target field number is repdigit.
160 IF NP<11 THEN F=0:RETURN
170 T$=STR$(NP):A$=MID$(T$,2,1):X=0:FOR I=2 TO LEN(T$)
180 IF MID$(T$,I,1)=A$ THEN X=X+1
190 NEXT:F=X=LEN(T$)-1:RETURN
200 ' Move players on field NP back by 2 fields.
210 BP=NP-2:IF BP<1 THEN BP=1
220 FOR I=1 TO PC:IF PP(I)<>NP THEN 240
230 PRINT"Spieler";I;"wird auf Position";BP;"zurückgesetzt.":PP(I)=BP
240 NEXT:RETURN
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- __blackjack__
- User
- Beiträge: 13100
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Mir fiel gerade auf, dass ein ungünstige Kombination in den Regeln (sofern ich die überhaupt korrekt interpretiere) von dem obigen Programm nicht abgedeckt wird und zu einer Endlosschleife führt. Also nicht einfach blind übernehmen.
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman
- __blackjack__
- User
- Beiträge: 13100
- Registriert: Samstag 2. Juni 2018, 10:21
- Wohnort: 127.0.0.1
- Kontaktdaten:
Soo, Zeilennummern entfernt und wo nötig durch Sprungmarken ersetzt, und nun mit QBasic ausführbar. Der Fehler ist behoben und der Test auf Schnappszahl ist jetzt ”mathematischer” gelöst – heisst der Zeichenkettenspeicher wird weniger vollgemüllt.
Code: Alles auswählen
RANDOMIZE TIMER
DIM PlayerCount AS INTEGER, FieldCount AS INTEGER, PlayerIndex AS INTEGER
DIM i AS INTEGER, isRepdigit AS INTEGER, n AS INTEGER, digit AS INTEGER
DIM hasWon AS INTEGER, score AS INTEGER, newPosition AS INTEGER
DIM backPosition AS INTEGER
INPUT "Anzahl der Spieler"; PlayerCount
INPUT "Anzahl Spielfelder"; FieldCount
DIM PlayerPosition(PlayerCount) AS INTEGER
FOR i = 1 TO PlayerCount
PlayerPosition(i) = 1
NEXT
PlayerIndex = 1
DO
p$ = "Spieler" + STR$(PlayerIndex) + " "
PRINT : PRINT p$; "ist am Zug."
GOSUB PlayTurn
IF hasWon THEN EXIT DO
PlayerIndex = (PlayerIndex MOD PlayerCount) + 1
LOOP
PRINT p$; "hat gewonnen!"
END
' Play one turn with player at PlayerIndex.
PlayTurn:
DO
PlayerPosition = PlayerPosition(PlayerIndex)
score = INT(RND * 6) + 1
newPosition = PlayerPosition + score
PW$ = p$ + "hat eine" + STR$(score) + " gewürfelt"
PRINT PW$; "."
IF newPosition <> FieldCount THEN
n = newPosition
GOSUB CheckRepdigit
IF isRepdigit THEN
PRINT "Zielfeldnummer ist eine Schnapszahl: +5"
newPosition = newPosition + 5
END IF
END IF
IF newPosition <= FieldCount THEN
PRINT p$; "zieht von"; PlayerPosition; "nach"; STR$(newPosition); "."
GOSUB MoveBack
PlayerPosition(PlayerIndex) = newPosition
END IF
hasWon = newPosition = FieldCount
IF hasWon OR (score <> 6) THEN EXIT DO
PRINT PW$; " und ist weiterhin am Zug."
LOOP
RETURN
' Check if n is repdigit.
CheckRepdigit:
digit = n MOD 10
isRepdigit = n > 9
DO WHILE n <> 0
IF (n MOD 10) <> digit THEN
isRepdigit = 0
EXIT DO
END IF
n = n \ 10
LOOP
RETURN
' Move players on field newPosition back by 2 fields.
MoveBack:
backPosition = newPosition - 2
IF backPosition < 1 THEN backPosition = 1
FOR i = 1 TO PlayerCount
IF PlayerPosition(i) = newPosition THEN
PRINT "Spieler"; i; "wird auf Position"; backPosition; "zurückgesetzt."
PlayerPosition(i) = backPosition
END IF
NEXT
RETURN
„All religions are the same: religion is basically guilt, with different holidays.” — Cathy Ladman