我对OCaml相当新,我想实现一个类似于四线的游戏。 我需要的是一些保持游戏状态的数据结构。游戏板是一个4x4的正方形,共有16块瓷砖。 我正在寻找OCaml中的表示,这将使得在整个列,行或对角线中检索(或执行某些操作)所有元素变得容易和快速。 我会在这个游戏上进行极小极大搜索,这就是速度很重要的原因。
到目前为止,我已经考虑过一维列表。列表的问题在于很难确定哪些元素属于每个行/列/对角线,然后使用List.map
检索它们。
我考虑过使用Array.make 4 (Array.make 4 Empty);;
。这对于行来说绝对是完美的。很容易得到它们并在其上进行模式匹配。但是在单个列和对角线上进行模式匹配是一件苦差事。
我希望能够做的是有一个游戏板并返回包含所有行/列/对角线的列表列表的功能。我想做,例如,match (rows,columns,diagonals) with (Empty, Empty, Empty, Empty) -> something
。
答案 0 :(得分:2)
由于长度是固定的,因此首选数组优于列表:它们使用的内存更少,读写速度更快。
我担心你需要编写一个函数来获取对角线,没有简单的模式匹配。
当你写“在[对角线]上做一些操作”时,我假设你正在考虑一个函数f
,它采用一个长度为4的数组存储元素,例如[|Empty;Empty;Empty;Empty|]
。
也许f
可以将位置p
作为参数,并将位置内的索引数组作为参数:
f p [|x1,y1; x2,y2; x3,y3; x4,y4|]
会提取正方形p.(x1).(y1) ... p.(x4).(y4)
。然后,只需传递不同的x
和y
,即可使f
对行/列/对角线进行操作。
一旦代码正常运行并且您转向优化,您可能需要查看位向量: 如果你的minmax搜索树中存储了很多位置,减少内存占用意味着更多的缓存命中和更快的执行。你可能想要自己想在一个int中编码一个位置,但这是一些棘手的工作,你不想太早做。
答案 1 :(得分:1)
如何使用相应的坐标索引瓷砖?因此,您的一维列表中的元素将采用以下形式:
(int * int * ref tile)
然后你可以像这样过滤行/列/对角线:
行n: (前提条件:0< = n,u,v< = 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u = n);;
列n: (前提条件:0< = n,u,v< = 3)
List.filter tiles (fun x -> match x with (u, v, _) -> v = n);;
对角线1: (前提条件:0< = u,v< = 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u = v);;
对角线2: (前提条件:0< = u,v< = 3)
List.filter tiles (fun x -> match x with (u, v, _) -> u + v = 3);;
也应该可以用一个整数(一维列表中的瓦片的索引)来索引瓦片,但这需要在滤波器函数中进行一些计算(给定索引,找出坐标,然后决定它是否属于所需的行/列/对角线。
答案 2 :(得分:1)
有时匹配不起作用。在这里,我认为你应该尝试尽可能多地使用函数,然后将你的单元格排在第一列或第一列不会那么复杂,你甚至可以通过反转索引顺序从一个表示移动到另一个表示。 / p>
如果我使用以下类型:
type color = Red | Yellow;;
type cell = Empty | Color of color;;
type board = Array.make 4 (Array.make 4 Empty);;
并首先决定列,然后以下函数将获取行或列:
let column (b: board) i j = b.(i).(j)
let row (b: board) i j = b.(j).(i)
对于对角线,有两组,一组向左上方向右下方,另一组向另一方向(从右上方向左下方):
let ldiag (b: board) i j = b.((i + j) mod 4).(j)
let rdiag (b: board) i j = b.((i - j + 4) mod 4).(j)
然后我想检查行,列或对角线只是检查该行的4个单元格。
let check predicate linef k = predicate (linef b k 0) &&
predicate (linef b k 1) &&
predicate (linef b k 2) &&
predicate (linef b k 3)
然后,例如,检查是否有红色的对角线:
let has_line linef b color =
let cmp x = x = color in
let check k = check cmp linef b k in
check 0 || check 1 || check 2 || check 3
let has_ldiag b color = has_line ldiag b color
let has_rdiag b color = has_line rdiag b color
let has_red_diagonal b = has_ldiag b Red | has_rdiag b Red
等