colobot-data/help/F/tremote4.txt

118 lines
4.9 KiB
Plaintext

\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;.