fb:porticula NoPaste
Nim-Spiel mit Alpha-Beta-Suche
Uploader: | nemored |
Datum/Zeit: | 14.09.2011 22:38:30 |
' Ein einfaches Nim-Spiel, bei dem der Computer die Alpha-Beta-Suche einsetzt
' Jeder Spieler wählt abwechselnd eine Reihe und entfernt aus ihr
' eine beliebige Anzahl an Streichhölzern (mindestens eines)
' Wer das letzte Streichholz nehmen muss, verliert.
'
' Damit die Computerzüge nicht zu stereotyp sind, wählt der Computer dann,
' wenn er sowieso auf der Verliererstraße ist, einen zufälligen Zug aus.
#DEFINE Mensch 1
#DEFINE Computer -1
TYPE zugtyp
AS INTEGER reihe, anz, wert
END TYPE
DIM SHARED AS INTEGER reihenzahl = 5, rechentiefe = 16, reihe(1 TO reihenzahl), gesamtzahl
FOR r AS INTEGER = 1 TO reihenzahl
reihe(r) = r
gesamtzahl += r
NEXT
DIM AS INTEGER spieler = 1, r, anz
DIM zug AS zugtyp, taste AS STRING
RANDOMIZE
FUNCTION alphabeta(resttiefe AS INTEGER, alph AS INTEGER, bet AS INTEGER) AS zugtyp
DIM AS INTEGER besteReihe, besteAnz, zugWert
' generiere mögliche Zuege
FOR r AS INTEGER = 1 TO reihenzahl
FOR anz AS INTEGER = reihe(r) TO 1 STEP -1
gesamtzahl -= anz
IF gesamtzahl = 0 THEN 'letzten Stein genommen
zugwert = -1
ELSE
IF restTiefe <= 1 THEN
zugWert = 0
ELSE
reihe(r) -= anz
zugWert = -alphabeta(restTiefe-1, -bet, -alph).wert
reihe(r) += anz
END IF
END IF
gesamtzahl += anz
IF zugWert > alph THEN
alph = zugWert
besteReihe = r
besteAnz = anz
END IF
IF alph >= bet THEN RETURN TYPE(besteReihe, besteAnz, 1)
NEXT
NEXT
IF alph >= 0 THEN RETURN TYPE(besteReihe, besteAnz, alph)
' keinen Gewinnzug gefunden; damit ist es egal, wie gezogen wird
DO
besteReihe = INT(RND*reihenzahl) + 1
IF reihe(besteReihe) = 0 THEN CONTINUE DO
besteAnz = INT(RND*reihe(besteReihe)) + 1
RETURN TYPE(besteReihe, besteAnz, alph)
LOOP
END FUNCTION
DO
' neues Spiel
PRINT "Wer beginnt? (1) Spieler (2) Computer (0) Ende"
DO
taste = INPUT(1)
LOOP UNTIL taste = "1" OR taste = "2" OR taste ="0"
IF taste = "0" THEN EXIT DO
IF taste = "1" THEN spieler = Mensch ELSE spieler = Computer
' Spielstart
DO
'Spielfeld zeichnen
CLS
FOR r AS INTEGER = 1 TO reihenzahl
PRINT r & ") " & SPACE(reihenzahl - r);
FOR anz AS INTEGER = 1 TO reihe(r)
PRINT "| ";
NEXT
PRINT : PRINT
NEXT
IF gesamtzahl = 0 THEN
PRINT "Das Spiel ist aus. Du hast ";
IF spieler = Mensch THEN PRINT "gewonnen!" ELSE PRINT "verloren!"
EXIT DO, DO
END IF
IF spieler = Mensch THEN
PRINT "Gib eine Reihe an (1-" & reihenzahl & "), in der sich noch Striche befinden."
PRINT "'0' beendet das Spiel."
DO
taste = INPUT(1)
IF taste = "0" THEN EXIT DO, DO, DO
r = VAL(taste)
LOOP UNTIL r > 0 AND r <= reihenzahl ANDALSO reihe(r) > 0
PRINT "Gib an, wie viele Striche du entfernen willst (1-" & reihe(r) & ")."
DO
anz = VAL(INPUT(1))
LOOP UNTIL anz > 0 AND anz <= reihe(r)
reihe(r) -= anz
gesamtzahl -= anz
ELSE
zug = alphabeta(rechentiefe, -2, 2)
PRINT "Der Computer wird aus der " & zug.reihe & ". Reihe " & zug.anz & " Strich(e) entfernen."
PRINT "(Die neue Spielsituation wird erst nach einem Tastendruck angezeigt.)"
reihe(zug.reihe) -= zug.anz
gesamtzahl -= zug.anz
GETKEY
END IF
spieler = -spieler
LOOP
LOOP