2012-10-29 8 views
5

Per imparare Clojure Sto lavorando a un piccolo gioco Tic Tac Toe. Dopo aver completato la prima parte del gioco con relativa facilità, ho faticato a provare a costruire un riproduttore di computer intelligente.Clojure: Iterating su un vettore di vettori per trovare il primo vettore che soddisfa una determinata condizione

Per la prova che sto scrivendo per aiutare a guidare questo, voglio verificare che il computer raccoglie punto 9 se è il turno del computer e questo è il consiglio:

X | O | 3
4 | X | O
7 | 8 | 9

per iniziare il gioco, la scheda viene definito in questo modo, come una mappa con coppie chiave-valore che rappresentano la posizione sulla scheda e il contenuto di quello spazio:

(def board {1 "1" 2 "2" 3 "3" 4 "4" 5 "5" 6 "6" 7 "7" 8 "8" 9 "9"}) 

ho avuto alcuni pensieri su come risolvere questo problema. Uno era di definire i set vincenti come questo:

(def winning-sets 
    [[(board 1) (board 2) (board 3)], 
    [(board 4) (board 5) (board 6)], 
    [(board 7) (board 8) (board 9)], 
    [(board 1) (board 4) (board 7)], 
    [(board 2) (board 5) (board 8)], 
    [(board 3) (board 6) (board 9)], 
    [(board 1) (board 5) (board 9)], 
    [(board 3) (board 5) (board 7)]]) 

iterare su ogni set:

(for [set winning-sets] 
    (filter #(= symbol %) set)) 

Ma questo non mi sembra giusto ... non so dove sarei andato da lì . Il problema che sto cercando di risolvere può essere descritto in questo modo:

dire al computer di guardare oltre gli 8 set vincenti e trovare un set che ha due dei vostri simboli e un punto aperto.

Sono abbastanza nuovo per Clojure, quindi non sono sicuro di aver capito il modo migliore per affrontare questo problema. Ho esaminato lo ClojureDocs (verificando le funzioni iterating come for e loop e case), ma non sono riuscito a farlo funzionare.

Quale sarebbe il modo migliore per scorrere su quei set vincenti, attualmente in forma vettoriale, e trovare il set che ha due di un simbolo specifico e un'apertura? O sarebbe meglio memorizzare i set vincenti in una struttura dati diversa?

NOTA: Ho letto le risposte a this question, ma non sono stato in grado di applicarle al mio.

+0

Penso che tu voglia una qualche funzione. – Kevin

risposta

4

Prima di tutto, vi consiglio di utilizzare questa struttura per la posizione di bordo:

(def board [[1 1 0] 
      [0 0 0] 
      [1 0 1]]) 

Dove X è 1, O è -1 e cella vuota è 0. Board nel mio esempio ha solo simboli X (per semplificare). Successivamente,

(def winning-sets 
    '([[0 0] [0 1] [0 2]] 
    [[1 0] [1 1] [1 2]] 
    [[2 0] [2 1] [2 2]] 
    [[0 0] [1 0] [2 0]] 
    [[0 1] [1 1] [2 1]] 
    [[0 2] [1 2] [2 2]] 
    [[0 0] [1 1] [2 2]] 
    [[0 2] [1 1] [2 0]])) 

Questo è "vincente" set di coordinate. Puoi calcolarlo se necessario, ma per 3x3 questa lista non è davvero così grande.In questi termini, la risposta per voi domanda è

(defn check 
    [target combo] 
    (= (map #(count (filter (partial = %) combo)) [target 0]) '(2 1))) 

(defn extract 
    [coords] 
    (apply vector (map (fn [[f s]] ((board f) s)) coords))) 

(filter #(check 1 (extract %)) winning-sets) 

Se si esegue questo codice in REPL, si vedrà

user=> (filter #(check 1 (extract %)) winning-sets) 
([[0 0] [0 1] [0 2]] 
[[2 0] [2 1] [2 2]] 
[[0 0] [1 0] [2 0]] 
[[0 0] [1 1] [2 2]]) 

che si presenta come risposta giusta (2 linee orizzontali, 1 verticale e 1 diagonale). Il codice è approssimativo e ci sono alcuni modi per renderlo più bello e riutilizzabile. Devo spiegare cosa sta succedendo o il codice è abbastanza chiaro?