テストステ論

高テス協会会長が, テストステロンに関する情報をお届けします.

石をとる処理を実装した

囲碁では, 囲んだ石をとることが出来る. コードがファック(あとでリファックタリングをする)だが, とりあえず動いてるように見える. 正確には, ある盤面があった時, ある石を含むその一団をとることが出来る場合はそのポジションのリストを返し, とれない場合は空リストを返すという関数だ.

プリントデバッグ以外, デバッグの仕方が分からない. もう少しまともなデバッグ方法はないものか. 疲れてしまう.

let remove_list b (i, j, init) =
  let lis = ref [] in
  let found_hole = ref false in
  let s = ref IntSet.empty in
  let rec visit (i, j, a) =
    Printf.printf "visit (%d,%d,%d)\n" i j a;
    if a != init then () else
      if out_board b (i, j) then () else
        if !found_hole then () else
          if search_hole b (i, j) then
            found_hole := true
          else
            if IntSet.mem (pos2int (i, j)) !s then () else
            begin
              Printf.printf "For the first time in forever ~~~\n" ;
              lis := (i, j) :: !lis ;

              s := IntSet.add (pos2int (i, j)) !s ;
              IntSet.iter (fun n -> Printf.printf "%d " n) !s ;
              print_newline () ;

              visit (i+1, j, b.(i+1).(j)) ;
              visit (i-1, j, b.(i-1).(j)) ;
              visit (i, j+1, b.(i).(j+1)) ;
              visit (i, j-1, b.(i).(j-1)) ;
            end ;
  in
  visit (i, j, init) ;
  Printf.printf "found hole: %b\nlist: " !found_hole ;
  List.iter (fun (i, j) -> Printf.printf "(%d,%d)" i j) !lis ;
  print_newline () ;
  if !found_hole then [] else !lis

テスト用関数を書いてテストをしている.

let remove_test init_list start =
  let b = make 19 in begin
    do_put_stones b init_list ;
    remove_stones b @@ remove_list b start ;
    show b ;
  end
;;

例えば, 一番難しいであろう, 一線にある連石をとる処理も動いてるのでまぁまぁ大丈夫なのだろう. 穴があったら教えて欲しい.

   [1 2 3 4 5 6 7 8 9 10111213141516171819]
 1|
 2|
 3|
 4|
 5|
 6|
 7| O
 8|   O
 9|   O
10| O
11|
12|
13|
14|
15|
16|
17|
18|
19|

コードが短い. クリアだ. 状態も簡単に扱うことが出来る. 私の経験上, アルゴリズムなどは状態を複雑に持ち回すものがあるが, ふつうのプログラミングではかなりの部分を純粋関数で書ける. OCamlは良いバランスなのだろう. このように, その気になれば状態を持ち回すことも出来る. 良いことがどうかは全く分からないが, 書きやすいとは感じる. ハスケル病が少しずつ治りつつある.