I am trying to create a Sudoku game in F# and I'm having a bit of trouble with the file reading and writing. But since I've also just started programming in f# I would like to check if my thinking is truly functional or if it have any obvious flaws.
The Sudoku game is made up of 5 parts, Logic.fs with the game board:
let sudokuGame = Array2D.init 9 9 (fun i j -> createSquare i j)
and the Square
data structure:
type Square = { x : int; y : int; number : int; optionList : int list }
(x, y being the position x,y in the 2D array, number the accepted value of the Square and optionList
the candidates for being the number of the Square), and getter/creation functions for it.
Solver.fs which contains functions to get rows, columns and islands (as lists) that can be matched against the lists in the Squares with a member function. It also has a solver:
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
Other than that there is the file manipulation file and two GUI files (which will be continued when the logic of the game is complete).
In the file manipulation file I want to create functions to save a game board or retrieve a game board from a file. There I have a lot of problems figuring out how the code should look since Array2D
doesn't seem to be able to be cast as a sequence, also saving a Array2D
or list with .ToString()
doesn't give all the information I want. A solution that I Think might work that I've tried to use is .map or .mapi but I can't get it to work.
Something that might be good to know is that when all logic is complete I'll try to make the Sudoku into a playable game. The game board will therefor be passed in a (theoretically endless) recursive loop.
Can you find any obvious flaws? Any logic or choice of data structures that should be changed or that I should think about? Should I use array2d
or would lists, sequences or standard arrays better fit my needs? Are there any functions I've written so far that just doesn't make any sense and should be changed?
I would rather skip any mutables since I want to learn functional programming. So far I used array2d
for it's indexing and without using its mutable trait. I also used a global gameBoard
even though I would like to be able to load new games from files. To be truly functional, should I remove as many or all global values?