class virtual ['a] matrix_game m pf =
object
val matrix : 'a array array = m
val rows = Array.length m
val cols = Array.length m.(0)
val print_function : 'a -> unit = pf
method print =
for i = (-1) to cols do
print_char '-'
done;
print_char '\n';
Array.iter
(fun x ->
print_char '|';
Array.iter (fun y -> print_function y) x;
print_endline "|")
matrix;
for i = (-1) to cols do
print_char '-'
done;
print_char '\n'
method private is_out_of_bounds (y, x) =
y >= rows || y < 0 || x >= cols || x < 0
method virtual private is_legal : int * int -> 'a -> bool
method virtual insert : int * int -> 'a -> unit
end
class sudoku =
object(self)
inherit ['a] matrix_game (Array.make_matrix 9 9 0) (fun x -> print_char ' ') as parent
val m = Array.make_matrix 9 9 0 (*override first def of matrix*)
method private is_out_of_bounds (y, x) =
y >= 9 || y < 0 || x >= 9 || x < 0
method private check_value v = v > 0 && v < 10
method private check_existence (y, x) v =
let empty_value = 0 in
let row_length = Array.length m in
let col_length = if row_length > 0 then Array.length m.(0) else 0 in
if y >= 0 && y < row_length && x >= 0 && x < col_length then
m.(y).(x) <> empty_value
else
false
method private is_legal (y, x) v =
not (self#is_out_of_bounds (y, x)) &&
self#check_value v &&
not (self#check_existence (y, x) v)
method insert (y, x) v =
if self#is_legal (y, x) v then
m.(y).(x) <- v
else
print_endline "Illegal move!"
method print : unit =
parent#print
end
methods insert and print are not working.
let s1 = new sudoku ;;
s1#insert (3,3) 5 ;;
s1#print;;
it should insert 5 to (3,3) in the matrix and print it. I'm stuck on this part. Sorry if this is dumb but any help is appreciated.
If we add a very simple method get_m
as follows to sudoku
, we can see that the state is being updated.
method get_m = m
# let s1 = new sudoku in s1#insert (3, 3) 5; s1#get_m;;
- : int array array =
[|[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 5; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]|]
So why does that not reflect when you print?
Well, let's add a few more methods to test this. The updated code is:
class virtual ['a] matrix_game m pf =
object
val matrix : 'a array array = m
val rows = Array.length m
val cols = Array.length m.(0)
val print_function : 'a -> unit = pf
method print =
for i = (-1) to cols do
print_char '-'
done;
print_char '\n';
Array.iter
(fun x ->
print_char '|';
Array.iter (fun y -> print_function y) x;
print_endline "|")
matrix;
for i = (-1) to cols do
print_char '-'
done;
print_char '\n'
method private is_out_of_bounds (y, x) =
y >= rows || y < 0 || x >= cols || x < 0
method virtual private is_legal : int * int -> 'a -> bool
method virtual insert : int * int -> 'a -> unit
method get_matrix = matrix
end
class sudoku =
object(self)
inherit ['a] matrix_game (Array.make_matrix 9 9 0) (fun x -> print_char ' ') as parent
val m = Array.make_matrix 9 9 0 (*override first def of matrix*)
method private is_out_of_bounds (y, x) =
y >= 9 || y < 0 || x >= 9 || x < 0
method private check_value v = v > 0 && v < 10
method private check_existence (y, x) v =
let empty_value = 0 in
let row_length = Array.length m in
let col_length = if row_length > 0 then Array.length m.(0) else 0 in
if y >= 0 && y < row_length && x >= 0 && x < col_length then
m.(y).(x) <> empty_value
else
false
method private is_legal (y, x) v =
not (self#is_out_of_bounds (y, x)) &&
self#check_value v &&
not (self#check_existence (y, x) v)
method insert (y, x) v =
if self#is_legal (y, x) v then
m.(y).(x) <- v
else
print_endline "Illegal move!"
method print : unit =
parent#print
method get_m = m
method get_matrix = parent#get_matrix
end
Now if we test this:
# let s1 = new sudoku;;
val s1 : sudoku = <obj>
# s1#insert (3, 3) 5;;
- : unit = ()
# s1#get_m;;
- : int array array =
[|[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 5; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]|]
s1#get_matrix;;
- : int array array =
[|[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]; [|0; 0; 0; 0; 0; 0; 0; 0; 0|];
[|0; 0; 0; 0; 0; 0; 0; 0; 0|]|]
The matrix in the sudoku
class object is not the same as the matrix in the parent. Now, since parent#print
prints that matrix, the changes are not reflected in your output.
We can add a print'
method which directly prints m
:
method print' =
for i = (-1) to cols do
print_char '-'
done;
print_char '\n';
Array.iter
(fun x ->
print_char '|';
Array.iter (fun y -> print_function y) x;
print_endline "|")
self#get_m;
for i = (-1) to cols do
print_char '-'
done;
print_char '\n'
But the problem with this is that `print_function was specified to always print a space, regardless of what was passed in, so we need to fix that.
inherit ['a] matrix_game (Array.make_matrix 9 9 0) (fun x -> print_int x) as parent
Or just:
inherit ['a] matrix_game (Array.make_matrix 9 9 0) print_int as parent
Having made these changes:
# s1#print';;
-----------
|000000000|
|000000000|
|000000000|
|000500000|
|000000000|
|000000000|
|000000000|
|000000000|
|000000000|
-----------
- : unit = ()
Now, the real root of the problem is that m
was unnecessary. We could instead replace your code with a simpler version.
class virtual ['a] matrix_game m pf =
object
val matrix : 'a array array = m
val rows = Array.length m
val cols = Array.length m.(0)
val print_function : 'a -> unit = pf
method print =
for i = (-1) to cols do
print_char '-'
done;
print_char '\n';
Array.iter
(fun x ->
print_char '|';
Array.iter (fun y -> print_function y) x;
print_endline "|")
matrix;
for i = (-1) to cols do
print_char '-'
done;
print_char '\n'
method private is_out_of_bounds (y, x) =
y >= rows || y < 0 || x >= cols || x < 0
method virtual private is_legal : int * int -> 'a -> bool
method virtual insert : int * int -> 'a -> unit
method get_matrix = matrix
end
class sudoku =
object(self)
inherit ['a] matrix_game (Array.make_matrix 9 9 0) (fun x -> print_int x) as parent
method private is_out_of_bounds (y, x) =
y >= 9 || y < 0 || x >= 9 || x < 0
method private check_value v = v > 0 && v < 10
method private check_existence (y, x) v =
let empty_value = 0 in
let row_length = Array.length matrix in
let col_length = if row_length > 0 then Array.length matrix.(0) else 0 in
if y >= 0 && y < row_length && x >= 0 && x < col_length then
matrix.(y).(x) <> empty_value
else
false
method private is_legal (y, x) v =
not (self#is_out_of_bounds (y, x)) &&
self#check_value v &&
not (self#check_existence (y, x) v)
method insert (y, x) v =
if self#is_legal (y, x) v then
matrix.(y).(x) <- v
else
print_endline "Illegal move!"
method print : unit =
parent#print
end
And testing it:
# let s1 = new sudoku in
s1#insert (3, 3) 5;
s1#print;;
-----------
|000000000|
|000000000|
|000000000|
|000500000|
|000000000|
|000000000|
|000000000|
|000000000|
|000000000|
-----------
- : unit = ()
Your printing method can be cleaned up considerably by leveraging the Format
module.
Consider printing an array of integers without spaces between them:
# let a = [|1; 2; 3; 4; 5; 6; 7; 8; 9|] in
let pp_nothing ppf () = Format.fprintf ppf "" in
let pp_int ppf i = Format.fprintf ppf "%d" i in
Format.asprintf "%a" (Format.pp_print_array ~pp_sep: pp_nothing pp_int) a;;
- : string = "123456789"
Now, if I want to print that with bars on either side:
# let a = [|1; 2; 3; 4; 5; 6; 7; 8; 9|] in
let pp_nothing ppf () = Format.fprintf ppf "" in
let pp_int ppf i = Format.fprintf ppf "%d" i in
Format.asprintf "|%a|" (Format.pp_print_array ~pp_sep: pp_nothing pp_int) a;;
- : string = "|123456789|"
Extending this:
method print =
let pp_nothing ppf () = Format.fprintf ppf "" in
let pp_newline ppf () = Format.fprintf ppf "\n" in
let pp_int ppf i = Format.fprintf ppf "%d" i in
let pp_char ppf ch = Format.fprintf ppf "%c" ch in
let pp_int_arr ppf arr =
Format.fprintf ppf "|%a|"
(Format.pp_print_array ~pp_sep: pp_nothing pp_int) arr
in
let pp_char_arr ppf arr =
Format.fprintf ppf "%a"
(Format.pp_print_array ~pp_sep: pp_nothing pp_char) arr
in
let pp_cap ppf len =
let a = Array.make len '-' in
Format.fprintf ppf "%a" pp_char_arr a
in
Format.printf "%a\n%a\n%a\n"
pp_cap 11
(Format.pp_print_array ~pp_sep: pp_newline pp_int_arr) matrix
pp_cap 11