How to resolve the algorithm 2048 step by step in the Clojure programming language
Published on 12 May 2024 09:40 PM
How to resolve the algorithm 2048 step by step in the Clojure programming language
Table of Contents
Problem Statement
Implement a 2D sliding block puzzle game where blocks with numbers are combined to add their values.
The name comes from the popular open-source implementation of this game mechanic, 2048.
Let's start with the solution:
Step by Step solution about How to resolve the algorithm 2048 step by step in the Clojure programming language
Source code in the clojure programming language
(ns 2048
(:require [clojure.string :as str]))
;Preferences
(def textures {:wall "----+"
:cell "%4s|"
:cell-edge "|"
:wall-edge "+"})
(def directions {:w :up
:s :down
:a :left
:d :right})
(def field-size {:y 4 :x 4})
;Output
(defn cells->str [line]
(str (:cell-edge textures)
(str/join (map (partial format (:cell textures)) line))
"\n"))
(defn walls->str [width]
(str (:wall-edge textures)
(str/join (repeat width (:wall textures)))
"\n"))
(defn field->str [field]
(let [height (count field)
width (count (first field))]
(str (str/join (interleave (repeat height (walls->str width))
(map cells->str field)))
(walls->str width))))
;Misc
(defn handle-input []
(let [input (read)
try-dir ((keyword input) directions)]
(if try-dir try-dir (recur))))
(defn get-columns [field]
(vec (for [x (range (count (first field)))]
(vec (for [y (range (count field))]
(get-in field [y x]))))))
(defn reverse-lines [field]
(mapv #(vec (reverse %)) field))
(defn padding [coll n sym]
(vec (concat coll (repeat n sym))))
(defn find-empties [field]
(remove
nil?
(for [y (range (count field))
x (range (count (nth field y)))]
(when (= (get-in field [y x]) \space) [y x]))))
(defn random-add [field]
(let [empties (vec (find-empties field))]
(assoc-in field
(rand-nth empties)
(rand-nth (conj (vec (repeat 9 2)) 4)))))
(defn win-check [field]
(= 2048
(transduce
(filter number?)
(completing max)
0
(flatten field))))
(defn lose-check [field]
(empty? (filter (partial = \space) (flatten field))))
(defn create-start-field [y x]
(->> (vec (repeat y (vec (repeat x \space))))
(random-add)
(random-add)))
;Algo
(defn lines-by-dir [back? direction field]
(case direction
:left field
:right (reverse-lines field)
:down (if back?
(get-columns (reverse-lines field))
(reverse-lines (get-columns field)))
:up (get-columns field)))
(defn shift-line [line]
(let [len (count line)
line (vec (filter number? line))
max-idx (dec (count line))]
(loop [new [] idx 0]
(if (> idx max-idx)
(padding new (- len (count new)) \space)
(if (= (nth line idx) (get line (inc idx)))
(recur (conj new (* 2 (nth line idx))) (+ 2 idx))
(recur (conj new (nth line idx)) (inc idx)))))))
(defn shift-field [direction field]
(->> (lines-by-dir false direction field)
(mapv shift-line)
(lines-by-dir true direction)))
(defn handle-turn [field]
(let [direction (handle-input)]
(->> (shift-field direction field)
(random-add))))
(defn play-2048 []
(loop [field (create-start-field (:y field-size) (:x field-size))]
(println (field->str field))
(cond (win-check field) (println "You win")
(lose-check field) (println "You lose")
:default (recur (handle-turn field)))))
(play-2048)
You may also check:How to resolve the algorithm Sieve of Eratosthenes step by step in the SNOBOL4 programming language
You may also check:How to resolve the algorithm Vigenère cipher step by step in the XPL0 programming language
You may also check:How to resolve the algorithm Loops/For step by step in the COBOL programming language
You may also check:How to resolve the algorithm Animate a pendulum step by step in the Portugol programming language
You may also check:How to resolve the algorithm Rename a file step by step in the Run BASIC programming language