Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/arrays/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
俄罗斯方块的向量还是Java数组?_Java_Arrays_Data Structures_Vector_Clojure - Fatal编程技术网

俄罗斯方块的向量还是Java数组?

俄罗斯方块的向量还是Java数组?,java,arrays,data-structures,vector,clojure,Java,Arrays,Data Structures,Vector,Clojure,我正试图用Clojure创建一个类似俄罗斯方块的游戏,但在决定游戏场的数据结构时遇到了一些问题。我想把运动场定义为一个可变网格。单个块也是网格,但不需要是可变的 我的第一次尝试是将网格定义为向量向量。例如,S形块如下所示: :s-block { :grids [ [ [ 0 1 1 ] [ 1 1 0 ] ] [ [ 1 0 ] [ 1 1 ] [ 0 1 ] ] ] } 但是对于像迭代和绘制这样的简单事情来说,

我正试图用Clojure创建一个类似俄罗斯方块的游戏,但在决定游戏场的数据结构时遇到了一些问题。我想把运动场定义为一个可变网格。单个块也是网格,但不需要是可变的

我的第一次尝试是将网格定义为向量向量。例如,S形块如下所示:

:s-block {
    :grids [
      [ [ 0 1 1 ]
        [ 1 1 0 ] ]

      [ [ 1 0 ]
        [ 1 1 ]
        [ 0 1 ] ] ]
}
但是对于像迭代和绘制这样的简单事情来说,这是相当棘手的(参见下面的代码)

为了使网格可变,我最初的想法是使每一行都成为一个引用。但是,我真的不知道如何更改行中特定单元格的值。一个选项是为每个单元格创建一个ref,而不是每行。但这感觉像是一种不干净的做法

我现在正在考虑使用Java数组。Clojure的aget和aset函数可能会变得更简单

然而,在把自己陷入更深的困境之前,我想问问自己的想法/见解。您建议如何实现可变二维网格?也可以随意分享其他方法

源代码当前状态:

更新
在你的建议的帮助下,经过我自己的一些修补,我得出了以下结论:

(defstruct grid :width :height)

(defn create-grid [w h initial-value]
  (struct-map grid
    :width  w
    :height h
    :data   (ref (vec (repeat (* w h) initial-value)))))

(defn create-grid-with-data [w h gdata]
  (struct-map grid
    :width w
    :height h
    :data (ref gdata)))

(defn get-grid [g x y]
  (let [gdata (g :data)
        idx   (+ x (* (g :width) y)) ]
    (gdata idx)))

(defn set-grid [g x y 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))))

我喜欢它,因为它是一个更通用的解决方案。如果它是完全错误的,或者可以改进,请随意说。

一个向量向量(如您最初的方法)如何存储在一个原子中(或者如果您需要对游戏场和其他东西进行协调的并发更新,可能是Ref…对于俄罗斯方块游戏来说不太可能),与
中的更新一起使用?(如果您使用的是Culjure(StP1.1)的近期快照,您可以考虑使用<代码> <代码>向量来构建您的向量。详见<代码>(DOC向量)< /C> >详细信息。

示例代码:

(def field (atom (vec (doall (for [_ (range 10)] (vec (repeat 10 false)))))))

(defn set-occupied! [x y]
  (swap! field #(update-in % [x y] (constantly true))))

(defn set-unoccupied! [x y]
  (swap! field #(update-in % [x y] (constantly false))))

(defn toggle-occupied! [x y]
  (swap! field #(update-in % [x y] not)))
事实上,上面的内容只是为了说明如何操作电路板。然而,这种方法的真正好处是,在核心逻辑中不需要那些破坏性(副作用)功能。相反,您可以将其编写为一组纯粹的函数,以获取游戏场的当前状态,可能还包括一些表示玩家输入(或缺少输入)的内容


最终,您只需要将其封装在一些Java互操作代码中,以将其插入GUI,但这将与您的核心逻辑完全解耦。总而言之,它应该在没有显著性能成本的情况下提供更愉快的总体体验(我的意思是,您的竞争环境可能有多大,更新将有多复杂…?)。

对每个单元格使用ref并不一定是个坏主意。将所有网格突变放入
dosync
中,Clojure应该注意每个多单元更新都是以原子方式完成的。(我不知道您是否计划同时在网格上运行多个线程,但这样做是安全的。)

下面我使用散列映射作为网格中每个单元格的值,因为您可能希望它不仅仅是一个布尔值被占用/未被占用;也许你想储存颜色信息或其他东西。但我保留了定义块的符号

(这个版本的
indexed
目前适用于最前沿的Clojure。在旧版本中,您可以在Clojure.contrib中找到
indexed
。)


Java数组看起来可能更简单,但它们不是线程安全的,而且大多数在seqs上运行的优秀Clojure函数都将以任何方式取消数组。改变一堆数组和对象绝对不是惯用的Clojure。Java数组通常用于与Java库的互操作。

我认为使用向量向量完全可以。因为你可能每秒只会做少量的更新,所以我不认为让整个游戏环境一成不变会有任何负面影响

当然,您需要构建一些帮助器函数来管理此数据结构,但以下是一些基本函数:

(defn make-row [w]
  (vec (for [x (range w)] 0)))

(defn make-grid [w h]
  (vec (for [y (range h)] (make-row w))))

(defn gget [grid x y]
  ((grid y) x))

(defn gset [grid x y v]
  (assoc grid y (assoc (grid y) x v)))

您可能可以使用这些或类似的工具来实现所需的所有其他功能。

我不完全理解,但它工作得很好:)(我看到set-Occessed用一个总是返回true的函数替换网格单元的内容,但我仍在努力弄清楚结构中的更新实际上是如何工作的。)总之,谢谢!很乐意帮忙。:-)实际上
设置已被占用
将给定网格单元的内容替换为将
(始终为true)
应用于其当前内容的结果(这就是
中的更新所做的;它有点类似于统一更新模型中的
交换!
更改
&friends)。您还可以使用
#(assoc in%[x y]true)
进行简单的替换(我想这会更有意义)<代码>切换已占用对我来说似乎是最有趣、最有用的函数,而且最好使用
updatein
编写。(哦,还有一个提取数据的
get in
函数。)另外,我可能会将整个棋盘状态包装在一个ref中。如果您需要协调访问游戏状态的任何事务/同步线程,例如显示渲染循环或分数计算等,这将非常有用。这不完全是对您问题的回答,但是,您可能想看看clojure中的俄罗斯方块是否在不借助可变网格的情况下实现。
(defn make-row [w]
  (vec (for [x (range w)] 0)))

(defn make-grid [w h]
  (vec (for [y (range h)] (make-row w))))

(defn gget [grid x y]
  ((grid y) x))

(defn gset [grid x y v]
  (assoc grid y (assoc (grid y) x v)))