(* ===================================================== *)
(*      Apprentissage de la programmation avec OCaml     *)
(*      Catherine Dubois & Valérie Ménissier-Morain      *)
(*                Éditions Hermès Sciences               *)
(*                        Mars 2004                      *)
(* ===================================================== *)
(* Fichier MLSRC/CC/CC_base_modulaire/circuits.ml        *)
(* ===================================================== *)

open Outils;;
open Representation;;

let case_vide (c,l) = zone_de_jeu.(c).(l)=Vide;;

let cases_jointes_segment_vertical (c1,l1) (c2,l2) =
  c1 = c2 &&
  let (minl, maxl) =
    if l1 < l2 then (l1, l2) else (l2, l1) in
       (* il n'y a pas de case intermédiaire *)
       maxl <= minl+1
    || (* toutes les cases intermédiaires sont vides *)
       (List.for_all case_vide
         (List.map (function l -> (c1, l))
           (interval (minl+1) (maxl-1))));;

let cases_jointes_segment_horizontal (c1,l1) (c2,l2) =
  l1 = l2 &&
  let (minc, maxc) =
    if c1 < c2 then (c1, c2) else (c2, c1) in
       (* il n'y a pas de case intermédiaire *)
       maxc <= minc+1
    || (* toutes les cases intermédiaires sont vides *)
         (List.for_all case_vide
         (List.map (function c -> (c, l1))
           (interval (minc+1) (maxc-1))));;
let cases_jointes_segment_hv (c1,l1) (c2,l2) =
   cases_jointes_segment_vertical (c1,l1) (c2,l2)
|| cases_jointes_segment_horizontal (c1,l1) (c2,l2);;

let rec cases_jointes_circuit_n_angles (c1,l1) (c2,l2) n =
  if n = 0 (* Cas de base de la récursivité *)
  then cases_jointes_segment_hv (c1,l1) (c2,l2)
  else
    List.exists
      (function l ->
           case_vide (c1,l)
        && cases_jointes_segment_vertical (c1,l1) (c1,l)
        && cases_jointes_circuit_n_angles (c1,l) (c2,l2) (n-1))
      (interval_sans l1 l2 0 (nb_lignes-1))
  || List.exists
      (function c ->
           case_vide (c,l1)
        && cases_jointes_segment_horizontal (c1,l1) (c,l1)
        && cases_jointes_circuit_n_angles (c,l1) (c2,l2) (n-1))
         (interval_sans c1 c2 0 (nb_colonnes-1));;

let rec cases_jointes_circuit_au_plus_n_angles (c1,l1) (c2,l2) n =
  if n = 0
  then cases_jointes_segment_hv (c1,l1) (c2,l2)
  else
      cases_jointes_circuit_au_plus_n_angles (c1,l1) (c2,l2) (n-1)
   || cases_jointes_circuit_n_angles (c1,l1) (c2,l2) n;;

let circuit_segment_vertical (c1,l1) (c2,l2) =
  if cases_jointes_segment_vertical (c1,l1) (c2,l2)
  then
    if
 c1 <> c2 || l1 <> l2
    then [(c1,l1);(c2,l2)]
    else [(c1,l1)]
  else raise Not_found;;

let circuit_segment_horizontal (c1,l1) (c2,l2) =
  if cases_jointes_segment_horizontal (c1,l1) (c2,l2)
  then
    if
 c1 <> c2 || l1 <> l2
    then [(c1,l1);(c2,l2)]
    else [(c1,l1)]
  else raise Not_found;;

let circuit_segment (c1,l1) (c2,l2) =
  if cases_jointes_segment_vertical (c1,l1) (c2,l2)
  || cases_jointes_segment_horizontal (c1,l1) (c2,l2)
  then
    if
 c1 <> c2 || l1 <> l2
    then [(c1,l1);(c2,l2)]
    else [(c1,l1)]
  else raise Not_found;;

let rec circuit_n_angles (c1,l1) (c2,l2) n =
  if n = 0 (* Cas de base de la récursivité *)
  then circuit_segment (c1,l1) (c2,l2)
  else
    try

      let ligne =
        List.find
        (function l ->
           case_vide (c1, l) &&
           cases_jointes_segment_vertical (c1,l1) (c1,l) &&
           cases_jointes_circuit_n_angles (c1,l) (c2,l2) (n-1))
      (interval_sans l1 l2 0 (nb_lignes-1)) in
      (c1, l1)::(circuit_n_angles (c1,ligne) (c2,l2) (n-1))
    with Not_found ->
      let colonne =
        List.find
         (function c ->
             case_vide (c, l1) &&
             cases_jointes_segment_horizontal (c1,l1) (c,l1)
          && cases_jointes_circuit_n_angles (c,l1) (c2,l2) (n-1))
          (interval_sans c1 c2 0 (nb_colonnes-1)) in
     (c1, l1)::(circuit_n_angles (colonne,l1) (c2,l2) (n-1));;

let rec circuit_au_plus_n_angles (c1,l1) (c2,l2) n =
  if n = 0
  then circuit_segment (c1,l1) (c2,l2)
  else
    try
 circuit_au_plus_n_angles (c1,l1) (c2,l2) (n-1)
    with Not_found -> circuit_n_angles (c1,l1) (c2,l2) n;;

let circuit_valide (c1,l1) (c2,l2) =
  match zone_de_jeu.(c1).(l1), zone_de_jeu.(c2).(l2) with
  | Vide, _ | _, Vide -> []
  | Occupée coul1, Occupée coul2 ->
      if coul1 = coul2
      then
        try

          circuit_au_plus_n_angles (c1,l1) (c2,l2) 2
        with Not_found -> []
      else [];;

Ce document a été traduit de LATEX par HEVEA.