Programmeerimise algkursus Harjutus 5

Allikas: Lambda

Meie robotile on nüüd küll raskem pihta saada, aga sõitmine segab tugevalt laskmist. Tegelikult on täiesti võimalik teha mitut asja korraga ning see polegi teab mis keeruline.

Arenenud Robot

Mitut asja korraga saab teha vaid siis, kui tegemist on nn. "arenenud" robotiga (Advanced Robot). Meil ei jää muud üle, kui oma robot ahvist inimeseks arendada.

public class LollRobot extends AdvancedRobot {

   String siga_sihikul;       // Siga, mida me seekord sihime
   String uus_siga;           // Vahemuutujad uue lähima vastase leidmiseks
   double min_kaugus;
...

Muutub kaks asja:

  1. Tekib võimalus kasutada mitteblokeeruvaid käske kujul setTeeMidagi (näiteks setTurnRight).
  2. Robot hakkab vastu seinu sõites haiget saama

Tekitame igiliikuva radari

Et liikumine ei segaks laskmist, tuleb siduda radari keeramine ja liikumine üksteisest lahku. Selleks kolime radari keeramise koodi eraldi meetodisse ja asendame turnRadarLeft käsu setTurnRadarLeft käsuga.

   public void onRadarTurnComplete() {
       // Enne otsimist on lähim siga lõpmata kaugel
       min_kaugus = Double.POSITIVE_INFINITY;

       // Hakka taustal uuesti radarit keerama
       setTurnRadarLeft(360);

       // Kuningas on surnud, elagu kuningas
       siga_sihikul = uus_siga;
   }

Järgmiseks organiseerime, et meie kirjutatud uus meetod käivitataks iga kord, kui radari ring saab täis. Selleks tuleb registreerida uus sündmus (customEvent). Seda tuleb teha run meetodis, vahetult enne while tsüklit.

NB! Pane tähele, et run meetodist on juba kogu radari kood ära koristatud!

   public void run() {
       // Ära keera tukki koos kerega ega radarit koos tukiga!
       setAdjustGunForRobotTurn(true);
       setAdjustRadarForGunTurn(true);
   
       // Registreerime uue sündmuse, mis käivitub, kui radaritiir on tehtud
       addCustomEvent(new RadarTurnCompleteCondition(this));
   
       // Käivitame esimese radaritiiru
       onRadarTurnComplete();
   
       while(true) {
           // Dingel-dangel, kellapendel
           ahead(100 * suund);
           suund = -suund;
       }
   }

Lisaks peame tegema veel ühe uue meetodi:

   public void onCustomEvent(CustomEvent e) {
       String s = e.getCondition().getName();
   
       if("robocode.RadarTurnCompleteCondition".equals(s)) {
               onRadarTurnComplete();
           }
   }

Ja ongi kõik!

Robot on nüüd palju krapsakam, kas pole?

Saab veel krapsakamaks, kui asendada õiges kohas turnLeft käsk setTurnLeft käsuga ;)

Iseseisev töö

Arenenud robot saab vastu seinu sõites haiget. Seetõttu tuleb enne liikuma hakkamist kontrollida, kas mitte sein ette ei jää. Täienda run meetodis asuvat edasi-tagasi sõitmise koodi nii, et kontrollitakse, kas sein on lähemal kui 150 pikslit ja kui on, siis sätitakse suund selliselt, et robot sõidab seinast eemale, mitte seina poole. Abiks on järgmised meetodid:

  • getX() - minu X koordinaat
  • getY() - minu Y koordinaat
  • getBattleFieldWidth() - Mänguvälja laius
  • getBattleFieldHeight() - Mänguvälja kõrgus
  • getHeading() - Suund kraadides, kuhu poole on minu nina (mäletate, 0 kraadi oli otse üleval).

Lisalugemist

Igasugused kavalad liikumisalgoritmid kasutavadki enamasti arenenud robotit. Mõned lihtsamad leiad siit: