(** {C Le jeu du {i same game}.} *) (** {1 Initialisation.} *) (** Initialise aléatoirement le tableau de jeu. *) let init_gb () = for ilig = 1 to Glob.nb_lig do for icol = 1 to Glob.nb_col do Glob.gb.(icol).(ilig) <- ((Random.int 3) + 1) done done (** {1 Fin de partie.} *) (** Vaut [true] si la partie est terminée: il ne reste plus aucune sélection possible. *) let end_game() = let icol = ref 1 and ilig = ref 1 in let rec loop() = if Glob.gb.(!icol).(!ilig) = 0 then (Glob.gb.(succ !icol).(!ilig) = 0) || (ilig := 1; incr icol; loop()) else ( (Glob.gb.(!icol).(!ilig) <> Glob.gb.(succ !icol).(!ilig)) && (Glob.gb.(!icol).(!ilig) <> Glob.gb.(!icol).(succ !ilig)) && (incr ilig; loop()) ) in loop() (** {1 Sélections.} *) (** Variable globale: donne l'indice de colonne minimal de la dernière sélection. *) let er_min = ref Glob.nb_col (** Marque la sélection déterminée par la pièce en [(icol, ilig)]. *) let mark_sel (icol, ilig) = let rec mark_sel_ext s icol ilig = Glob.gb.(icol).(ilig) <- (-s); er_min := min icol !er_min; if Glob.gb.(icol).(ilig-1) = s then mark_sel_ext s icol (ilig-1); if Glob.gb.(icol-1).(ilig) = s then mark_sel_ext s (icol-1) ilig; if Glob.gb.(icol).(ilig+1) = s then mark_sel_ext s icol (ilig+1); if Glob.gb.(icol+1).(ilig) = s then mark_sel_ext s (icol+1) ilig in er_min := icol; mark_sel_ext Glob.gb.(icol).(ilig) icol ilig (** Vaut [true] si la pièce en [(icol, ilig)] n'est pas isolée. *) let valid_sel icol ilig = let s = Glob.gb.(icol).(ilig) in (Glob.gb.(icol).(ilig-1) = s) || (Glob.gb.(icol-1).(ilig) = s) || (Glob.gb.(icol).(ilig+1) = s) || (Glob.gb.(icol+1).(ilig) = s) (** {1 Suppression et compactage.} *) (** Supprime les pièces marquées de la colonne [col] et compacte les pièces restantes. *) let collapse_down col = let rmin = ref 1 and rmax = ref 2 in let rec loop () = if col.(!rmin) <= 0 then ( col.(!rmin) <- col.(!rmax); col.(!rmax) <- 0 ); if col.(!rmin) > 0 then incr rmin; incr rmax; if col.(!rmax) <> 0 then loop() else if col.(!rmin) < 0 then col.(!rmin) <- 0 in loop() (** Supprime les pièces marquées du tableau et compacte les colonnes restantes. *) let collapse () = let rcol = ref !er_min in let rec loop () = Format.printf"collapse: er_min= %d, rcol=%d@." !er_min !rcol; let col = Glob.gb.(!rcol) in collapse_down col; if (col.(1) <> 0) then ( let tmp = Glob.gb.(!er_min) in Glob.gb.(!er_min) <- col; Glob.gb.(!rcol) <- tmp; incr er_min ); incr rcol; if Glob.gb.(!rcol).(1) <> 0 then loop() in loop () (** {1 Déroulement du jeu.} *) (** Variable globale: mémorise la dernière action effectuée (voir fonction {! Jeu.game_act}). *) let last_act = ref Glob.Null (** Effectue une action de jeu selon l'évènement souris enregistré ({!Gui.click}) et la dernière action effectuée ({!Jeu.last_act}). *) let game_act () = let act = Gui.click() in match act with Glob.Null -> last_act := act | Glob.Quit -> failwith "quit" | Glob.Next -> ( (match !last_act with Glob.Sel _ -> (collapse(); Gui.redraw_gb Glob.gb) | _ -> ()); last_act := act ) | Glob.Sel (icol, ilig) -> ( if (valid_sel icol ilig) then ( (match !last_act with Glob.Sel (icol', ilig') -> mark_sel (icol', ilig') | _ -> ()); mark_sel (icol, ilig); Gui.redraw_gb Glob.gb; last_act := act ) ) (** Boucle de jeu. *) let rec game_loop() = if end_game() then ( match Gui.click() with Glob.Next -> ( init_gb(); Gui.draw_gb Glob.gb; Gui.draw_next_bt(); game_loop() ) | Glob.Quit -> ( Format.printf"\n End of game@."; Graphics.close_graph() ) | _ -> game_loop() ) else ( game_act(); game_loop() ) (** Lancement du jeu. *) let main () = try ( Graphics.open_graph (Printf.sprintf" %dx%d" Gui.gw_width Gui.gw_height); Gui.draw_next_bt(); Gui.draw_quit_bt(); init_gb(); Gui.draw_gb Glob.gb; last_act := Glob.Null; game_loop() ) with Failure "quit" -> Graphics.close_graph() (**/**) ;; main()