I am trying to create a game like Tetris with Clojure, and I am having problems choosing the data structure for the playing field. I want to define the playing field as a resizable grid. Individual blocks are also grids, but they do not need to be changed.
My first attempt was to define a grid as a vector of vectors. For example, an S-block is as follows:
:s-block { :grids [ [ [ 0 1 1 ] [ 1 1 0 ] ] [ [ 1 0 ] [ 1 1 ] [ 0 1 ] ] ] }
But this turns out to be quite complicated for simple things like iteration and drawing (see code below).
To make the grid volatile, my initial idea was to make each line a link. But then I could not understand how to change the value of a specific cell in a row. One option is to create each individual cell instead of each row. But this seems like an unclean approach.
I am now considering using Java arrays. Clojure The aget and aset functions are likely to be much simpler.
However, before delving into a deeper mess, I want to ask ideas / ideas. How would you recommend implementing a mutable 2d mesh? Feel free to share alternative approaches.
Current Status of the source code: Tetris.clj (rev452)
Update
With the help of your suggestions and after some mastering, I came up with the following:
(defstruct grid :width :height) (defn create-grid [wh initial-value] (struct-map grid :width w :height h :data (ref (vec (repeat (* wh) initial-value))))) (defn create-grid-with-data [wh gdata] (struct-map grid :width w :height h :data (ref gdata))) (defn get-grid [gxy] (let [gdata (g :data) idx (+ x (* (g :width) y)) ] (gdata idx))) (defn set-grid [gxy value] (let [data (deref (g :data)) idx (+ x (* (g :width) y)) ] (dosync (alter (g :data) (fn [_] (assoc data idx value)))))) (defn get-grid-rows [g] (partition (g :width) (deref (g :data))))
I like it because it is a more general solution. If this is completely wrong or can be improved, feel free to talk about it.
source share