Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- (ns nim.core
- (:require [clojure.string :as string])
- (:gen-class))
- (defn winning-heaps? [heaps]
- (let [sum (reduce + heaps)]
- (and
- (or
- (and (every? #(> 2 %) heaps) (odd? sum))
- (zero? (reduce bit-xor heaps)))
- (not (zero? sum)))))
- (defn new-heaps [n min max]
- (let [heaps (vec (repeatedly n #(+ min (rand-int (- (inc max) min)))))]
- (if (winning-heaps? heaps)
- (let [first-row (nth heaps 0)]
- (if (== first-row max)
- (assoc heaps 0 (dec first-row))
- (assoc heaps 0 (inc first-row))))
- heaps)))
- (defn all-moves [heaps]
- (->> heaps
- (map-indexed (fn [index heap]
- (for [new-heap (range heap)]
- (assoc heaps index new-heap))))
- (apply concat)))
- (defn best-move [heaps]
- (if (winning-heaps? heaps)
- (first (for [new-heaps (all-moves heaps)
- :when (= (reduce + new-heaps) (dec (reduce + heaps)))] new-heaps))
- (first (for [new-heaps (all-moves heaps)
- :when (winning-heaps? new-heaps)] new-heaps))))
- (defn legal-move? [heaps move]
- (some #(= move %) (all-moves heaps)))
- (defn game-over? [heaps]
- (every? zero? heaps))
- (defn heap-string
- [heaps]
- (string/join (map-indexed (fn [row count]
- (str row ": " (string/join (repeat count "I")) "\n"))
- heaps)))
- (defn prompt
- [msg]
- (print (str msg " "))
- (flush)
- (read-line))
- (defn prompt-int
- [msg]
- (try
- (Integer. (prompt msg))
- (catch Exception e (prompt-int msg))))
- (defn input-move
- [heaps]
- (println (heap-string heaps))
- (let [row (prompt-int "From which row do you want to remove?")
- amount (prompt-int "How many do you want to leave?")]
- (when (and (neg? row) (>= row (count heaps)))
- (println "Illegal move!")
- (input-move heaps))
- (let [new-heaps (assoc heaps row amount)]
- (if-not (legal-move? heaps new-heaps)
- (do
- (println "Illegal move!")
- (input-move heaps))
- new-heaps))))
- (defn -main
- [& args]
- (loop [myturn false
- heaps (new-heaps 3 3 9)]
- (cond
- (and (game-over? heaps) myturn) (println "You lost!")
- (and (game-over? heaps) (not myturn)) (println "You won!")
- :else (if myturn
- (recur false (best-move heaps))
- (recur true (input-move heaps))))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement