Lösungen für ein bekanntes Solitär-Game berechnen lassen

Code-Stücke können hier veröffentlicht werden.
Antworten
mukay
User
Beiträge: 2
Registriert: Montag 12. Oktober 2009, 12:57

Hallo,

es handelt sich um ein bekanntes Spiel (vl. kennt wer genauen Namen und Ursprung?). Meistens ist es ein Rundes Brett mit einer Rille am Rand in der man die geschlagenen Kugeln sammeln kann. In der Mitte des Spiels sind 33 kleine aushöhlungen für die Kugeln eingraviert.
Die Anordung sieht etwa so aus:

Code: Alles auswählen

  ***                                     OOO
  ***       *...Kugel                     OOO
*******     O...Loch                    OOOOOOO     mögliche Züge:
***O***     ----------------------->    OOO*OOO     **O -> OO* bzw: O** -> *OO
*******     und soll durch geeignetes   OOOOOOO       (eine Kugel springt über eine
  ***       ziehen nebenstehendes         OOO         andere in ein Loch)
  ***       Bild ergeben                  OOO         und natürlich auch vertikal
Folgender Code stellt die Funktionen zur Berechnung zur Verfügung. Die Berechnung erfolgt in der run_down() Methode. Es ist eine Rekursive Version auskommentiert (sie exceeded die Rekursionstiefe). Die Iterative Version führt halt nach 24h immer noch zu keinem Ergebnis. Hilfreich wäre nun ein Vorschlag was ich tun könnte um irgendwie die Lösungen berechnen zu können. (Ein Schachcomputer rechnet irgenwie auch nette spielzüge aus, schach hat aber sicher eine höhere Komplexität).
Nun der Code mit run_down() und einigen Hilfsmethoden.

Code: Alles auswählen

fd = [
    ['u','u','k','k','k','u','u'],
    ['u','u','k','k','k','u','u'],
    ['k','k','k','k','k','k','k'],
    ['k','k','k','l','k','k','k'],
    ['k','k','k','k','k','k','k'],
    ['u','u','k','k','k','u','u'],
    ['u','u','k','k','k','u','u']
]
it=[0L,0]

# liefert eine List die die Kombinationen 'k','k','l' od. 'l','k','k'
# im feld wiedergeben. Ein List-Element hat den Aufbau [z,s,<'h','v'>].
# z..Zeile, s..Spalte, 'h'..horizontal, 'v'..vertikal
def find():
    res = []
    for i in range(7):
        for j in range(5):
            if fd[i][j]=='k' and fd[i][j+1]=='k' and fd[i][j+2]=='l':
                res.append([i,j,'h'])
            elif fd[i][j]=='l' and fd[i][j+1]=='k' and fd[i][j+2]=='k':
                res.append([i,j,'h'])
            if fd[j][i]=='k' and fd[j+1][i]=='k' and fd[j+2][i]=='l':
                res.append([j,i,'v'])
            elif fd[j][i]=='l' and fd[j+1][i]=='k' and fd[j+2][i]=='k':
                res.append([j,i,'v'])
    return res;

# Führt einen Spielzug auf dem Feld aus
# coord: Koordinate an der der Spielzug aufgeführt werden soll
#        = List mit Elementen zeile[0-6],spalte[0-6],'v' od. 'h' für
#          horizontal oder vertikal
def move(coord):
    r = coord[0]
    c = coord[1]
    if coord[2]=='h':
        if fd[r][c]=='k':# and fd[r][c+1]=='k' and fd[r][c+2]=='l':
            fd[r][c]='l'
            fd[r][c+1]='l'
            fd[r][c+2]='k'
        else: #if fd[r][c]=='l':# and fd[r][c+1]=='k' and fd[r][c+2]=='k':
            fd[r][c]='k'
            fd[r][c+1]='l'
            fd[r][c+2]='l'
    else: #if coord[2]=='v':
        if fd[r][c]=='k':
            fd[r][c]='l'
            fd[r+1][c]='l'
            fd[r+2][c]='k'
        else:
            fd[r][c]='k'
            fd[r+1][c]='l'
            fd[r+2][c]='l'

# Führt auf dem Spielfeld einen Zug wieder zurück aus
# coord: List[zeile,spalte,'v' oder 'h' für vertikal oder horizontal]
def unmove(coord):
    r = coord[0]
    c = coord[1]
    if coord[2]=='h':
        if fd[r][c]=='k':# and fd[r][c+1]=='l' and fd[r][c+2]=='l':
            fd[r][c]='l'
            fd[r][c+1]='k'
            fd[r][c+2]='k'
        else: #if fd[r][c]=='l':# and fd[r][c+1]=='l' and fd[r][c+2]=='k':
            fd[r][c]='k'
            fd[r][c+1]='k'
            fd[r][c+2]='l'
    else: #if coord[2]=='v':
        if fd[r][c]=='k':
            fd[r][c]='l'
            fd[r+1][c]='k'
            fd[r+2][c]='k'
        else:
            fd[r][c]='k'
            fd[r+1][c]='k'
            fd[r+2][c]='l'

#Rekursive Version der Berechnung der Lösung(en)            
#def run_down(last_op):
#    ops=find()
#    if ops:
        #it[0]=it[0]+1
        #it.append(0)
        #it[it[0]]=len(ops)
#        for op in ops:
#            move(op)
#            run_down(op)
#            unmove(last_op)
#    else:
        #if check_fd():
        #    it[1]=it[1]+1
        #print('.')
#        unmove(last_op)

#Iterative Version der Berechnung der Lösung(en)
def run_down():
    cnt_depth=[]
    len_depth=[]
    op_depth=[]
    
    i=0
    ops=find()
    cnt_depth.append(0)
    len_depth.append(len(ops))
    op_depth.append(ops)
    while i>=0:
        if cnt_depth[i]<len_depth[i]:
            move(ops[cnt_depth[i]])
            ops=find()
            cnt_depth.append(0)
            len_depth.append(len(ops))
            op_depth.append(ops)
            i=i+1
        elif cnt_depth[i]==0:
            if not check_fd():
                i=i-1
                cnt_depth.pop()
                len_depth.pop()
                op_depth.pop()
                ops=op_depth[i]
                unmove(ops[cnt_depth[i]])
                cnt_depth[i]=cnt_depth[i]+1
            else:
                print(cnt_depth)
        else:
            i=i-1
            cnt_depth.pop()
            len_depth.pop()
            op_depth.pop()
            ops=op_depth[i]
            unmove(ops[cnt_depth[i]])
            cnt_depth[i]=cnt_depth[i]+1

# Liefert True, wenn das Spielfeld eine Lösung darstellt (nur mehr eine Kugel
# genau in der Mitte des Spielfeldes
def check_fd():
    if fd[3][3]=='k':
        for i in range(7):
            for j in range(7):
                if fd[i][j]=='k' and i<>3 and j<>3:
                    return False
    else:
        return False
    return True

# gibt das Spielfeld aus indem Kugeln mit * und Löcher mit O dargestellt werden
def print_fd():
    for i in range(7):
        p=""
        for j in range(7):
            if fd[i][j]=='u':
                p=p+' ';
            elif fd[i][j]=='k':
                p=p+'*';
            else:
                p=p+'O';
        print(p)
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

Mir ist nicht ganz klar, was du genau erreichen willst.
Willst du irgendeinen Lösungsweg finden? Oder alle? Oder den bzw. einen kürzesten?

Vielleicht hilft dir das, etwas Klarheit in die Sache zu bringen:
http://home.comcast.net/~gibell/pegsoli ... sults.html
mukay
User
Beiträge: 2
Registriert: Montag 12. Oktober 2009, 12:57

Es reicht eigentlich schon mal ein funktionierendes Programm, welches irgendeinen Lösungsweg findet. Alle, bzw. den kürzesten Weg zu finden ist für mich jetzt noch nicht wesentlich.
Der angegebene Link ist mir etwas zu kompliziert.
Benutzeravatar
numerix
User
Beiträge: 2696
Registriert: Montag 11. Juni 2007, 15:09

mukay hat geschrieben:Der angegebene Link ist mir etwas zu kompliziert.
Ich fürchte, das liegt in der Natur der Sache, denn ganz so einfach scheint mir das nicht zu sein, wenn man in akzeptabler (Rechen-)Zeit ein Ergebnis sehen will. :wink:
Antworten