Created
March 17, 2012 18:59
-
-
Save jmgimeno/2064173 to your computer and use it in GitHub Desktop.
Rock, paper, scissors
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Una de les formes de trobar bones solucions és trobar bones | |
;; estructures de dades de partida. | |
;; Aquí has de representar tres coses: | |
;; 1. Regles del joc (quina cosa guanya a què) | |
;; 2. Resultats d'una ronda | |
;; 3. Resulatats d'un torneig | |
;; Formes de representar 1. | |
;; Per les elecciones, poden usar keywords y dir que tenim :paper | |
;; :scissors i :rock (:lizard i :spock queda com exercici) i per | |
;; indicar qui guanya podem fer servi p.e. un conjunt de parelles: | |
(def rpsRules #{ [:paper :rock] [:rock :scissors] [:scissors :paper] }) | |
;; Per a un resultat modem fer servir un maya entre jugador i elecció, per exemple: | |
(def result1 {:jugador1 :rock :jugador2 :paper}) | |
;; Per a un torneig una llista de resultats (no valdría un conjunt | |
;; doncs podem tenor dos jugadors que en rondes diferents escullen el | |
;; mateix). | |
;; La funció aquesta retorna el jugador que ha guanyat o nil en cas | |
;; d'empat. | |
;; Una primera solució | |
(defn whoWins [result] | |
(let [[player1 player2] (keys result) | |
[choice1 choice2] (vals result)] | |
(cond | |
(rpsRules [choice1 choice2]) player1 | |
(rpsRules [choice2 choice1]) player2 | |
:else nil))) | |
;; Un refinament (bastant més funcional): | |
(defn whoWins [result] | |
(let [choices (vals result)] | |
(if (apply not= choices) | |
((if (rpsRules choices) first second) (keys result))))) | |
;; Ara poodem saber | |
(whoWins result1) | |
(def tournament [{:jugador1 :rock :jugador2 :paper} | |
{:jugador1 :paper :jugador2 :paper} | |
{:jugador1 :scissors :jugador2 :paper} | |
{:jugador1 :scissors :jugador2 :rock} | |
{:jugador1 :rock :jugador2 :paper}]) | |
;; Com estem fent servir estructures estàndar, podem aplicar les | |
;; funcions predefinides per veure el resultat de totes les rondes: | |
(map whoWins tournament) | |
;; O comptabilitzar els resultats | |
(frequencies (map whoWins tournament)) | |
;; O agafar els resultats que no han acabat en empat | |
(filter whoWins tournament) | |
;; O les victòries del :jugador1 | |
(filter #(= :jugador1 (whoWins %)) tournament) | |
;; NOTA: La setmana vinent veurem tota aquesta sintaxi (espero). | |
;; Com whoWins depèn de les regles de joc, podem fer una funció que | |
;; rebi com a paràmetre les regles de joc i retorni una funció tal que | |
;; donat un resultat dihui qui guanya: | |
;; Forma 1: | |
(defn makeWhoWins [rules] | |
(fn [result] | |
(let [choices (vals result)] | |
(if (apply not= choices) | |
((if (rules choices) first second) (keys result)))))) | |
(def rpsWhoWins (makeWhoWins rpsRules)) | |
;; Forma 2: | |
(defn generalizedWhoWins [rules result] | |
(let [choices (vals result)] | |
(if (apply not= choices) | |
((if (rules choices) first second) (keys result))))) | |
(def rpsWhoWins (partial generalizedWhoWins rpsRules)) | |
;; Una vegada generalitzades les coses, podem canviar de joc. | |
;; P.e. daus (guanya qui treu el dau més alt) | |
(def diceTournament [{:player1 3 :player2 3} | |
{:player1 1 :player2 4} | |
{:player1 6 :player2 1} | |
{:player1 3 :player2 2}]) | |
(defn diceRules [[dice1 dice2]] | |
(> dice1 dice2)) | |
(def diceWhoWins (makeWhoWins diceRules)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment