Функция вставки матрицы в OCaml не работает

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) в матрицу и распечатать ее. Я застрял на этой части. Извините, если это глупо, но любая помощь приветствуется.

Сила классов Java: сравнение с языком C
Сила классов Java: сравнение с языком C
Абстракция" - это процесс упрощения сложных сущностей или концепций реального мира с целью их применения в форме программирования. В Java класс...
1
0
58
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Если мы добавим к 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 

Другие вопросы по теме