السابقالفهرسالتالي

الفصل 10

GridWorld: الجزء الثاني

 

الجزء الثاني من حقيبة GridWorld الدراسية تستخدم مقومات لم نرها حتى الآن، لذا سنلقي نظرة سريعة الآن وستحصل على المزيد من التفاصيل لاحقاً. للتذكير فقط، يمكنك الحصول على وثائق أصناف GridWorld من http://thinklikecs.webs.com/resources/javadoc/gridworld.

عندما تنصب GridWorld، يجب أن تحصل على مجلد باسم boxBug داخل المجلد projects، يحتوي على BoxBug.java، BoxBugRunner.java، وBoxBug.gif.

انسخ هذه الملفات إلى مجلد عملك واستوردهم إلى بيئة البرمجة لديك. توجد تعليمات هنا قد تساعدك: http://www.collegeboard.com/prod_downloads/student/testing/ap/compsci_a/ap07_gridworld_installation_guide.pdf.

(توجد نسخة مترجمة من هذه التعليمات على: http://thinklikecs.webs.com/resources/gridworld_installation_guide.pdf)

هذه هي الشفرة من BoxBugRunner.java:

import info.gridworld.actor.ActorWorld;
import info.gridworld.grid.Location;
import java.awt.Color;

public class BoxBugRunner {
   public static void main(String[] args) {
      ActorWorld world = new ActorWorld();
      BoxBug alice = new BoxBug(6);
      alice.setColor(Color.ORANGE);
      BoxBug bob = new BoxBug(3);
      world.add(new Location(7, 8), alice);
      world.add(new Location(5, 5), bob);
      world.show();
   }
}
يجب أن يكون كل شيء هنا مألوفاً، ما عدا Location ربما، وهو جزء من GridWorld، يشبه java.awt.Point.

يحتوي BoxBug.java على تعريف الصنف BoxBug.

public class BoxBug extends Bug {
   private int steps;
   private int sideLength;

   public BoxBug(int length) {
      steps = 0;
      sideLength = length;
   }
}
يقول السطر الأول أنه يوسّع (extends) Bug، ما يعني أن BoxBug هو من نوع Bug.

السطرين التاليين هما متغيري حالة. لكل حشرة (كائن Bug) متغيرين باسم sideLength، يحدد حجم الصندوق الذي ترسمه، وsteps، الذي يحتفظ بعدد الخطوات التي تحركتها الحشرة.

يعرف السطر التالي عملية بناء (أو باني constructor)، وهي عملية خاصة تهيئ متغيرات الحالة. عندما تصنع حشرة باستدعاء new، تستدعي Java هذا الباني.

يستخدم معامل الباني لتهيئة sideLength (المسافة الجانبية).

تتحكم العملية act بسلوك الحشرة. ها هي العملية act للصنف BoxBug:

public void act() {
   if (steps < sideLength && canMove()) {
      move();
      steps++;
   }
   else {
      turn();
      turn();
      steps = 0;
   }
}
إذا كانت BoxBug (حشرة الصندوق) قادرة على الحركة، ولم تصل بعد للعدد المطلوب من الخطوات، ستتحرك وتزيد steps.

إذا ارتطمت بجدار أو أنهت أحد جوانب الصندوق، ستستدير بزاوية 90 درجة على اليمين وتعيد ضبط steps إلى 0.

شغل البرنامج وشاهد ماذا يفعل. هل حصلت على السلوك المتوقع منه؟

تمرين 10.1

الآن أصبحت تعرف ما يكفي لحل التمارين الموجودة في دليل الطالب، الجزء 2. اذهب إليها، ثم عد إلى هنا لمزيد من المرح.

10.1 النمل الأبيض

كتبتُ صنفاً باسم Termite يوسع الصنف Bug ويضيف له القدرة على التفاعل مع الأزهار.

لتشغيله، نزل هذه الملفات واستوردها إلى بيئة البرمجة لديك:
http://thinklikecs.webs.com/resources/code/Termite.java
http://thinklikecs.webs.com/resources/code/TermiteRunner.java
http://thinklikecs.webs.com/resources/code/Termite.gif

بما أن Termite يوسع Bug، كل عمليات Bug ستعمل على Termite. لكن النمل الأبيض (Termites) يملك عمليات إضافية لا تملكها الحشرات (Bugs).

/**
 * Returns true if the termite has a flower.
 */
public boolean hasFlower();
/**
 * Returns true if the termite is facing a flower.
 */
public boolean seeFlower();

/**
 * Creates a flower unless the termite already has one.
 */
public void createFlower();

/**
 * Drops the flower in the termites current location.
 *
 * Note: only one Actor can occupy a grid cell, so the effect of
 * dropping a flower is delayed until the termite moves.
 */
public void dropFlower();

/**
 * Throws the flower into the location the termite is facing.
 *
 */
public void throwFlower();

/**
 * Picks up the flower the termite is facing, if there is one,
 * and if the termite doesn't already have a flower.
 */
public void pickUpFlower();
بالنسبة لبعض العمليات، يوفر الصنف Bug تعريفاً لها ويوفر Termite لها تعريفاً آخر. في تلك الحالة، يجب أن تهيمن (override) عملية Termite على عملية Bug.

مثلاً، تعيد العملية Bug.canMove القيمة true إذا وجدت زهرة في الموقع التالي، لذا يمكن للحشرات أن تدوس الأزهار. أما Termite.canMove فتعيد false إذا وجد أي كائن في الموقع التالي، لذا فإن سلوك النمل الأبيض مختلف.

كمثال آخر، يملك النمل الأبيض نسخة من turn تأخذ عدداً صحيحاً من الدرجات كمعامل. أخيراً، يملك النمل الأبيض randomTurn، التي تدوره 45 درجة على اليمين أو اليسار عشوائياً.

ها هي الشفرة من TermiteRunner.java:

public class TermiteRunner
{
   public static void main(String[] args)
   {
   ActorWorld world = new ActorWorld();
   makeFlowers(world, 20);
   Termite alice = new Termite();
   world.add(alice);
   Termite bob = new Termite();
   bob.setColor(Color.blue);
   world.add(bob);
   world.show();
   }
   public static void makeFlowers(ActorWorld world, int n) {
      for (int i=0; i<n; i++) {
         world.add(new EternalFlower());
      }
   }
}
يجب أن يبدو كل شيء هنا مألوفاً. يقوم TermiteRunner بإنشاء ActorWorld فيه عشرين زهرة خارجية (ExternalFlower) ونملتين بيضاوين (two Termites).

الزهرة الخارجية هي زهرة تتجاهل العملية act حتى لا تصبح الأزهار أغمق.

class EternalFlower extends Flower {
   public void act() {}
}
إذا شغلت TermiteRunner.java يجب أن ترى نملتين تتحركان عشوائياً بين الأزهار.

يوضح MyTermite.java العمليات التي تتفاعل مع الأزهار. ها هو تعريف الصنف:

public class MyTermite extends Termite {
   public void act() {
      if (getGrid() == null)
         return;
      if (seeFlower()) {
         pickUpFlower();
      }
      if (hasFlower()) {
         dropFlower();
      }
      if (canMove()) {
         move();
      }
      randomTurn();
   }
}
MyTermite يوسع Termite، ويتجاوز العملية act. إذا رأت MyTermite زهرة، ستلتقطها، وإذا كانت تملك زهرة، ستتركها.

تمرين 10.2

الغرض من هذا التمرين هو اسكتشاف سلوك النمل الأبيض الذي يتفاعل مع الأزهار.

عدل TermiteRunner.java لإنشاء MyTermites بدلاً من Termites. بعدها شغله ثانية. يجب أن تتحرك MyTermites عشوائياً، محركة الأزهار. يجب ألا يتغير عدد الأزهار (بما في ذلك الأزهار التي تمسكها MyTermites).

في كتاب Termites, Turtles and Traffic Jams يصف الكاتب Mitchell Resnick نمطاً بسيطاً من سلوك النمل الأبيض:

عدل MyTermite.java لتنفيذ هذا النمط. ما أثر هذا التعديل على سلوك MyTermites برأيك؟

جربه. يجب ألا يتغير عدد الأزهار أيضاً، لكن مع الوقت ستتكدس الأزهار في عدد قليل من الكوم، على الأغلب كومة واحدة فقط.

هذا السلوك هو صفة متطورة (emergent property)، التي تستطيع أن تقرأ عنها في http://en.wikipedia.org/wiki/Emergence. تتبع MyTermites قوعد بسيطة معتمدة على معلومات قصيرة المدى، لكن النتيجة هي منظمة كبيرة الحجم.

10.2 نمل لانغتون الأبيض

نملة لانغتون (Langton's Ant) تعكس نمطاً بسيطاً من سلوك النمل الذي يظهر سلوكاً معقداً بشكل مدهش. تعيش النملة في شبكة تشبه شبكة GridWorld حيث تكون الخلية إما بيضاء أو سوداء. تتحرك النملة وفق هذه القواعد:

بما أن هذه القواعد بسيطة، فقد تتوقع أن النملة ستفعل شيئاً بسيطاً مثل رسم مربع أو تكرار نقش معين. لكن إذا كانت على شبكة ذات خلايا بيضاء، ستقوم النملة بأكثر من 10,000 حركة فيما يبدو أنه نقشة عشوائية قبل أن تستقر في حلقة دورانية متكررة تتألف من 104 خطوات.

يمكنك قراءة المزيد عن نملة لانغتون على http://en.wikipedia.org/wiki/Langton_ant.

إن صنع نملة لانغتون في GridWorld ليس سهلاً لأننا لا نستطيع التحكم بلون الخلايا. يمكننا استخدام الأزهار كبديل، لوضع علامة على الخلايا، لكننا لا نستطيع وضع زهرة ونملة على نفس الخلية، لذا لا نقدر على تطبيق قواعد النملة تماماً.

بدلاً من ذلك سننشئ ما سأسميه LangtonTermite، التي تستعمل seeFlower للتحقق من وجود زهرة في الخلية التالية، وpickUpFlower لالتقاطها، وthrowFlower لوضع زهرة في الخلية التالية. قد ترغب بقراءة شفرة هذه العمليات حتى تتأكد أنك تفهم عملها.

تمرين 10.3

  1. اصنع نسخة من Termite.java سمها LangtonTermite.java ونسخة من TermiteRunner.java باسم LangtonRunner.java. عدلهم بحيث تكون أسماء الأصناف بنفس أسماء الملفات، وبحيث يقوم LangtonRunner بإنشاء LangtonTermite.
  2. إذا أنشأت ملفاً باسم LangtonTermite.gif، سيستخدمه GridWorld لتمثيل نملتك. يمكنك تنزيل صور حشرات ممتازة من http://www.cksinfo.com/animals/insects/realisticdrawings/index.html. يمكنك استخدام برنامج مثل ImageMagick لتحويلها إلى صيغة GIF.
  3. عدل act لإجراء قواعد تشبه قواعد نملة لانغتون. قم بتجارب مستخدماً قواعد مختلفة، وبانعطافات 45 و90 درجة. أوجد القواعد التي تستغرق أكبر عدد من الخطوات قبل أن تبدأ النملة بالدوران في حلقة.
  4. لتعطي نملتك مساحة كافية، يمكنك صنع شبكة أكبر أو التحويل إلى UnboundedGrid.
  5. أنشئ أكثر من نملة وانظر كيف ستتفاعل فيما بينها.
السابقالفهرسالتالي