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]
- (loop []
- (let [input (try (Integer. (prompt msg))
- (catch NumberFormatException _ nil))]
- (or input (recur)))))
- (defn input-move
- [heaps]
- (loop []
- (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?")
- move (try
- (let [new-heaps (assoc heaps row amount)]
- (if (legal-move? heaps new-heaps)
- new-heaps
- (throw (IllegalStateException. "Illegal move"))))
- (catch IndexOutOfBoundsException _ nil)
- (catch IllegalStateException _ nil))]
- (or move (do
- (println "Illegal move")
- (recur))))))
- (defn -main
- [& args]
- (loop []
- (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)))))
- (when (= "y" (prompt "Do you want to play again? y/n:")) (recur))))
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement