Deprecated: The each() function is deprecated. This message will be suppressed on further calls in /home/zhenxiangba/zhenxiangba.com/public_html/phproxy-improved-master/index.php on line 456
(*** Gui: 盤面の GUI ***)
open Tk
open MySupport
open Board
(* 定数 *)
let c_height = 1 (* マスの高さは1文字分*)
let c_width = 2 (* マスの幅は2文字分*)
(* 色の設定 *)
let defcol = `White (* 押されてない時の色 *)
let pushcol = `Blue (* 押されている時の色 *)
let selcol = `Color "#ffdfdf" (* マウスカーソルが来ている時の色 *)
(* マス目の状態から対応する色・レリーフへ変換 *)
let color_of_state = function
Pressed -> pushcol | NotPressed -> defcol
let relief_of_state = function
Pressed -> `Sunken | NotPressed -> `Ridge
let toggle = function Pressed -> NotPressed | NotPressed -> Pressed
(* 仕様を区切り文字 sep を使って文字列に変換 *)
let rec string_of_spec sep = function
[] -> ""
| [i] -> string_of_int i
| i :: rest -> (string_of_int i) ^ sep ^ string_of_spec sep rest
(** 各種ウィジェット操作 **)
(* マス目にマウスポインタが来た時の動作 *)
let focus label _ = Label.configure label ~background:selcol
(* マス目からマウスポインタが離れた時の動作 *)
let unfocus label st _ =
Label.configure label ~background:(color_of_state !st)
(* マス目の上でマウスボタンが押された時の動作 *)
let pressed label st _ =
st := toggle !st;
Label.configure label
~relief:(relief_of_state !st) ~background:(color_of_state !st)
(* マス目をクリア *)
let clear label st _ =
st := NotPressed;
Label.configure label
~relief:(relief_of_state !st)
~background:(color_of_state NotPressed)
(* 全マス目をクリア *)
let clear_all cells states =
List.iter2
(fun (_::c_row) st_row ->
List.iter2 (fun c_row st_row -> clear c_row st_row ())
c_row st_row)
cells states
(* アプリケーションの終了 *)
let quit () = closeTk(); exit 0
(* 盤面が正解かチェックして応答を label に表示 *)
let check h_spec v_spec body label () =
if is_solved h_spec v_spec body
then Label.configure label ~text:"正解!" ~foreground:`Red
else Label.configure label ~text:"残念..." ~foreground:`Blue
(** ウィジェット作成関数 **)
(* マス目のウィジェット1行を作成 *)
let rec make_cells ?(width=c_width) ?(height=c_height) parent =
function
[] -> []
| c::rest ->
let label =
Label.create parent ~width ~height ~relief:`Ridge
~background:(color_of_state !c) in
(* イベントの割りあて *)
bind ~events:[`Enter] ~action:(focus label) label;
bind ~events:[`Leave] ~action:(unfocus label c) label;
bind ~events:[`ButtonPress] ~action:(pressed label c) label;
label :: make_cells ~width ~height parent rest
(* 問題(縦方向)表示のためのラベルのリスト作成 *)
let make_vspec ?(spwidth=c_width) ~spheight speclist parent =
List.map
(fun s ->
Label.create parent ~width:spwidth ~height:spheight
~text:s ~anchor:`S ~relief:`Groove)
(List.map (string_of_spec "\n") speclist)
(* 横1行分のウィジェット
問題(横方向)表示のためのラベルとマス目のリスト
の作成 *)
let make_row ~spwidth ?(height=c_height) ?(width=c_width)
spec parent cell_list =
let s = string_of_spec " " spec in
Label.create parent
~width:spwidth ~height ~text:s ~anchor:`E ~relief:`Groove
:: (make_cells ~height ~width parent cell_list)
(* 盤面を作る関数 *)
let make_board {width=width;
height=height;
h_spec=h_spec;
v_spec=v_spec;
body=body} b_clear b_check parent =
(* 問題表示のための幅と高さの計算 *)
let spwidth = max (max_list (List.map List.length h_spec) * 2) 10 in
let spheight = max (max_list (List.map List.length v_spec)) 4 in
(* 盤面フレームの作成 *)
let f1 = Frame.create parent in
(* 盤面チェックの時の結果を表示する左上隅のラベルを作る*)
let corner = Label.create ~width:spwidth ~height:spheight f1 in
let reset_corner _ =
Label.configure corner
~relief:`Raised ~text:"お絵かき\nロジック" ~foreground:`Black in
reset_corner ();
bind ~events:[`ButtonPress] ~action:reset_corner corner;
Button.configure b_check ~command:(check h_spec v_spec body corner);
(* 0行目は corner と縦方向の数字表示のラベルの集まり *)
let row0 = corner::make_vspec v_spec ~spheight f1 in
pack row0 ~side:`Left ~anchor:`S;
(* 各行を格納するためのフレーム *)
let frame_rows = make_list height (fun () -> Frame.create parent) in
pack (f1 :: frame_rows) ~side:`Top;
(* 各行の中身を作り iter でまとめて pack *)
let rows = map3 (make_row ~spwidth) h_spec frame_rows body in
List.iter (pack ~side:`Left) rows;
Button.configure b_clear ~command:(fun () -> clear_all rows body)
(** メイン処理 **)
let () =
(* 引数の数のチェック *)
if Array.length Sys.argv = 1 then failwith "Usage: ilogic filename"
else
begin
let top = openTk() in
(* 盤面のためとボタンを並べるためのフレーム *)
let fr_board = Frame.create top in
let fr_buttons = Frame.create top in
pack [fr_board; fr_buttons] ~side:`Left ~fill:`Y;
(* ボタンの作成 *)
let b_check = Button.create ~text:"解答チェック" fr_buttons in
let b_clear = Button.create ~text:"やり直し" fr_buttons in
let b_quit =
Button.create ~text:"終了" ~command:quit fr_buttons in
pack [b_check; b_clear; b_quit] ~side:`Top ~fill:`X;
(* 盤面情報の読み込みとウィジェットの作成 *)
let board = Input.input_board (Sys.argv.(1)) in
make_board board b_clear b_check fr_board;
Wm.title_set top "お絵かきロジック";
mainLoop()
end