MathGame_V2/maeth.ml

120 lines
3.7 KiB
OCaml

open Graphics ;;
Random.self_init () ;;
type operation =
Val of int |
Sum of operation * operation |
Diff of operation * operation |
Prod of operation * operation |
Exp of operation * int ;;
let rec calculate = function
| Val k -> k
| Exp (op, k) -> Math.pw (calculate op) k
| Sum (f, g) -> (calculate f) + (calculate g)
| Diff (f, g) -> (calculate f) - (calculate g)
| Prod (f, g) -> (calculate f) * (calculate g) ;;
let generate_random_calc ?plus_w:(pw=10) ?minus_w:(mw=8) ?prod_w:(uw=2) ?exp_w:(ew=0) (length : int) (inf : int) (sup : int) =
let sum = pw + mw + uw + ew in
let rec aux = function
| 0 | 1 ->
Val (inf + Random.int (sup - inf))
| k ->
let r = Random.int sum in
if r < pw then begin
if Random.int 2 = 0 then
Sum(aux 0, aux (k-1))
else
Sum(aux (k-1), aux 0)
end
else if r < pw+mw then begin
if Random.int 2 = 0 then
Diff(aux 0, aux (k-1))
else
Diff(aux (k-1), aux 0)
end
else if r < pw+mw+uw then begin
if Random.int 2 = 0 then
Prod(aux 0, aux (k-1))
else
Prod(aux (k-1), aux 0)
end
else begin
Exp(aux (k-1), 2 + Random.int 2)
end
in
aux length ;;
let draw_bracket_open ?retval:(rv=Drawing.fodder) (x : int) (y : int) (size : int) =
moveto (x + size/4) (y+5*size/4) ;
lineto (x) (y+size/2) ;
lineto (x) (y-size/2) ;
lineto (x + size/4) (y-5*size/4) ;
rv := x + size/4 +6 ;;
let draw_bracket_close ?retval:(rv=Drawing.fodder) (x : int) (y : int) (size : int) =
moveto (x) (y+5*size/4) ;
lineto (x + size/4) (y+size/2) ;
lineto (x + size/4) (y-size/2) ;
lineto (x) (y-5*size/4) ;
rv := x + size/4 +6 ;;
let draw_sign ?retval:(rv=Drawing.fodder) (x : int) (y : int) (len : int) = function
| '+' ->
draw_poly_line [|(x, y); (x + len, y)|] ;
draw_poly_line [|(x+len/2, y + len/2); (x+len/2, y - len/2)|] ;
| '-' ->
draw_poly_line [|(x, y); (x + len, y)|] ;
| 'x' ->
Drawing.draw_letter x y 'x' len ;
| _ -> failwith "incorrect\n" ;;
let require_bracket = function
| Val _ -> false
| _ -> true ;;
let print_calc (f : operation) (x0 : int) (y0 : int) (size : int) =
set_line_width 3 ;
set_color black ;
let x = ref x0 in
let rec aux = function
| Val k ->
Drawing.draw_integer_alignedleft !x y0 k size ~retval:x ;
(*Printf.printf "%d --> \n" !x ;*)
| Exp (f, k) -> ()
| Sum (f, g) ->
if require_bracket f then draw_bracket_open !x y0 size ~retval:x ;
aux f ;
if require_bracket f then draw_bracket_close !x y0 size ~retval:x ;
draw_sign !x y0 size '+' ~retval:x ;
x := !x + size*10/7 ;
if require_bracket g then draw_bracket_open !x y0 size ~retval:x ;
aux g ;
if require_bracket g then draw_bracket_close !x y0 size ~retval:x ;
| Diff (f, g) ->
if require_bracket f then draw_bracket_open !x y0 size ~retval:x ;
aux f ;
if require_bracket f then draw_bracket_close !x y0 size ~retval:x ;
draw_sign !x y0 size '-' ~retval:x ;
x := !x + size*10/7 ;
if require_bracket g then draw_bracket_open !x y0 size ~retval:x ;
aux g ;
if require_bracket g then draw_bracket_close !x y0 size ~retval:x ;
| Prod (f, g) ->
if require_bracket f then draw_bracket_open !x y0 size ~retval:x ;
aux f ;
if require_bracket f then draw_bracket_close !x y0 size ~retval:x ;
draw_sign !x y0 (size/2) 'x' ~retval:x ;
x := !x + size*10/7 ;
if require_bracket g then draw_bracket_open !x y0 size ~retval:x ;
aux g ;
if require_bracket g then draw_bracket_close !x y0 size ~retval:x ;
in
aux f ;;