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
методы вставки и печати не работают.
let s1 = new sudoku ;;
s1#insert (3,3) 5 ;;
s1#print;;
он должен вставить 5 в (3,3) в матрицу и распечатать ее. Я застрял на этой части. Извините, если это глупо, но любая помощь приветствуется.
Если мы добавим к get_m
очень простой метод sudoku
, как показано ниже, мы увидим, что состояние обновляется.
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|]|]
Так почему же это не отражается при печати?
Что ж, давайте добавим еще несколько методов, чтобы проверить это. Обновленный код:
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
Теперь, если мы проверим это:
# 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|]|]
Матрица в объекте класса sudoku
не совпадает с матрицей в родительском объекте. Теперь, поскольку parent#print
печатает эту матрицу, изменения не отражаются на выводе.
Мы можем добавить метод print'
, который напрямую печатает 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'
Но проблема в том, что функция print_function была указана так, чтобы всегда печатать пробел, независимо от того, что было передано, поэтому нам нужно это исправить.
inherit ['a] matrix_game (Array.make_matrix 9 9 0) (fun x -> print_int x) as parent
Или просто:
inherit ['a] matrix_game (Array.make_matrix 9 9 0) print_int as parent
Внеся эти изменения:
# s1#print';;
-----------
|000000000|
|000000000|
|000000000|
|000500000|
|000000000|
|000000000|
|000000000|
|000000000|
|000000000|
-----------
- : unit = ()
Настоящий корень проблемы в том, что m
не было необходимости. Вместо этого мы могли бы заменить ваш код более простой версией.
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
И тестируем это:
# let s1 = new sudoku in
s1#insert (3, 3) 5;
s1#print;;
-----------
|000000000|
|000000000|
|000000000|
|000500000|
|000000000|
|000000000|
|000000000|
|000000000|
|000000000|
-----------
- : unit = ()
Ваш метод печати можно значительно улучшить, используя модуль Формат.
Рассмотрим печать массива целых чисел без пробелов между ними:
# 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"
Теперь, если я хочу напечатать это с полосами по обе стороны:
# 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|"
Расширение этого:
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