我正试图在F#中创建一个Sudoku游戏,我在文件的读写方面遇到了一些麻烦。但是,由于我也刚刚开始用f#编程,我想检查一下我的想法是否真正实用,或者它是否有任何明显的缺陷。
数独游戏由五个部分组成,Logic.fs与游戏板:
let sudokuGame = Array2D.init 9 9 (fun i j -> createSquare i j)
以及Square
数据结构:
type Square = { x : int; y : int; number : int; optionList : int list }
(x,y是二维数组中的位置x,y,对平方的接受值进行编号,optionList
作为平方的候选值),以及它的getter/creation函数。
Solver.fs,它包含用于获取行、列和孤岛(作为列表)的函数,它们可以与平方中的列表与成员函数相匹配。它也有一个解决者:
let getRow S =
let rec getR pos =
match pos with
| 10 -> []
| x -> (sudokuGame.[(x-1), ((S.y) - 1)]).number :: getR (x+1)
in getR 1
let getCol S =
let rec getC pos =
match pos with
| 10 -> []
| y -> (sudokuGame.[(S.x - 1), (y - 1)]).number :: getC (y+1)
in getC 1
let getIsland S =
let getX =
match S.x with
| x when x < 4 -> 0
| x when x < 7 -> 3
| x -> 6
let getY =
match S.y with
| y when y < 4 -> 0
| y when y < 7 -> 3
| y -> 6
List.ofArray [| for x in 0 .. 2 do for y in 0 .. 2 -> sudokuGame.[getX+x,getY+y].number; |]
//placeInX is a function which leaves the items in x not found in y
let updateOptionList L S = { x= S.x; y=S.y; number = S.number; optionList = (placeInX (S.optionList) L )}
let getUpdatedSquare S =
if List.length (getSquareList S) <> 0
then
updateOptionList (getRow S) S |> updateOptionList (getCol S) |> updateOptionList (getIsland S) |> createCompleteSquare
else
S
let sodukoSolver (gameBoard : Square[,]) =
Array2D.map (getUpdatedSquare) (gameBoard)
let checkSudoku (gameBoard : Square[,]) (reference : Square[,]) =
gameBoard = reference
除此之外,还有文件操作文件和两个GUI文件(当游戏的逻辑完成后,这些文件将继续进行)。
在文件操作文件中,我希望创建函数来保存游戏板或从文件中检索游戏板。在这里,我有很多问题,找出代码应该是什么样子,因为Array2D
似乎不能被转换为序列,而且用.ToString()
保存Array2D
或list也不能提供我想要的所有信息。我认为我尝试过使用的解决方案是.map或.mapi,但我无法让它工作。
最好知道的是,当所有的逻辑都完成后,我将尝试将Sudoku变成一个可玩的游戏。因此,游戏板将在(理论上无止尽的)递归循环中传递。
你能发现明显的缺陷吗?任何逻辑或数据结构的选择,应该改变或我应该考虑?我应该使用array2d
还是列表、序列或标准数组更适合我的需要?到目前为止,我编写的函数中是否有一些功能没有任何意义,应该修改呢?
我宁愿跳过任何可变项,因为我想学习函数式编程。到目前为止,我使用array2d
作为它的索引,并且没有使用它的可变特性。我还使用了一个全局gameBoard
,尽管我希望能够从文件中加载新的游戏。要真正发挥作用,我应该删除同样多的或所有的全球价值观吗?
发布于 2015-07-07 07:19:48
Array2D在基本操作方面有点不足,特别是与Array、List、Set等相比。对于写入文件,我建议使用Array2D.iter并依次写入每条记录;您选择的格式取决于您。然后读取每条记录就像做一个Array2D.init一样简单,并从文件中取出每条记录。
我看不出这里有什么明显的缺陷。也许您希望使用内置集数据类型来存储可能的值。
您的代码具有足够的功能,但是如果您传递值而不是使用全局值,您将获得更大的灵活性。
https://codereview.stackexchange.com/questions/91912
复制相似问题