From d1638ac376fa854de9e99abbbb10b723508b4c44 Mon Sep 17 00:00:00 2001 From: Jan-Eric Nitschke <47750513+JanEricNitschke@users.noreply.github.com> Date: Fri, 7 Jun 2024 08:12:46 +0200 Subject: [PATCH] Add logic for first three AI strengths. --- tictactoe_clojure/tictactoe.clj | 69 +++++++++++++++++++++++---------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/tictactoe_clojure/tictactoe.clj b/tictactoe_clojure/tictactoe.clj index d40f062..581465d 100644 --- a/tictactoe_clojure/tictactoe.clj +++ b/tictactoe_clojure/tictactoe.clj @@ -1,23 +1,11 @@ (def win-conditions [[0 1 2] [3 4 5] [6 7 8] [0 3 6] [1 4 7] [2 5 8] [0 4 8] [2 4 6]]) -(defn ask [] - (println "Please answer \"y\"[yes] or \"n\"[no]:") - (.trim (read-line))) - -(defn get-valid-answer [question] - (println question) - (let [answer (->> (repeatedly ask) - (filter #{"y" "n"}) - (first))] - (= answer "y"))) - (defn swap-player [player] (if (= player "X") "O" "X")) -(defn get-player-input []) (defn show-board [board] (println (str (nth board 0) " | " (nth board 1) " | " (nth board 2))) @@ -32,7 +20,6 @@ (println (str "Player " player " turn")) (show-board board) (let [player-input (read-string (read-line))] - (println player-input) (if (and (number? player-input) (<= 0 player-input 8)) (assoc board player-input player) (do @@ -44,17 +31,59 @@ (do (println "Game drawn!") true) false)) -(defn won-win-condition [board player win-condition] +(defn won-win-condition [player board win-condition] (every? #(= player (nth board %)) win-condition)) -(defn game-won [board player] - (if (some (partial won-win-condition board player) win-conditions) +(defn is-win [player board] + (some (partial won-win-condition player board) win-conditions)) + +(defn game-won [player board] + (if (is-win player board) (do (println (str "Player " player " wins!")) true) false)) +(defn ai-turn-easy [player board] + (let [empty-spaces (filter #(not (or (= % "X") (= % "O"))) board) + random-space (nth empty-spaces (rand-int (count empty-spaces)))] + (assoc board (Integer. random-space) player))) + +(defn try-win-move [player board] + (let [empty-spaces (filter #(not (or (= % "X") (= % "O"))) board)] + (some (fn [space] + (let [new-board (assoc board (Integer. space) player)] + (if (is-win player new-board) + (Integer. space) + false))) + empty-spaces))) + +(defn ai-turn-medium [player board] + (let [ win-move-spot (try-win-move player board)] + (if (nil? win-move-spot) + (ai-turn-easy player board) + (assoc board win-move-spot player)))) + +(defn ai-turn-hard [player board] + (let [win-move-spot (try-win-move player board)] + (if (nil? win-move-spot) + (let [block-move-spot (try-win-move (swap-player player) board)] + (if (nil? block-move-spot) + (ai-turn-easy player board) + (assoc board block-move-spot player))) + (assoc board win-move-spot player)))) + +(defn ai-turn-best [player board] + board) + (defn ai-turn [player board strength] (println (str "AI turn as player " player " with strength " strength)) - board) + (show-board board) + (let [board-after-ai-move (case strength + 1 (ai-turn-easy player board) + 2 (ai-turn-medium player board) + 3 (ai-turn-hard player board) + (ai-turn-best player board))] + (Thread/sleep 1000) + board-after-ai-move)) (defn ai-turn? [player X-strength O-strength] (if (= player "X") @@ -67,14 +96,14 @@ O-strength)) (defn play [board X-strength O-strength] - (loop [game-board board player "X"] - (if (or (game-won game-board (swap-player player)) (board-full game-board)) + (loop [player "X" game-board board] + (if (or (game-won (swap-player player) game-board) (board-full game-board)) (show-board game-board) (let [new-board (if (ai-turn? player X-strength O-strength) (ai-turn player game-board (strength-for-player player X-strength O-strength)) (player-turn player game-board))] - (recur new-board (swap-player player)))))) + (recur (swap-player player) new-board))))) (defn parse-args "Parses command line arguments and returns a map with X-strength and O-strength."