Programmeerimise algkursus Harjutus 6

Allikas: Lambda

Seinte vastu sõitmine on igatpidi paha. Esiteks kaotab robot energiat, teiseks võib ta sedasi nurka või seina äärde kinni jääda ja vastastele kergeks saagiks osutuda.

Uus sündmus

Algatuseks lisame "päris oma" sündmuse, mis hakkab käivituma siis, kui me seinale liiga lähedal oleme.

run meetodisse:

   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));

       // Registreerime sündmuse seina läheduse tunnetamiseks
       addCustomEvent(new Condition("CloseToWallCondition") {
           public boolean test() {
               double x = getX();
               double y = getY();
               double w = getBattleFieldWidth();
               double h = getBattleFieldHeight();
               double wm = 100;

               if (x <= wm || y <= wm || w - x < wm || h - y < wm) {
                   return true;
               } else {
                   return false;
               }
           }
       });
       

       // Käivitame esimese radaritiiru
       onRadarTurnComplete();
   
       while(true) {
           // Dingel-dangel, kellapendel
           ahead(100 * suund);
           suund = -suund;
       }
   }

onCustomEvent meetodisse:

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

       if("CloseToWallCondition".equals(s)) {
           onCloseToWall();
       }
   }

Hoidume matemaatikast ;)

Seinast eemale saamiseks on kõige parem viis sõita keskpunkti poole. Et teada kuhu poole jääb keskpunkt, on vaja funktsiooni, mis oskaks arvutada peilungit kahe punkti vahel. Ise jalgratast ei ole vaja leiutada, internet on täis koodinäiteid, mis on kirjutatud matemaatikat paremini jagavate kodanike poolt. Meie kasutame ühte, mida õppejõud on natuke kohendanud.

    /**
     * Returns the distance between two points
     */
    public double distance(double x1, double y1, double x2, double y2) {
        double x = x2-x1;
        double y = y2-y1;
        double range = Math.sqrt(x*x + y*y);

        return range;
    }

    /**
     *  computes the absolute bearing between two points
     */
    public double absoluteBearing(double x1, double y1, double x2, double y2) {
        double hyp = distance(x1, y1, x2, y2);
        double xo = x2-x1;
        double yo = y2-y1;
        double angle = Math.asin(xo / hyp);

        if(yo < 0) {
            angle = Math.PI - angle;
        }
        else if(xo < 0) {
            angle += Math.PI * 2;
        }

        angle = Math.toDegrees(angle);
        return angle;
    }

Lahkume seina lähedusest

Seina lähedusest lahkumine võiks käia umbes nii:

  1. Vaatame kuhu jääb mänguväljaku keskpunkt meie sõidusuuna suhtes
  2. Otsustame, kas keskpunkti poole sattumiseks tuleb liikuda edasi või tagasi
  3. Hakkame õiges suunas sõitma ja protsessi kiirendamiseks keerame vastavalt kas nina või saba keskpunkti poole
    public void onCloseToWall() {
        double x = getX();
        double y = getY();
        double w = getBattleFieldWidth();
        double h = getBattleFieldHeight();

        double suund_keskele = absoluteBearing(x, y, w / 2, h / 2);
        double keeramisnurk = normalRelativeAngle(suund_keskele - getHeading());
        double soita = Math.abs(getDistanceRemaining());

         if(Math.abs(keeramisnurk) > 90) {
             soita = -soita;
             keeramisnurk = keeramisnurk - 90;
         }

        setAhead(soita);
        setTurnRight(keeramisnurk);
    }