\b;Exercice Télécommandez un robot, sans utiliser une \l;borne d'information\u object\exchange;, pour qu'il passe par les 6 croix bleues. Il faudra utiliser une variable \c;\l;static\u cbot\static;\n; pour communiquer directement d'un programme à un autre. Les 2 acteurs principaux de cet exercice sont: 1) Un \l;robot déménageur\u object\botgr; sans pile, donc immobile. C'est lui l'émetteur que vous devez programmer. 2) Un \l;robot d'entraînement\u object\bottr; qui attend les ordres. Ce robot est déjà programmé. \b;Le robot récepteur Pour commencer, il faut comprendre le programme du robot d'entraînement qui attend les ordres. Une \l;classe\u cbot\class; \c;order\n; contient deux variables: \c;global_type\n; détermine l'ordre à effectuer (avancer ou tourner) et \c;global_param\n; détermine la distance à avancer ou l'angle de rotation: \c;\s;\l;public\u cbot\public; \l;class\u cbot\class; order \s;{ \s; \l;int\u cbot\int; global_type = \l;nan\u cbot\nan;; \s; \l;float\u cbot\float; global_param; \s;} \n; Une deuxième \l;classe\u cbot\class; \c;exchange\n; contient le mécanisme d'échange et de mémorisation des ordres. Il faut d'abord déclarer une variable \c;\l;static\u cbot\static;\n; appelée ici \c;global_order\n;. Cette variable contient l'ordre à effectuer. L'instruction \c;static\n; permet à tous les robots d'accéder à la même variable unique. \c;\s;\l;public\u cbot\public; \l;class\u cbot\class; exchange \s;{ \s; \l;static\u cbot\static; \l;private\u cbot\private; order global_order = new order; \n; Une première méthode \c;put\n; sera utilisée par le robot émetteur pour donner un ordre. Si l'ordre est différent de \c;\l;nan\u cbot\nan;\n;, cela signifie qu'il n'a pas encore été effectué par le robot récepteur. Dans ce cas, la méthode \c;get\n; ne fait rien et retourne \c;false\n;: \c;\s; \l;synchronized\u cbot\synchro; \l;bool\u cbot\bool; put(order a) \s; { \s; if ( global_order.global_type == nan ) \s; { \s; global_order = a; \s; return true; \s; } \s; else \s; { \s; return false; \s; } \s; } \n; Une deuxième méthode \c;get\n; sera utilisée par le robot récepteur pour prendre connaissance d'un ordre à effectuer: \c;\s; \l;synchronized\u cbot\synchro; order get() \s; { \s; return global_order; \s; } \n; Une troisième méthode \c;delete\n; sera utilisée par le robot récepteur pour indiquer que l'ordre est terminé: \c;\s; \l;synchronized\u cbot\synchro; void delete() \s; { \s; global_order.global_type = nan; \s; } \s;} \n; Le programme principal peut maintenant exister. La variable \c;list\n; est de type \c;exchange\n;, qui est une \l;classe\u cbot\class;. Il faut utiliser l'instruction \c;\l;new\u cbot\new;\n; pour créer immédiatement une instance. \c;\s;\l;extern\u cbot\extern; void object::Slave3( ) \s;{ \s; exchange list = new exchange(); \s; order todo; \n; La première boucle \c;while\n; exécute les ordres à l'infini. La deuxième boucle \c;while\n; attend un ordre en exécutant la méthode \c;get\n; de la classe \c;exchange\n;. Dès qu'un ordre contenant une valeur différente de \c;nan\n; est reçu, la boucle est stoppée. \c;\s; \l;while\u cbot\while; ( true ) \s; { \s; \l;while\u cbot\while; ( true ) \s; { \s; todo = list.get(); \s; if ( todo.global_type != nan ) break; \s; wait(1); \s; } \n; Il ne reste plus qu'à exécuter l'ordre reçu: \c;\s; if ( todo.global_type == 1 ) \s; { \s; move(todo.global_param); \s; } \s; else if ( todo.global_type == 2 ) \s; { \s; turn(todo.global_param); \s; } \s; else \s; { \s; message("Unknown order"); \s; } \n; Dès que l'exécution de l'ordre est terminée, il faut appeler la méthode \c;delete\n; pour indiquer au robot émetteur qu'il peut envoyer l'ordre suivant: \c;\s; list.delete(); \s; } \s;} \n; \b;Le robot émetteur Dans le robot émetteur, il est plus simple d'écrire une procédure \c;SendOrder\n; qui se charge d'envoyer un ordre au robot récepteur: \c;\s;void object::SendOrder(float order, float param) \s;{ \s; exchange list = new exchange(); \s; order todo(); \s; \s; todo.global_type = order; \s; todo.global_param = param; \s; \s; while ( list.put(todo) == false ) \s; { \s; wait(1); \s; } \s;} \n; La boucle \c;while\n; attend qu'un éventuel ordre précédent soit terminé, ce qui arrive lorsque le robot récepteur exécute la méthode \c;delete\n;. Le programme principal est finalement d'une simplicité enfantine: \c;\s;extern void object::Remote4( ) \s;{ \s; SendOrder(1, 20); // move(20); \s; SendOrder(2, 90); // turn(90); \s; SendOrder(1, 20); // move(20); \s; SendOrder(2, 90); // turn(90); \s; SendOrder(1, 10); // move(10); \s; SendOrder(2, 90); // turn(90); \s; SendOrder(1, 10); // move(10); \s; SendOrder(2,-90); // turn(-90); \s; SendOrder(1, 10); // move(10); \s;} \n; \key;\key help;\norm; permet de revoir ces instructions en tout temps! \t;Voir aussi \l;Exercice précédent\u tremote3; et \l;programmation\u cbot;.