เข้าสู่ระบบ จำนวนคนออนไลน์ 2307 คน
siwarat
บล็อกของศิวรัตน์
About me:
 
หัวข้อล่าสุด
 
 
  • การเขียนโปรแกรมหุ่นยนต์ (0)
    [มากกว่า 6 เดือน]
  • ประเภทการสื่อสาร (0)
    [มากกว่า 6 เดือน]
  • การเริ่มต้นเขียนโปรแกรม (0)
    [มากกว่า 6 เดือน]
  • คณิตคิดเลขเร็ว (0)
    [มากกว่า 6 เดือน]
  • เหตุระทึกขวัญ (0)
    [มากกว่า 6 เดือน]
  • ด. เด็ก (0)
    [มากกว่า 6 เดือน]
  • อุปกรณ์คอมพิวเตอร์ (0)
    [มากกว่า 6 เดือน]
  •  
         
     
    ปฎิทิน
     
     

    <ตุลาคม 2557>
     
    40293012345
    416789101112
    4213141516171819
    4320212223242526
    44272829303112
    453456789
     
         
     
    สถิติบลอกนี้
     
     
    • คนเข้าบลอกนี้ทั้งหมด 5126
    • เฉพาะวันนี้ 4
    • ความคิดเห็น 0
    • จำนวนเรื่อง 7
    ให้คะแนนบลอกนี้
    แจ้งเนื้อหาบลอกไม่เหมาะสม
     
         
    การเขียนโปรแกรมหุ่นยนต์
    16 กันยายน 2554 - 12:04:00

     Robocode คืออะไร?

    Robocode เป็นโปรแกรม Opensource สำหรับการศึกษาเริ่มโดยนาย Mathew Nelson (ซึ่งจัดทำโดย IBM) ในขณะนี้มีผู้คนมากมายเข้ามาเป็นส่วนร่วม แต่คนที่รับผิดชอบโปรเจ๊คตอนนี้ก็คือ Flemming N. Larsen มีหน้าที่แก้บั๊กและพัฒนาเวอร์ชั่นถัดๆไป เกมส์ถูกออกแบบมาเพื่อช่วยเรียนรู้ภาษา Java และความรู้ทางด้านปัญญาประดิษฐ์ ซึ่งเริ่มได้ง่ายมาก หุ่นยนต์ง่ายๆสามารถเขียนได้ภายใน 2-3 นาที แต่ถ้าหุ่นยนต์ที่สมบูรณ์แบบก็จะกินเวลาหลายเดือนหรือมากกว่านั้น

    ลักษณะของเกมส์ พวกร่วมเข้าแข่งขันเขียนซอฟต์แวร์ควบคุมหุ่นยนต์ขนาดเล็กที่สู้กับหุ่นยนต์ตัวอื่นที่เหมือนกัน (แต่คนละโปรแกรม) หุ่นยนต์เคลื่อนที่ ยิง ค้นหาหุ่นยนต์ตัวอื่น และ ชนกำแพงหรือชนกับหุ่นยนต์ตัวอื่น(ถ้าพวกมันไม่ระวัง)  แนวคิดและกติกาของเกมส์นั้นเข้าใจง่าน แต่สิ่งที่ยากและสำคัญที่สุดคือกลยุทธ์ หุ่นยนต์บางตัวอาจจะประกอบไปด้วยโปรแกรมถึง 1000 บรรทัดหรือมากกว่านั้น เพื่อกลยุทธ์ที่เฉียบคม บางหุ่นยนต์ที่ประสบความสำเร็จ ก็เลือกใช้วิธีทางสถิติ หรือไม่ก็สร้างเครือข่ายประสาทจำลองเพื่อใช้ในการตัดสินใจ

    การแข่งขันในประเทศไทย การแข่งขันในประเทศไทย สามารถสมัครได้ตั้งแต่วันที่ 5 พฤศจิกายน พ.ศ. 2551 เป็นต้นไป สามารถติดตามข้อมูลข่าวสารได้จากที่นี้ http://www.vcharkarn.com/robocode 
    ดาวน์โหลด เวอร์ชั่นล่าสุดของ Robocode คือ 1.6.2 ซึ่งจะเป็นเวอร์ชั่นที่ใช้ในการแข่งขัน Robocode Thailand Contest 2009 สามารถดาวน์โหลดได้จากเว็บของโรโบโค้ตได้โดยตรงจากที่นี่http://sourceforge.net/project/showfiles.php?group_id=37202 
    สนับสนุนการแจกจ่าย การที่จะทดสอบหุ่นยนต์ของคนอื่นนั้นเพียงแค่ไปดาวน์โหลดไบต์โค๊ด(ข้อมูลที่ถูกคอมไพล์มาเรียบร้อนแล้ว)มาจากเว็บไซด์ และสามารถทดสอบหุ่นยนต์ที่ดาวน์โหลดมากับหุ่นยนต์ของเราได้ทันทีโดยที่ผู้แจกจ่ายสามารถสบายใจได้ว่าซอร์สโค๊ดที่เขียนมาจะไม่ถูกแอบดูหรือนำไปใช้ เนื่องจากผ่านการคอมไพล์มาเรียบร้อยแล้ว

    การเคลื่อนที่และการเล็ง สิ่งที่แข่งขันใน Robocode มีเพียง 2 สิ่ง
    1. หลบการชนให้ได้มากที่สุด (ชนกระสุน, ชนหุ่นยนต์, ชนกำแพง)
    2. พยายามคาดเดาตำแหน่งที่ศัตรูกำลังจะไป และยิงให้โดนมากที่สุด
    เทคนิคต่างๆจึงได้ถูกคิดค้นขึ้น และถูกนำมาใช้ในหุ่นยนต์ดังๆ เช่น 
    WaveSurfing - ปรับการเคลื่อนที่โดยที่จะพยายามหลบไม่ให้โดนโจมตีแบบเดิมเป็นครั้งที่สอง
    StatisticalTargeting - เก็บข้อมูลที่ตรงกับสถานการณ์ของเป้าหมายและตัดสินใจให้ถูกต้อง ใช้ข้อมูลที่เก็บมาทำการตัดสินใจในการยิงเป้าหมาย
    GuessFactorTargeting - นี่คือวิธีที่ดีที่สุดในบรรดาวิธี StatisticalTargeting เมื่อสถิติของศัตรูต่างๆอยู่ภายในตัวเลขหนึ่งตัว (GuessFactor)
    PatternMatching - พยายามจับรูปแบบของศัตรูด้วยรูปแบบเก่าๆที่เคยจับได้ และนำข้อมูลมาทำการตัดสินใจในการยิง

    หุ่นยนต์ตัวอย่าง หุ่นยนต์ตัวอย่างสำหรับนักพัฒนามือใหม่ ถูกรวมไว้เข้ากับแพ๊คเกจของ Robocode แล้ว สามารถพบได้หลังการทำ Installซึ่งได้แสดงการเขียนโปรแกรมหุ่นยนต์อย่างง่าย การเขียนโปรแกรมโดยใช้เหตุการณ์เป็นตัวกระตุ้น(Event-driven programming) และสอนการเขียนค่าต่างๆลงไฟล์เพื่อการเก็บสถิติ

    หุ่นยนต์เปิดเผยโค้ด สามารถเข้าไปดูรายชื่อได้ที่ Robowiki's opensource http://robowiki.net/?OpenSource 
    การแข่งขันในรุ่นต่างๆ การแข่งขันในรุ่นต่างๆแบ่งเป็นสี่รุ่น
    กำหนดโดยใช้ขนาดของโค้ดเพื่อจำกัดคุณสมบัติที่มากเกินไป
    (การวัดค่าดูที่ขนาดของไบต์โค้ด[คอมไพล์เรียบร้อยแล้ว])
    1. รุ่นเมก้า - ไม่มีข้อกำจัดของขนาดโค้ด (การแข่งขันของ Robocode Thailand Contest 2009 ก็ใช้รุ่นนี้) 
    2. รุ่นมินิ - โค้ดไม่เกิน 1500 bytes
    3. รุ่นไมโคร - โค้ดไม่เกิน 750 bytes
    4. รุ่นนาโน - โค้ดไม่เกิน 250 bytes 

    เอกสารต่างๆที่น่าสนใจ 
    Official Website 
    หน้าต่อไปเป็นการสอนการใช้และสร้างหุ่นยนต์ด้วย Robocode :D



    หน้าที่ 2 - การลงโปรแกรมและลองเล่น Robocode บน Windows

    การลงและลองเล่น Robocode บน Windows


    ติดตั้งโปรแกรม


    ในหน้าที่เราจะกล่าวถึงการติดตั้งโปรแกรม Robocode บนระบบปฏิบัติการ Windows ซึ่ง Robocode นั้นพัฒนามาจากโปรแกรมภาษา Java และจำเป็นต้องมี Java Runtime ที่มี version 1.5.0 หรือสูงกว่าเพื่อใช้ในการพัฒนาหุ่นยนต์ 
    เนื้อหาข้างล่างดังต่อไปนี้เป็นการทดสอบถึงความพร้อมของระบบก่อนที่จะการติดตั้ง Robocode ซึ่งสามารถทดสอบได้ดังต่อไปนี้


    การตรวจสอบว่าลง Java Runtime หรือยังและเวอร์ชั่นอะไร


     
    กดปุ่ม Start และเลือก Run
     
    พิมพ์ cmd หรือ command เพื่อเรียกใช้ Command prompt


  • พิมพ์ "java -version" เพื่อตรวจสอบ ถ้าหาก java version เป็น "1.5.xxxx" หรือ "1.6.xxxx" (xxxx หมายถึงตัวอักษรอะไรก็ได้สี่ตัว) ท่านสามารถลงโปรแกรม robocode ได้ทันที คลิ๊กที่นี่

  • หากปรากฏข้อความเป็นอย่างอื่น อาทิเช่น java version เป็น "1.4.xxxx" แสดงว่าเครื่องของท่านได้ทำการลง Java เรียบร้อยแล้วแต่ version เก่าเกินไปต้องทำการดาวน์โหลด JAVA Runtime มาใหม่ คลิ๊กที่นี่

  • หากท่านพบ 'java' is not recognized as an internal or external command... แสดงว่าเครื่องของท่านยังไม่ได้ลง Java เลย ต้องทำการดาวน์โหลด JAVA Runtime มาลง คลิ๊กที่นี่


  • การติดตั้ง Java Runtime


    การสร้างหุ่นยนต์รถถังเพื่อเข้าแข่งขัน จะเริ่มจากการติดตั้งซอฟแวร์ Java Runtime Version 1.5.0 หรือสูงกว่า โดยวิธีการต่อไปนี้จะทำการดาวน์โหลด Java SDK เวอร์ชั่นล่าสุด(ขณะที่เขียนคือ version 1.6.7) ซึ่งหาได้จากเว็บ http://www.java.com/en/download/index.jsp ดังรูป
     
     
    กด Install

     

    กด Accept

    โปรแกรมกำลังทำการติดตั้ง


    การติดตั้งโปรแกรมและเรียกใช้โปรแกรม Robocode


    โปรแกรม Robocode ซึ่งดาวน์โหลดได้จากเว็บไซท์ของ Robocode 
    (http://robocode.sourceforge.net) ซึ่งจะได้ไฟล์ชื่อ robocode-setup-x.y.z.jar โดย x.y.z 
    จะเป็นเลขเวอร์ชัน มาแล้ว ติดตั้งโดยดับเบิลคลิกไฟล์ที่ดาวน์โหลดมา โปรแกรมจะแสดงหน้าต่างดังรูป

     
    คลิ๊กที่ Download

    กดที่คำว่า Download เพื่อดาวน์โหลดตัวติดตั้ง robocode 1.6.1.2
     
    ทำการ Download
     
    หลังจากนั้น ก็ดับเบิ้ลคลิ๊กเพื่อลง robocode
     
    หลังติดตั้งเสร็จ จะสามารถเปิดโปรแกรม robocode โดยจะมี short cut ปรากฎอยู่ที่ Desktop
     
    โปรแกรม Robocode กำลังโหลด
     
    โปรแกรม Robocode พร้อมใช้งาน


     


    เอาหุ่นยนต์มาสู้กันเถอะ!


    เราจะเอาหุ่นยนต์ที่เราสร้างมาต่อสู้กับหุ่นยนต์ตัวอื่นกัน
     
    กด Battle > New
     
    เลือกหุ่นยนต์อะไรก็ได้ อาทิเช่น sample.Crazy แล้วกด Add ->
     
    เลือกหุ่นยนต์คู้ต่อสู้อีกตัว(ตัวไหนก็ได้) ในที่นี่เราเลือก Sample.Corners แล้วกด Add -> แล้วกด Start Battle
     
    การต่อสู้เริ่มขึ้นแล้ว 



    หน้าที่ 3 - การติดตั้ง Robocode สำหรับผู้ใช้ Linux

    หากท่านใช้ Windows ข้ามไปหน้าที่ สี่ ได้เลยครับ 
    การติดตั้งสำหรับชาว Linux ที่ต้องการจะเขียนหุ่นยนต์ด้วย Robocode เราจะใช้การลงผ่าน apt-get หรือ aptitude ก็ได้ครับ เพราะว่าสะดวกไม่ต้องกังวลเรื่อง Java runtime ซึ่งรายละเอียดมีดังนี้นะครับ
    แบบ Text mode
    1.เปิด terminal
    2.พิมพ์ sudo apt-get install robocode
    3.ใส่รหัสผ่านของ user ของท่าน
    4.รอจนทำการลงเสร็จ
    5.พิมพ์ robocode แล้วก็ enter
    แบบ Graphic mode (บน Ubuntu, LinuxTLE)

    1.คลิ๊กที่ System > Administration > Software Package Manager
    2.ใส่รหัสผ่านของ user ของท่าน
    3.พิมพ์คำว่า "robocode"
    Software Package manager
    4.ดับเบิ้ลคลิ๊กที่คำว่า "robocode"
    5.กด apply แล้วก็ apply อีกที
    6.รอลงจนเสร็จ 
    Dialog Finished!
    7.ไปที่ Application > Programming > Robocode
    robocode playing
    ส่วนวิธีการใช้นั้น สามารถไปดูได้ที่หน้า สาม ครับ เหมือน Windows เปี้ยบเลย
    ตอนต่อไปเราจะทำการเริ่มลงลึกเรื่องเขียนหุ่นยนต์กันเลยนะครับ :D



    หน้าที่ 4 - เริ่มเขียนหุ่นยนต์

    เริ่มต้นเขียน Robocode โดย Robot Editor

    1.เข้าโปรแกรม Robocode
    2.ไปที่เมนูบาร์ข้างบนคลิ๊กที่ Robot > Editor
    3.หน้าต่างของ Robot Editor โผล่ขึ้นมาคลิ๊กที่ File > New Robot
    4.จะมีหน้าต่างคำถามขึ้นมา ให้ตั้งชื่อหุ่นยนต์แล้วใส่เข้าไป และหลังจากนั้นใส่ชื่อทีมของคุณ(ที่ใช้ในหน้าสมัครแข่งขัน)ลงไป
    5.เย้!! คุณจะได้เห็น code ของคุณในการเขียนหุ่นยนต์แล้ว

    code หุ่นยนต์ใหม่เอียม


    package myteamname;
    import robocode.*;
      
    public class MyFirstRobot extends Robot {

         public void run() {
             while (true) {
                 ahead(100);
                 turnGunRight(360);
                 back(100);
                 turnGunRight(360);
             }
         }
      
         public void onScannedRobot(ScannedRobotEvent e) {
             fire(1);
         }

    }

    เฉพาะส่วนที่เขียวและหนา เท่านั้นที่เราต้องสนใจ นอกนั้นเราก็ไม่ต้องแก้อะไรเลย นิดเดียวเองใช่ไหม :D
    แต่ถึงอย่างไรก็ตาม หากคุณสนใจส่วนสีน้ำเงินมากๆ เดี๋ยวผมจะอธิบายให้ฟัง เอาไปเลย
     

     package myteamname;
     import robocode.*;
      
     public class MyFirstRobot extends Robot {
         public void run() {
         }
     }

    import robocode.*;
     
    //บอกจาวาว่าเรากำลังจะสร้างจะใช้ออปเจ็ค Robocode บนหุ่นยนต์ของคุณ
    public class MyFirstRobot extends Robot { 
    //บอกจาวาว่าสิ่งที่เรากำลังพูดถึงต่อไปนี้คือหุ่นยนต์นะจ๊ะ
    public void run() {} 
    //method นี้จะถูกรัน(หรือถูกประมวลผล) เมื่อการแข่งขันเริ่มขึ้น
    {} 
    //เครื่องหมาย {} จะรวมกลุ่มโค้ดต่างๆไว้ด้วยกัน
    เรามาขับเคลื่อนหุ่นยนต์กันเถอะ!
    เรามาวิเคราะห์ code โซนเขียวและหนา กันดีกว่า
    เริ่มต้นที่ method run() 
     while (true) {
         ahead(100);
         turnGunRight(360);
         back(100);
         turnGunRight(360);
     }


    while (x) { }
    //หมายถึงเมื่อใดข้อกำหนด x ยังคงเป็นจริง เราก็จะทำคำสั่งที่อยู่ระหว่างเครื่องหมาย { และเครื่องหมาย }
    //เมื่อ true มันเป็นจริงเสมอ (ก็มันชื่อ true นี่หว่า) ก็หมายความว่า ทำคำสั่งที่อยู่ระหว่างเครื่องหมาย { และเครื่องหมาย } ตลอดไป
    ดังนั้นหุ่นยนต์จะ
      1. เคลื่อนที่ไปข้างหน้า 100 จุด(pixels)
      2. หมุนปืนไปทางขวา(ตามเข็มนาฬิกา) ไป 360 องศา(ก็หมุนครบ 1 รอบพอดีเลยนี่เอง)
      3. เคลื่อนถอยหลังไป 100 จุด(pixels)
      4. หมุนปืนไปทางขวา(ตามเข็มนาฬิกา) ไปอีก 360 องศา(ก็คือหมุนอีก 1 รอบนั่นเอง)
    หุ่นยนต์จะทำไปเช่นนี้ไปเรื่อยๆ เรื่อยๆ เรื่อยๆ ... เรื่อยๆๆๆๆ จนกระทั่งมันตาย จากคำสั่ง while(true) นั่นแหละ
    ก็ไม่แย่นักใช่ไหม?
    ยิงมันเลย!(ตูม ตูม ตู้มมมม)
    เมื่อเรดาร์ของเราเจอหุ่นยนต์ เราอยากจะยิงใส่มัน

     public void onScannedRobot(ScannedRobotEvent e) {
         fire(1);
     }


    Robocode จะเรียก method onScannedRobot เมื่อมันเจอหุ่นยนต์ตัวอื่น มันจะส่งข้อมูลสารพัดเกี่ยวกับหุ่นยนต์ตัวนั้นผ่านมาทางตัวแปร event e อาทิเช่นหุ่นยนต์ชื่ออะไร พลังชีวิตเท่าไร่ อยู่ที่ไหน หันหัวไปทางไหน วิ่งเร็วเท่าไร่ เป็นต้น
    อย่างไรก็ตาม, นี่ยังเป็นหุ่นยนต์ตัวอย่างง่ายๆ, เราเลยยังไม่สนใจข้อมูลพวกนี้, ยิงอย่างเดียวก็พอ!

    เรียบเรียง(Compile) หุ่นยนต์ของคุณ ให้พร้อมใช้งาน

    แรกสุด!, คุณต้องทำการบันทึกหุ่นยนต์ของคุณก่อน โดยคลิ๊กที่ File > Save บันทึกเป็นชื่อไฟล์เดียวกับชื่อหุ่นยนต์ของคุณและมีนามสกุลเป็น .java
    หลังจากนั้นก็คลิ๊กที่ Compiler > Compile

    ถ้าข้อความไม่ปรากฏดังรูปอาทิเช่น Complie Failed. ก็หมายความว่าเราเขียน code ผิด จะต้องกลับไปแก้ ตามที่ Robocode บอกให้แก้ครับ(มันฉลาดเนอะ)
    ถ้าหุ่นยนต์ของคุณสามารถเรียบเรียงได้โดยไม่มีปัญหาอะไร คุณสามารถให้หุ่นยนต์เริ่มการแข่งขันได้โดยไปที่หน้าต่าง robocode (ไม่ใช่ Robot Editor นะจ๊ะ) แล้วกดเลือก Battle > New ถ้ายังไม่เห็นหุ่นยนต์ของคุณคุณสามารถ refresh หน้าต่างใหม่ได้โดยกด F5, หลังจากนั้นก็ใส่หุ่นยนต์ของคุณแข่งขันกับหุ่นยนต์ตัวอื่นอาทิเช่น sample.Target, แล้วก็กดปุ่ม Start Battle เพื่อให้เกมส์เริ่มต้น 


    แล้วทำอะไรต่ออีกล่ะ
    คุณควรที่จะดูโค้ดในหุ่นยนต์ตัวอย่างที่มาพร้อมกับ Robocode ว่าแต่ละตัวสามารถทำงานได้อย่างไรกัน
    คุณสามารถศึกษา code ที่มากขึ้นโดยการดูรายชื่อ event, method, variable ต่างๆ ผ่าน Robocode API เพือดูว่ามีสิ่งใดที่หุ่นยนต์ของคุณสามารถทำได้


    ในหน้าถัดไปจะกล่าวถึง ระบบฟิสิกส์ใน robocode :D



    หน้าที่ 5 - กายภาพและกฎฟิสิกส์ของหุ่นยนต์

    กายภาพของหุ่นยนต์
    The anatomy of a robot 
    ขนาดของหุ่นยนต์เท่ากับ 36x36 pixels
    1. Body(ตัวถัง) - จะรองรับปืนและเรดาร์อยู่ข้างบน ตัวถังถูกใช้สำหรับเคลื่อนที่ไปข้างหน้า,ถอยหลัง,เลี้ยวซ้าย,เลี้ยวขวา
    2. Gun(ปืน) - ถูกติดตั้งไว้บนตัวถัง เอาไว้ใช้ในการยิงกระสุนปืน ปืนสามารถหมุนซ้ายหรือขวาได้
    3. Radar(เรดาร์) - ถูกติดตั้งไว้บนปืน
    เอาไว้ใช้ในการค้นหาหุ่นยนต์ตัวอื่นที่ทำการเคลื่อนที่
    เรดาร์สามารถหมุนซ้าย หมุนขวา และเรดาร์จะสร้าง event "onScannedRobot"
    เมื่อตรวจพบหุ่นยนต์
    ตำแหน่งอ้างอิงในสนามรบ
    โรโบโค้ดใช้การกำหนดตำแหน่งแบบ Cartesian Coordinate System ซึ่งหมายถึงตำแหน่งที่ (0,0) จะอยู่ที่มุมล่างซ้ายของสนาม
    โรโบโค้ดใช้การกำหนดมุมตามเข็มนาฬิกา เมื่อองศาที่ 0 หรือ 360 ไปทางทิศเหนือ 90 องศาไปทางทิศตะวันออก 180 องศาไปทางทิศใต้และ 270 องศาไปทางทิศตะวันตก

    เวลาและความยาวระยะทางที่ใช้ในโรโบโค้ด
    โรโปโค้ดใช้หน่วยเวลาเป็น ติ๊ก(คือหน่วยของเวลาหนึ่ง). หุ่นยนต์จะมีโอกาสรัน 1 ลูป(หรือ 1 ตาเดิน) ในทุกๆ 1 ติ๊ก
    หน่วยของระยะทางนั้นง่ายๆ เป็นหน่วย pixels แต่มีข้อยกเว้น 2 ข้อดังนี้
    1. ทุกๆความยาวถูกแทนที่ด้วยตัวแปรลักษณะ double (เป็นตัวแปรประเภทหนึ่งในภาษา Java ซึ่งสามารถแทนค่าในตัวเลขได้ละเอียดถึงจุดทศนิยม 1074 ตำแหน่ง ค่ามากที่สุดที่เก็บได้ก็คือ (2-2-52)·21023 ) (อ้างอิงจาก http://java.sun.com/javase/6/docs/api/java/lang/Double.html) ซึ่งหมายความว่าคุณสามารถเคลื่อนหุ่นยนต์เป็นระยะทางกึ่งหนึ่งของ pixel ได้(ไม่จำเป็นต้องเป็นจำนวนเต็ม)
    2. โรโบโค้ดจะทำการลดขนาดสนามลงเพื่อให้ใส่บนจอภาพได้ ดังนั้นจึงเป็นไปได้ว่าภาพหุ่นยนต์ที่แสดงออกมาเดินทางได้ระยะทางน้อยกว่าความเป็นจริงนิดนึง (แตกต่างกันน้อยจนไม่มีความสำคัญ)
    ฟิสิกส์เคลื่อนที่ของหุ่นยนต์
    ความเร่ง (Aceeleration หรือชอบย่อกันในภาษาวิทยาศาสตร์ว่า a) : หุ่นยนต์จะมีอัตราเร่งเครื่องให้เดินเร็วขึ้น 1 pixel ต่อ 1 ตาเดิน ต่อ 1 ตาเดิน หรือ 1 pixel / 1 ตาเดิน2 (กลายเป็นสูตรความเร่งแล้วเห็นไหม) และจะมีอัตราเบรก 2 pixel / 1 ตาเดิน2. โรโบโค้ดจะเลือกความเร่งที่เหมาะสมตามระยะทางที่ต้องการจะไป
    สูตรความเร็ว (Velocity Equation , v) : v = at ความเร็วสูงสุดจะไม่เกิน 8 pixels/ 1 ตาเดิน. (ข้อบันทึกสำหรับนักพัฒนาความเร็วในโรโบโค้ดถูกเขียนเป็นลักษณะของเว็กเตอร์ ทิศทาวที่หุ่นยนต์หันไปที่ทิศทางหัวลูกศรของเว็กเตอร์นั้นๆ)
    สูตรระยะทาง (Distance Equation, d) : d = vt นั่นก็คือ ระยะทาง = ความเร็ว * เวลา.
    การหมุนของหุ่นยนต์ ปืน และเรดาร์
    ความเร็วหมุนสูงสุดของหุ่นยนต์ : (10 - 0.75 * abs(velocity)) องศา / ตาเดิน, ยิ่งเคลื่อนที่เร็วเท่าไร่ จะยิ่งหมุนช้าเท่านั้น { abs() เป็น function ทางคณิตศาสตร์ชื่อว่า absolute แปลงค่าตัวเลขติดเลข ให้เป็นบวก  และจะไม่เปลี่ยนแปลงตัวเลขที่เป็นบวกอยู่แล้ว}
    ความเร็วหมุนสูงสุดของปืน : 20 องศา / ตาเดิน, และถูกบวกด้วยกับความเร็วหมุนในขณะนั้นของหุ่นยนต์
    ความเร็วหมุนสูงสุดของเรดาร์ : 45 องศา/ ตาเดิน, และถูกบวกด้วยกับความเร็วหมุนในขณะนั้นของปืน
    กระสุนปืน
    สามารถเลือกยิงได้หลากหลายความแรงงงงง! ได้ตั้งแต่ 0.1 - 3 firepower ดังนี้
    พลังทำลาย : 4*ความแรงในการยิง, ถ้าความยิงแรงมากกว่า 1, มันมีพลังทำลายเพิ่มขึ้นอีก = 2 * (firepower -1)
    ความเร็ว : 20 - 3 * firepower
    เพิ่มความร้อนให้ปืน : 1 + firepower / 5. คุณจะไม่สามารถยิงได้อีกเมื่อปืนยังร้อนอยู่ (หรือความร้อนของปืน >0) ความเร็วในระบายความร้อนเท่ากับ 0.1 ต่อ 1 ตาเดิน
    ได้พลังชีวิตกลับมา(เมื่อยิงโดน) : 3 * firepower


    การชนกัน
    เมื่อชนกับหุ่นยนต์ตัวอื่น : หุ่นยนต์แต่ละตัวจะรับความเสียหาย 0.6 พลังชีวิต, ขณะที่หุ่นยนต์กำลังพยายามเคลื่อนที่หนีออกจากการชน แต่ก็ยังหนีไม่พ้น ก็จะยังเสียพลังชีวิตไปเรื่อยๆ จนกว่าจะพ้นจากการชนได้
    เมื่อชนกับกำแพง : (การชนกับกำแพงจะเกิดขึ้นก็ต่อเมื่อคุณเลือกใช้หุ่นยนต์ประเภท AdvancedRobots แล้วเท่านั้น) จะรับความเสียหาย = abs(velocity) * 0.5 - 1 (แต่จะไม่น้อยกว่า 0)
    อ้างอิงจาก http://testwiki.roborumble.org/w/index.php?title=Robocode/Game_Physics
    ในหน้าถัดไป จะกล่าวถึงคำสั่ง Robocode พื้นฐานที่ควรรู้ครับ



    หน้าที่ 6 - คำสั่งพื้นฐานของ Robocode

    นี่คือหน้าที่รวบรวมคำสั่งพื้นฐานของการเขียน Robocode ไว้ให้นะครับ


    คำสั่งพื้นฐาน
    การสั่งงานให้หุ่นยนต์เคลื่อนที่

    เคลื่อนที่ไปข้างหน้า : ใช้คำสั่ง ahead(double distance) เคลื่อนไปข้างหน้าตามจำนวน distance pixel(s) อาทิเช่น ahead(100) ไปข้างหน้า 100 pixels
    เคลื่อนที่ถอยหลัง : ใช้คำสั่ง back(double distance) เคลื่อนที่ถอยหลังหน้าตามจำนวน distance pixel(s) อาทิเช่น back(50) ไปข้างหลัง 50 pixels
    การสั่งงานให้หุ่นยนต์หมุน
    หมุนตัวหุ่นยนต์ไปทางซ้าย :
     ใช้คำสั่ง turnLeft(double degree) หมุนตัวหุ่นไปทางซ้ายตามจำนวน degree องศา อาทิเช่น turnLeft(30.14) หมุนไปทางซ้าย 30.14 องศา
    หมุนตัวหุ่นยนต์ไปทางขวา : ใช้คำสั่ง turnRight(double degree)
    หมุนตัวหุ่นไปทางขวาตามจำนวน degree องศา อาทิเช่น turnRight(90)
    หมุนไปทางขวา 90 องศา(หนึ่งมุมฉาก)
    การสั่งงานให้ปืนหมุน
    หมุนปืนไปทางซ้าย : ใช้คำสั่ง turnGunLeft(double degree)
    หมุนตัวปืนไปทางซ้ายตามจำนวน degree องศา อาทิเช่น turnGunLeft(10.5)
    หมุนปืนไปทางซ้าย 10.5 องศา
    หมุนปืนไปทางขวา : ใช้คำสั่ง turnGunRight(double degree)
    หมุนตัวปืนไปทางขวาตามจำนวน degree องศา อาทิเช่น turnGunRight(1)
    หมุนปืนไปทางขวา 1 องศา
    การสั่งงานให้เรดาร์หมุน
    หมุนเรดาร์ไปทางซ้าย : ใช้คำสั่ง turnRadarLeft(double degree)
    หมุนตัวเรดาร์ไปทางซ้ายตามจำนวน degree องศา อาทิเช่น turnRadarLeft(45)
    หมุนเรดาร์ไปทางซ้าย 45 องศา
    หมุนเรดาร์ไปทางขวา : ใช้คำสั่ง turnRadarRight(double degree)
    หมุนตัวเรดาร์ไปทางขวาตามจำนวน degree องศา อาทิเช่น turnRadarRight(180)
    หมุนเรดาร์ไปทางขวา 180 องศา(สองมุมฉาก)

    การยิง
    ยิงกระสุน :
     ใช้คำสั่ง fire(double firepower) ยิงกระสุนไปทิศทางที่ปืนชี้อยู่ตามจำนวนความแรงของ firepower มีค่าตั้งแต่ 0.1 - 3 ความรุนแรง ความเร็ว ของกระสุนสามารถกลับไปดูสูตรได้ที่หน้า 5
    อย่างเช่น fire(0.1) ยิงกระสุนปืนขนาดความแรง 0.1, fire(2.5) ยิงกระสุนปืนความแรงขนาด 2.5
    ในตอนถัดเราจะพูดถึงการเขียน Radar ครับ :D



    หน้าที่ 7 - เรดาร์

    เรดาร์เป็นสิ่งที่จำเป็นมากสำหรับหุ่นยนต์ เพราะถ้าเราไม่มีมัน เราจะไม่สามารถเล็งศัตรูได้อย่างแม่นยำและเราจะไม่ทราบว่าตัวเราอยู่ที่ไหน ทำให้เราเคลื่อนที่ได้มั่วซั่วมาก เหมือนกับการเคลื่อนที่และการยิง การควบคุมเรดาร์ก็จำเป็นต้องมีลำดับวิธี(algorithm) ตั้งแต่ง่ายๆจนไปถึงซับซ้อนมากๆ ในหุ่นยนต์ส่วนมากมักจะเขียนส่วนนี้เพียงเล็กน้อยเท่านั้น ถ้าเทียบกับการยิงและเคลื่อนที่
    ในหุ่นยนต์ที่มีการประมวลผลมากๆ จุดที่ดีที่สุดในการวางโค้ดคือคำสั่งแรกๆในแต่ละลูป ซึ่งเราจะสามารถป้องกันไม่ให้เรดาร์หมุนเลยไป ถ้าหุ่นยนต์ถูกข้ามตาเดินเพราะประมวลนานเกินเวลาที่กำหนดไว้

    ข้อมูลจำเพาะทางเทคนิค

    เรดาร์ใน Robocode จะสามารถหมุนได้เร็วที่สุด 45 องศาต่อ 1 ตาเดิน หรือ 1 tick เวลา. เรดาร์สามารถสแกนหุ่นยนต์ได้ไกลถึง 1200 pixels. มุมที่เกิดจากเรดาร์หมุนระหว่าง 2 ตาจะสร้างส่วนโค้งของเรดาร์, ถ้ามีหุ่นยนต์ตัวไหนปรากฏอยู่ภายใต้ส่วนโค้งของเรดาร์ จะถูกส่งต่อไปยัง method onScannedRobot() เรียงลำดับโดยระยะห่าง หุ่นยนต์ตัวไหนที่อยู่ใกล้ที่สุดจะถูกค้นพบก่อน ในขณะที่ตัวที่อยู่ไกลที่สุดจะถูกค้นพบเป้นตัวสุดท้าย โดยปกติแล้ว method onScannedRobot() มีความสำคัญในระดับที่ต่ำที่สุด จึงถูกเรียกเป็นสิ่งสุดท้ายในแต่ละตาเดิน
    เรดาร์สำหรับการแข่งขันแบบ 1-ต่อ-1
    เนื่องจากเป็นการแข่งแบบ 1-ต่อ-1 เราจึงมั่นใจได้ว่าศัตรูมีเพียงแค่ตัวเดียว ซึ่งสามารถทำให้เราสร้างการล็อกเป้าหมายได้อย่างสมบูรณ์ได้

    การควบคุมเรดาร์แบบง่ายที่สุด : แบบหมุนไปเรื่อยๆ(The Spinning Radar) (Spin_Radar.java)

    เป็นการควบคุมเรดาร์ที่ง่ายที่สุด, มันไม่ค่อยมีประสิทธิภาพเท่าไร่นัก แต่ก็ยังพอเห็นมีคนใช้อยู่นะ
    ลองมาดูชิ้นส่วนของโค้ดกันเลย

    public void run() {
        // ...
        turnRadarRightRadians(Double.POSITIVE_INFINITY);
    }

    การควบคุมเรดาร์แบบล็อกเป้าหมายแบบง่าย (The infinity lock) (Simple_Lock.java)
    เป็นการล็อคเป้าหมายแบบง่ายที่สุด แต่ข้อเสียของมันคือชอบไถลเลยไป และเป้าหายจะการเล็งบ่อยๆ
    มาดูชิ้นส่วนของโค้ดตรงนี้กันเลย
    public void run() {
        // ...
        turnRadarRightRadians(Double.POSITIVE_INFINITY);
    }
    public void onScannedRobot(ScannedRobotEvent e) {
        // ...
        setTurnRadarLeftRadians(getRadarTurnRemainingRadians());
    }

    การควบคุมเรดาร์ให้ล็อกเป้าหมายแบบสมบูรณ์ (The Perfect lock)
    ซึ่งก็มีหลายวิธีเหมือนกัน

    การล็อกเป้าแบบวงแคบ(โหลดตัวอย่างได้ที่นี่ Narrow_Radar.java)

    เล็งเรดาร์ไปยังจุดที่อยู่ล่าสุดจากที่เราเห็น จะส่งส่วนโค้งเรดาร์ที่มีขนาดแคบ เพื่อที่จะหาหุ่นยนต์ที่อยู่บริเวณใกล้เคียงจุดนั้น เนื่องจากส่วนมากหุ่นยนต์จะไม่สามารถเคลื่อนที่ออกจากส่วนโค้งเรดาร์ได้เร็วพอ แต่ก็อาจจะไม่เป็นจริงในบางกรณี การล็อกของเรดาร์บางครั้งก็ยังสามารถหลุดได้ นี่คือส่วนของโค้ดของการล็อกเป้าแบบวงแคบ
    import robocode.util.Utils;
    public void run() {
        // ...

        turnRadarRightRadians(Double.POSITIVE_INFINITY);
        do {
            // ค้นหาเป้าหมายใหม่
            scan();
        } while (true);
    }
    public void onScannedRobot(ScannedRobotEvent e) {
        //เซ็ตตัวแปร "องศาที่เรดาร์จะต้องหมุนเพิ่ม" ให้เท่ากับ
        double radarTurn =
            // องศาที่ตัวหุ่นยนต์ของเราหันอยู่เมื่อเทียบกับสนามรบ + องศาที่จุดค้นพบศัตรูเทียบกับองศาที่ตัวหุ่นยนต์เราหันอยู่
            getHeadingRadians() + e.getBearingRadians()
            // ลบด้วยองศาที่เรดาร์กำลังหันไปอยู่
            - getRadarHeadingRadians();


        //หมุนเรดาร์ไปทางขวาตามค่าของตัวแปร "องศาที่เรดาร์จะต้องหมุนเพิ่ม"
        setTurnRadarRightRadians(Utils.normalRelativeAngle(radarTurn));
        // ...
    }

    **เพิ่มเติม**
    ปัญหาหลุดเป้าของตัวนี้ สามารถแก้ได้โดยคูณให้มุมการหมุนของเรดาร์เพิ่มขึ้น โดยการเปลี่ยนโค้ดบรรทัดสุดท้ายให้เป็น setTurnRadarRightRadians(factor * Utils.normalRelativeAngle(radarTurn)); โดยที่ค่า factor นั้นควรมีค่าประมาณนี้
      1.0 - พฤติกรรมของเรดาร์ยังเหมือนเดิม
      1.99 - ให้การแคบตัวขององศาที่ใช้ล็อกเป้าหมาย ช้าลง ซึ่งเพื่มโอกาสให้เราติดตามเป้าหมายได้ และผลออกมาค่อนข้างติดตามได้เกือบตลอดเวลา
      2 - ทำให้เรดาร์หมุนเลยไปนิดนึง แต่ติดตามเป้าหมายได้ดีกว่าค่า 1.99
    การล็อกเป้าแบบวงกว้าง (Load ตัวอย่างได้ที่นี่ Wide_Radar.java)
    การล็อกเป้าแบบวงกว้างถูกใช้เพื่อการป้องกันที่เรดาร์หมุนหลุดเป้าหมายไปบ่อยๆ ซึ่งเป็นจุดอ่อนของการล็อกเป้าแบบวงแคบ เราดาร์จะสแกนเป็นวงที่กว้างขึ้นในสนามรบและจะไม่ลื่นไถล การล็อกเป้าแบบนี้เป็นการล็อกเป้าที่ใช้มากที่สุดในการแข่งขันแบบ 1-vs-1 นี่ตือตัวอย่างโค้ด
    import robocode.util.Utils;
    public void run() {
        // ...
        while(true) {
            turnRadarRightRadians(Double.POSITIVE_INFINITY);
        }
    }
    public void onScannedRobot(ScannedRobotEvent e) {
        // เหมือนกันกับล็อกเป้าแบบแคบ
        double absoluteBearing = getHeadingRadians() + e.getBearingRadians();
        // 
    Utils.normalRelativeAngle จะลบค่ามุมที่เกินกว่า 360 องศา ให้มีค่ามุมเดียวกันที่น้อยกว่า 360 องศา เช่นUtils.normalRelativeAngle(400) = 40 เป็นต้น จะได้ไม่เสียเวลาหมุนรอบตัวเองที่ไร้ค่าไปหนึ่งรอบ
        double radarTurn = Utils.normalRelativeAngle(absoluteBearing - getRadarHeadingRadians());
        // ความกว้างของหุ่นยนต์บวกด้วยสองเท่าของมุมเรดาร์ที่สามารถหมุนได้ใน 1 ตาเดิน ซึ่งมีค่าเท่ากับ36 pixels แต่ไม่เกินองศามากที่สุดที่หมุนได้ (45 องศา = PI/4.0 , 1 PI = 180 องศา = 3.14 เรเดียน)
        double arcToScan = Math.min(Math.atan(36.0 / e.getDistance()), Math.PI/4.0);
        // เราต้องการส่งให้เรดาร์สแกนหาไปทางที่หุ่นยนต์ศัตรูเพิ่งพุ่งหนีไป
        radarTurn += (radarTurn < 0) ? -arcToScan : arcToScan;
        setTurnRadarRightRadians(radarTurn);
        // ...
    }


    โค้ดเรดาร์ทั้งหมดที่กล่าวมานี้ จำเป็นต้องปรับค่าของหุ่นยนต์ใน method run() ดังนี้
    เนื่องจากเรดาร์ถูกติดตั้งบนปืน และ ปินถูกติดตั้งบนตัวรถถัง ปกติแล้วเวลารถถังหมุน ปืนและเรดาร์จะหมุนตามไปด้วย และ เวลาปืนหมุน เรดาร์ก็จะหมุนตามไปด้วยเช่นกัน วิธีการที่ทำให้มันเป็นอิสระต่อกัน ต้องใส่โค้ดดังนี้

    setAdjustRadarForRobotTurn(true); //เซ็ตให้เรดาร์ไม่หมุนตามตัวหุ่นยนต์ เมื่อตัวหุ่นยนต์หมุน (ให้ข้อต่อระหว่างเรดาร์กับหุ่นยนต์มันเป็นอิสระต่อกัน)
    setAdjustGunForRobotTurn(true); 
    //เซ็ตให้ปืนไม่หมุนตามตัวหุ่นยนต์ เมื่อตัวหุ่นยนต์หมุน (ให้ข้อต่อระหว่างปืนกับหุ่นยนต์มันเป็นอิสระต่อกัน)
    setAdjustRadarForGunTurn(true); //เซ็ตให้เรดาร์ไม่หมุนตามปืน เมื่อปืนหมุน (ให้ข้อต่อระหว่างปืนกับเรดาร์มันเป็นอิสระต่อกัน
    และจำเป็นต้องเปลี่ยนจาก public class robotname extends Robot เป็น public class robotname extends AdvancedRobot
    หน้าต่อไปเราจะพูดถึงระบบการเคลื่อนที่ของหุ่นยนต์กันนะครับ



    หน้าที่ 8 - การเคลื่อนที่ของหุ่นยนต์(พื้นฐาน)

    การเคลื่อนที่ของหุ่นยนต์เป็นหนึ่งในปัจจัยสำคัญในการชนะ โดยเฉพาะอย่างยิ่งการหลบลูกกระสุน ถ้าเราสามารถหลบลูกกระสุนได้มากเท่าไร่ เราก็ยิ่งมีโอกาสอยู่รอดได้นานเท่านั้น
    การเคลื่อนที่ใน Robocode สามารถแบบได้ 6 แบบหลักๆคือ
    1. อยู่นิ่งเฉยๆ เพราะถูกยิงโดนได้ง่าย จึงเป็นความคิดที่แย่มาก
    2. เคลื่อนที่เป็นเส้นตรง สามารถหลบการถูกยิงจากการเล็งแบบอยู่กับที่
    3. เคลื่อนที่เป็นวงกลม สามารถหลบการถูกยิงจากการเล็งแบบอยู่กับที่ และการเล็งแบบเส้นตรง
    4. เคลื่อนที่ซิกแซก ยากที่จะโดนยิงจากการเล็งแบบเส้นตรง และการเล็งตามแบบโค้ง แต่การเล็งแบบอยู่กับที่จะมีประสิทธิภาพ
    5. เคลื่อนที่โดยสุ่ม สามารถลดการโดนยิงได้จากการเล็งทุกแบบ แต่ค่อนข้างยากที่จะทำให้มันมีประสิทธิภาพ
    6. เคลื่อนที่ขั้นสูง จากการเคลื่อนที่แบบที่ 1-5 ไม่มีการเก็บข้อมูลเพื่อตัดสินใจในการเคลื่อนที่ การเคลื่อนที่แบบนี้จะเก็บข้อมูลต่างๆอาทิเช่น รูปแบบการยิงกระสุน แล้วนำมาประมวลผล เพื่อตัดสินใจเลือกเส้นทางการเคลื่อนที่ ที่ดีที่สุด หุ่นยนต์ที่มีประสิทธิภาพสูงมักจะใช้วิธีนี้
    หากผู้อ่านลง Robocode ไว้แล้วให้ลองเปิด Editor ดูแล้วเข้าไปเปิดไฟล์ที่ directory "sample/"
    จะ ได้เห็นตัวอย่างของโค้ดของหุ่นยนต์หลากหลายตัว ที่มีการเคลื่อนที่ในรูปแบบที่ต่างๆ กัน
    การเคลื่อนที่แบบ อยู่นิ่งเฉยๆ (- -")
    ลองเลือกเปิดหุ่นยนต์  sitting duck หรือ target
    ไปดูตรงบริเวณ method run() จะเห็นได้ว่าไม่มีคำสั่งสำหรับการเคลื่อนที่เลย

    การเคลื่อนที่แบบเป็นเส้นตรง

    ลองเลือกเปิดหุ่นยนต์ Walls (ไม่ใช่ Wall-E นะจ๊ะ) 
    เป็นหุ่นยนต์ที่เคลื่อนที่ตามขอบกำแพง
    เราจะเห็น code ใน method run() ดังต่อไปนี้


        public void run() {
            ...

            // ตัวแปร moveAmount ถูกกำหนดให้มีค่าเท่ากับความยาวมากสุดในสนามรบ 
            // getBattleFieldWidth() = จำนวน
    ความยาว pixels ในสนามรบ (ค่าในการแข่งขันคือ 800)
            // getBattleFieldHeight() = จำนวนความสูง pixels ในสนามรบ (ค่าในการแข่งขันคือ 600) 
            // Math.max(A,B) ถ้า A มากกว่า B จะคืนค่า A : ถ้า B มากกว่า A จะคืนค่า B
            moveAmount = Math.max(getBattleFieldWidth(), getBattleFieldHeight());
            // turnLeft() หมุนไปทางซ้าย 
            // getHeading() จะคืนค่าองศาของที่หุ่นยนต์หันอยู่ อาทิเช่นหุ่นยนต์หันหน้าไปทางทิศเหนือ getHeading() จะมีค่าเป็น 0 ถ้าหันไปทางทิศตะวันออกเฉียงเหนือ จะมีค่าเป็น 45
            // % หรือ modulation คือการหารเอาเศษ อาทิเช่น 100 % 3 = 1 เพราะ 100 หาร 3 ได้ 33 เศษ 1
            // การที่เราได้เศษจากการหาร 90 จะสามารถทำให้เรารู้จำนวนองศาที่เหลือที่สามารถทำให้หุ่นยนต์หันไปทวนเข็มนาฬิกาเพื่อให้หุ่นยนต์วางตัวเป็นมุมฉาก (0, 90, 180, 270)
            turnLeft(getHeading() % 90); //หันไปทางซ้าย 
    เพื่อเคลื่อนที่เข้าหากำแพง
            ahead(moveAmount); //เดินไปข้างหน้าให้เยอะที่สุดเท่าที่จะทำได้ เพื่อให้ถึงกำแพง
            // หันหน้าติดกับกำแพงแล้ว
            turnGunRight(90); //หมุนปืนไปทางขวา 90 องศา
            turnRight(90); //หมุนตัวเองไปทางขวา 90 องศา
           
            //พร้อมที่จะเคลื่อนที่รอบขอบสนามรบแล้ว!
            while (true) { //สั่งให้ทำไปเรื่อยๆจนกว่าจะตาย
                // เคลื่อนที่ตามขอบกำแพงไปจนสุดกำแพง
                ahead(moveAmount);
                // หมุนตัวเองทางขวาเพื่อให้วิ่งตามขอบกำแพงอันถัดไป
                turnRight(90);
            }
        }


    เคลื่อนที่เป็นวงกลม
    ลองเปิดหุ่นยนต์ SpinBot
    เราจะเห็น code ใน method run() ดังต่อไปนี้


        public void run() {
            ...

            // ทำไปเรื่อยๆจนกว่าจะตาย
            while (true) {
                // setTurnRight สั่งให้หมุนไปทางขวาเรื่อยๆ เมื่อเราทำการเคลื่อนที่ ใช้ได้ก็ต่อเมื่อ extend AdvanceRobot เท่านั้น
                // สั่งให้เกมส์เมื่อเราทำการเคลื่อนที่ ให้เราหมุนไปทางขวาเยอะๆๆๆ
                setTurnRight(10000);
                // ตั้งความเร็วสูงสุดของการเลี้ยวคือ 5
                setMaxVelocity(5);
                // เคลื่อนที่ไปพร้อมๆกับหมุน
                ahead(10000);
                // ทำซ้ำอีกครั้ง
            }
        }


    เคลื่อนที่เป็นซิกแซก
    ลองเลือกเปิดหุ่นยนต์ MyFirstRobot
    เราจะเห็น code ใน method run() ดังต่อไปนี้     
       public void run() {

            ...
            
    // ทำไปเรื่อยๆจนกว่าจะตาย
            while (true) {
                ahead(100); // เลื่อนไปข้างหน้า 100
                turnGunRight(360); // หมุนปืน 1 รอบ
                back(100); // เลื่อนไปข้างหลัง 100
                turnGunRight(360); // หมุนปืนอีก 1 รอบ
            }
        }
    เคลื่อนที่โดยสุ่ม (MyFirstRobotRandom.java)
    เนื่องจากหุ่นยนต์เคลื่อนที่แบบสุ่มไม่มีตัวอย่างใน package ของ robocode  
    ผมจึงแก้ไขโค้ด MyFirstRobot ให้สุ่มการเคลื่อนที่ทั้งจำนวนขาไปขากลับและจำนวนองศาที่หมุน เพื่อแสดงให้เป็นตัวอย่าง ดังต่อไปนี้
    import java.lang.Math;
    ...
       public void run() {
            ...
            
    // ทำไปเรื่อยๆจนกว่าจะตาย
            while (true) { 
                //Math.random() จะสุ่มค่ามาให้ตั้งแต่ 0..1 อย่างเช่น 0.000231, 0.984441 เมื่อนำมาคูณกับ 800 ก็จะได้ค่าสุ่มอยู่ในระหว่าง 0.0 x 800 = 0 กับ 1.0 x 800 = 800 หรืออยู่ในช่วง [0,800]
                //(int)(X) ทำให้ตัวแปร X ซึ่งเป็นตัวแปรประเภทอะไรก็ตามเป็น Integer
                ahead((int)(Math.random()*800)); // เคลื่อนที่ไปข้างหน้าโดยค่าสุ่มจากตั้งแต่ 0 ถึง 800 pixel(s)
                turnGunRight((int)(Math.random()*360)); // หมุนปืนไปทางด้านขวาโดยสุ่มองศาตั้งแต่ 0 ถึง 360 องศา
                back((int)(Math.random()*800)); // 
    เคลื่อนที่ไปข้างหลังโดยค่าสุ่มจากตั้งแต่ 0 ถึง 800 pixel(s)
                turnGunRight((int)(Math.random()*360)); // หมุนปืนไปทางด้านขวาโดยสุ่มองศาตั้งแต่ 0 ถึง 360 องศา
            }
        }


    การเคลื่อนที่ขั้นสูง
    มีหลากหลายแบบมาก จะขออธิบายเฉพาะอันที่มีชื่อเสียงมากๆ อาทิเช่น
    1. Wavesurfing
    2. Anti-Gravity
    ในหน้าถัดไปครับ :D



    หน้าที่ 9 - การเคลื่อนที่ของหุ่นยนต์(ขั้นสูง)

    การเคลื่อนที่ของหุ่นยนต์ขั้นสูงประกอบด้วย 2 อันใหญ่ๆ ดังนี้คือ
    1.Wavesurfing Movement(การเคลื่อนที่แบบโต้เคลื่อน)
    2.Anti-gavity Movement(การเคลื่อนที่โต้ต้านแรงโน้มถ่วง)


    การเคลื่อนที่โต้คลื่น
    เป็นการเคลื่อนที่ที่ดีมาก สำหรับการต่อสู้ 1-vs-1 โดยที่จะสามารถหลบกระสุนของศัตรูได้อย่างยอดเยี่ยมมาก
    คลื่นในโรโบโค้ดคืออะไร?

    ในทุกๆครั้งเมื่อหุ่นยนต์ศัตรู(หรือหุ่นยนต์เราเอง) ยิงกระสุนมาหนึ่งนัดจะก่อเกิดวงกลม ที่มีจุดศูนย์กลางที่หุ่นยนต์ และเส้นรอบวงกลมจะเป็นเส้นที่บ่งบอกความเป็นไปได้รอบ 360 องศาว่าจะมีกระสุนอยู่ ณ ช่วงเวลานั้นๆ
    รัศมีของคลื่นนั้นสามารถคำนวณได้จาก = ความเร็วของกระสุน x (วินาทีปัจจุบัน - วินาทีที่ยิง) 
        
    แล้วโต้คลื่นคืออะไร?
    การโต้คลื่นคือการพยายามเคลื่อนที่ไต่เส้นคลื่นของกระสุนที่กำลังวิ่งมาหาเราที่อยุ่ใกล้กับเราที่สุด ซึ่งทำให้เราเคลื่อนที่เป็นมุมฉากกับรัศมีของคลื่นกระสุน เพื่อให้เวลาที่กระสุนผ่านเคลื่อนที่หุ่นยนต์เรานั้น ใช้เวลาสั้นที่สุด และใช้เวลาหลบน้อยที่สุด(หักหลบโดยไต่เส้นคลื่นทวนเข็มหรือตามเข็มนาฬิกา)
    เมื่อเราไม่สามารถ scan กระสุนได้ แล้วเราจะรู้ได้อย่างไรว่ากระสุนถูกยิงมาแล้ว และตำแหน่งอยู่ที่ไหน
    ถึงแม้ว่าเราไม่สามารถ scan กระสุนได้ แต่เราสามารถ scan หุ่นยนต์ของศัตรูได้ เมื่อหุ่นยนต์ศัตรูพลังงานลด โดยที่เราไม่ได้โดนกระสุนของเรายิง แสดงว่าศัตรูได้นำไปใช้ในการยิงใส่เรา เราสามารถรู้ความเร็วของกระสุน โดยดูที่พลังงานที่ศัตรูใช้ไป ส่วนตำแหน่งนั้น เราพอคาดเดาได้จากตำแหน่งของเรา เนื่องจากไม่ว่าอย่างไร หุ่นยนต์ศัตรูต้องเล็งมาหาเราแน่ พยายามหลบออกจากตำแหน่งเก่าใน ณ วินาทีที่ศัตรูยิงกระสุนมา
    แล้วเราจะหักหลบไปทางไหนดี
    เก็บคลื่นทุกคลื่นลง array โดยจดจำตำแหน่งของตัวเองลงไปด้วย เวลาเราเลือกว่าจะไปทางทวนเข็มนาฬิกาหรือตามเข็มนาฬิกาดีนั้น พยายามเลือกโดยดูกระสุนถัดไปในชุดหลังด้วยเช่น กระสุนที่สอง ที่สาม เลือกด้านที่มีความเสี่ยงยิงโดนให้น้อยที่สุดครับ


    ตัวอย่างโค้ด [Basic Surfer]
    แหล่งอ้างอิง : 
    http://testwiki.roborumble.org/w/index.php?title=Wave_Surfing
    http://robowiki.net/cgi-bin/robowiki?WaveSurfing/Tutorial


    การเคลื่อนที่ต้านแรงโน้มถ่วง
    การเคลื่อนที่ต่อต้านแรงโน้มถ่วง เป็นการเคลื่อนที่อยู่บนหลักการที่ว่า มีแรงดึงดูดหรือแรงผลักในพื้นที่สนามรบ ดึงดูดให้หุ่นยนต์ของเราให้เข้ามาในพื้นที่บริเวณเป็นพิเศษ หรือผลักหุ่นยนต์ของเราให้หลีกเลี่ยงพื้นที้บริเวณนี้เป็นกรณีพิเศษ เพื่อที่จะหลอกหุ่นยนต์ที่มีความสามารถในการเล็งศัตรูในรูปแบบตายตัว(pattern) ต่างๆ ดังเช่นในภาพดังต่อไปนี้



    สมมุติว่ามีแรงโน้มถ่วง (เว็กเตอร์ F) ดึงดูดให้หุ่นยนต์ของเรามาอยู่บริเวณมุมซ้ายล่างเป็นกรณีพิเศษ




    หลอกหุ่นยนต์ที่เล็งแบบ pattern ได้อย่างไร?
    เนื่องจากว่าหุ่นยนต์ศัตรู(ซึ่งส่วนมาก) ที่เลือกใช้วิธีการเล็งแบบเป็น pattern เช่น การเล็งแบบเส้นตรง(Linear Targeting), การเล็งแบบวงโค้ง(Circula Targeting) นั้น ทำบนสมมุติฐานที่ว่าหุ่นยนต์ของเราจะเคลื่อนเป็น pattern กระจายไปทั่วทั้งฉากอย่างเท่าๆกัน เมื่อเราให้น้ำหนักบริเวณใด บริเวณหนึ่งเป็นพิเศษจะทำให้การเล็ง pattern เหล่านั้น ด้อยประสิทธิภาพลงไปได้เยอะ


    ตัวอย่างโค้ด

    void antiGravMove() {
        //ปรับให้แรงดึงดูดแกน X เริ่มต้นเป็น 0
        double xforce = 0;
        //ปรับให้แรงดึงดูดแกน Y เริ่มต้นเป็น 0
        double yforce = 0;
        double force;
        double ang;
        GravPoint p;
        
        //วนลูปไล่ตั้งแต่แรงดึงดูดแรกถึงแรงดึงดุดสุดท้าย
        for(int i = 0;i<gravpoints.size();i++) {
        //ให้ p เป็นแรงดึงดูดที่กำลังสนใจ
            p = (GravPoint)gravpoints.elementAt(i);
        //คำนวณแรงดึงดูดจากจุดนั้นกับจุดที่เราอยู่ ตามทฤษฎีพิสิกส์แรงดึงดูดของสองวัตถุที่เคยเรียนในม.ปลาย
        //F = GmM/R^2 โดยที่เราสมมุติว่า G = 1 (บนดาวเคราะห์ที่ไหนซักแห่ง), m = 1, M = 1 (หุ่นยนต์มีน้ำหนักเท่ากัน)
        //แหล่งอ้างอิง http://regentsprep.org/Regents/physics/phys01/unigrav/default.htm

            force = p.power/Math.pow(getRange(getX(),getY(),p.x,p.y),2);
            //คำนวณหามุมองศาของแรงดึงดูด
            ang = 
        normaliseBearing(Math.PI/2 - Math.atan2(getY() - p.y, getX() - p.x)); 
            //บวกค่าแรงดึงดูดของ p เข้าไปในแรงดึงดูดรวมของแกน X และ Y โดยใช้องศาที่คำนวณมาได้ข้างต้น
            xforce += Math.sin(ang) * force;
            yforce += Math.cos(ang) * force;
        }
        //ลูปจนเสร็จ จนเราได้ค่าแรงโน้มถ่วงรวมของแกน X และ Y เรียบร้อยแล้ว
           
        //เคลื่อนที่ไปยังจุดที่ต้องการโดยหัก(หรือเพิ่ม)แรงดึงดูดตามแกน X,Y แล้ว 
        goTo(getX()-xforce,getY()-yforce);
    }


    จุดแข็งที่ดีที่สุดของ Anti-Gravity Movement

    เป็นการเคลื่อนที่ที่เหมาะที่สุด สำหรับการต่อสู้ที่มากกว่า 2 ทีมเป็นต้นไป
    โดยการเปลี่ยนแรงโน้มถ่วงคงที่ เปลี่ยนไปเป็นให้ตำแหน่งของหุ่นยนต์ศัตรูเป็นตำแหน่งของแรงผลักให้ห่าง
    ซึ่งจะทำให้เราสามารถเคลื่อนที่ตีตัวออกห่างจากกลุ่มของศัตรูได้
    ซึ่งโดยมากแล้ว การยิงต่อสู้นั้น หุ่นยนต์มักจะเลือกหุ่นยนต์ที่ใกล้ตัวมากที่สุด
    ซึ่งถ้าหุ่นยนต์ของเราอยู่ห่างจากกลุ่มของศัตรู หุ่นยนต์ของเราจะมีโดนยิงน้อยลง และมีโอกาสยิงหุ่นยนต์ตัวอื่นอย่างฟรีๆมากขึ้น
    แหล่งอ้างอิง : http://www.ibm.com/developerworks/java/library/j-antigrav/


    ตอนต่อไป เป็นเกี่ยวกับการเล็งศัตรูนะครับ :D



    หน้าที่ 10 - การเล็งและยิงศัตรู(เบื้องต้น)

    การเล็งและยิง เป็นจุดสำคัญการตัดสินผลของเกมส์ หากหุ่นยนต์มีความสามารถในการยิงได้อย่างแม่นยำ โอกาสชนะก็ไม่ไกลเกินเอื้อม
    การเล็งและการยิงมีหลากหลายแบบ อาทิเช่น
    1. ยิงทันทีเมื่อเจอ (Head-on Targeting)
    2. ยิงดักแบบง่าย (Simple Targeting)
       2.1 ยิงดักสำหรับหุ่นยนต์เคลื่อนที่เป็นเส้นตรง (Linear Targeting)
       2.2 ยิงดักสำหรับหุ่นยนต์เคลื่อนที่เป็นวงกลม (Circular Targeting)
    3. ยิงสุ่มเป็นกลุ่มสู่เป้าหมาย (Random or Scatter Targeting)
    4. ยิงโดยคาดเดาและจดจำ (Guess Factor Targeting)


    1. ยิงทันทีเมื่อเจอ
    อันนี้คงไม่ต้องพูดอะไรมาก เจอปุ๊ป ยิงปั้บ โอกาสยิงโดนค่อนข้างต่ำ จะดีเมื่ออยู่ใกล้มากๆเท่านั้น
    public void run() {
    //...
    }
    public void onScannedRobot(ScannedRobotEvent e) {
        fire(1);
    }

    2. ยิงดักแบบง่าย
    เป็นการยิงดัก เผื่อเวลาให้ลูกกระสุนเคลื่อนที่ไปโดนหุ่นยนต์ศัตรู โดยการเก็บข้อมูลของหุ่นยนต์ฝ่ายตรงข้าม ไม่มากนัก
      2.1 การยิงดักสำหรับหุ่นยนต์เคลื่อนที่เป็นเส้นตรง
      เราจะยิงเผื่อเวลาที่ลูกกระสุนเคลื่อนที่ไปโดนหุ่นยนต์ศัตรู โดยเราสมมุติเอาว่า หุ่นยนต์ของศัตรูจะเคลื่อนที่ไปข้างหน้า ด้วยทิศทางและความเร็วเท่าเดิม


    // คำนวณมุมระหว่างศัตรูกับเรา เช่นศัตรูอยู่ตำแหน่งที่ 1 นาฬิกาของตัวเรา ก็หมายความว่า adsoluteBearing จะมีค่า 30 องศา
    double absoluteBearing = getHeadingRadians() + e.getBearingRadians();
    /**คำนวณความเร็วของหุ่นยนต์ศัตรู 
    ซึ่งจะเท่ากับ e.getVelocity() * Math.sin(e.getHeadingRadians() - absoluteBearing)
    แล้วเรา
    คำนวนองศาของปืนโดยการสมมุติว่ายังเดินทางไปด้วยความเร็วและทิศทางที่เราคำนวณได้ข้างต้นจนกว่ากระสุนจะเคลื่อนที่ไปถึง จะสร้างเป็นรูปสามเหลี่ยมได้ดังนี้



    ดังนั้นมุม ก จะสามารถหาได้โดยใช้ asin() (arc sine) [อ้างอิงhttp://en.wikipedia.org/wiki/Inverse_trigonometric_function]
    = asin((ความเร็วของหุ่นยนต์ศัตรู x เวลาที่กระสุนใช้ในการเดินทาง) / (ความเร็วของกระสุน x เวลาที่กระสุนใช้ในการเดินทาง))
    = asin(
    ความเร็วของหุ่นยนต์ศัตรู / ความเร็วของกระสุน)
    เนื่องจากว่าเราใช้แรงยิง = 3.0
    ความเร็วของกระสุนจึงเท่ากับ = 20 - 3 * 3.0
     = 11.0
    เราหมุนเรดาร์ไปยังมุมสมบูรณ์โดยอ้างอิงจากสนามรบ เราจึงหมุนปืนเพิ่มเติม ในกรณีที่ตำแหน่งของปืนนั้นไม่ได้วางตัวที่ 0 องศาที่ทิศเหนือ
    โดยหาจากสมการ absoluteBearing - getGunHeadingRadians()
    การคำนวณมุมของปืนทั้งหมดจึงเป็น ...**/

    double absoluteBearing = getHeadingRadians() + e.getBearingRadians();
    setTurnGunRightRadians(Utils.normalRelativeAngle(absoluteBearing - getGunHeadingRadians() + Math.asin(e.getVelocity() * Math.sin(e.getHeadingRadians() - absoluteBearing) / 11.0)));
    setFire(3.0);
    แหล่งอ้างอิง http://testwiki.roborumble.org/w/index.php?title=Linear_Targeting


    2.2 ยิงดักสำหรับหุ่นยนต์เคลื่อนที่เป็นวงกลม (Circular Targeting)
    ใช้ในการยิงหุ่นยนต์ที่มักที่จะเดินเป็นวงกลมหรือโค้ง โดยมีหลักการดังนี้
      1. วัดอัตราการหมุนของหุ่นยนต์ศัตรูโดยลบจากการหันตัวปัจจุบันและการหันตัวครั้งที่แล้วของหุ่นยนต์ศัตรู  ถ้าเรดาร์ไม่สามารถจับการหมุนตัวของศัตรูได้ทุกวินาที ให้จดจำระยะเวลาเป็นวินาทีที่เรดาร์ขาดหายไป แล้วหารกับผลต่างของมุม เพื่อหาค่าเฉลี่ย


    public void onScannedRobot(ScannedRobotEvent e)
    {
    double turnrate=(e.getHeadingRadians()-lastEnemyHeading)/(getTime()-scantime);
    scantime=getTime();
    lastEnemyHeading=e.getHeadingRadians();
    ...
    }


     2. เราจะสามารถหาตำแหน่งของศัตรู ได้โดยจากมุมที่ scan ได้แล้ว แตกแกน X และ Y เพื่อใช้ในการคำนวณหาตำแหน่งของศัตรู


    absoluteBearing = e.getBearingRadians() + getHeadingRadians();
    double relativeX = e.getDistance()*Math.sin(absoluteBearing);
    double relativeY = e.getDistance()*Math.cos(absoluteBearing);


    3.  เรากะตำแหน่งของศัตรูในอนาคตโดยที่คิดว่าหุ่นยนต์ของศัตรูจะหมุนตัวด้วยอัตราคงที่และด้วยความเร็วคงที่ เมื่อเรานำข้อมูลของวินาทีที่ 0 มาคำนวณ เราจะได้ตำแหน่งวินาทีที่ 1 ของศัตรจะเป็น
    วินาทีที่ 1


    newX1 = relativeX + e.getVelocity()*Math.sin(initialHeading + turnrate)
    newY1 = relativeY + e.getVelocity()*Math.cos(initialHeading + turnrate)

    เมื่อเราคำนวณวินาทีที่ 2 จากข้อมูลวินาทีที่ 0 มาคำนวณก็จะได้เป็น
    newX2 = relativeX + e.getVelocity()*Math.sin(initialHeading + turnrate) +
    e.getVelocity()*Math.sin(initialHeading + turnrate + turnrate)
    newY2 = relativeY + e.getVelocity()*Math.cos(initialHeading + turnrate) +
    e.getVelocity()*Math.cos(initialHeading + turnrate + turnrate)

    เมื่อเราคำนวณวินาทีที่ T จากข้อมูลวินาทีที่ 0 มาคำนวณก็จะได้เป็น
    newXT = relativeX + e.getVelocity()*Math.sin(initialHeading + turnrate) +
    e.getVelocity()*Math.sin(initialHeading + 2 x turnrate) + ... +
    e.getVelocity()*Math.sin(initialHeading + T x turnrate)
    newYT = relativeY + e.getVelocity()*Math.cos(initialHeading + turnrate) +
    e.getVelocity()*Math.cos(initialHeading + 2 x turnrate) + ... +
    e.getVelocity()*Math.cos(initialHeading + T x turnrate)


    ลองเขียนในสมการผลรวม :D (ใครชอบคณิตศาสตร์บ้างครับ ยกมือออ!!)
    [นี่ไม่ใช่ java code นะครับ]
    newXT = relativeX +
    sum.gif e.getVelocity()*Math.sin(initialHeading + T*turnrate)


    newYT = relativeY +
    sum.gif e.getVelocity()*Math.cos(initialHeading + T*turnrate)


    ถึงแม้ว่าสนามรบและเวลาในโรโบโค้ดไม่ได้เป็นจำนวนต่อเนื่อง (Continuous) เพราะว่าเราแทนพื้นที่สนามรบด้วยจำนวน pixels และเวลาเป็น tick ซึ่งคอมพิวเตอร์ไม่สามารถสั่งให้หุ่นยนต์ของเราอยู่ในจุดที่ละเอียดกว่า 1 pixel ได้ หรือสามารถควบคุมให้หุ่นยนต์ของเราอย่ในช่วงเวลาที่ละเอียดกว่า 1 tick ได้
    ดังนั้น! โรโบดค้ดจึงเป็นจำนวนไม่ปะติดปะต่อ (Discrete) 
    แต่หน่วย pixel และ tick ของโรโบโค้ดก็มีละเอียดมากพอที่จะทำ Integral เพื่อประมาณผลรวม (พื้นที่ใต้กราฟ) อย่างสมการ Continuous ได้ โดยที่ค่าผลต่างของจริงกับที่ประมาณมีค่าน้อยมาก
    [นี่ไม่ใช่ java code นะครับ]
    newXT = relativeX + e.getVelocity() *
    integral.gif Math.sin(initialHeading + t*turnrate) dt
    newYT = relativeY + e.getVelocity() *
    integral.gif Math.cos(initialHeading + t*turnrate) dt
    ก็จะได้ผล Integral ออกมาเป็นสมการสูตรสำเร็จ หาตำแหน่งของศัตรูในระยะเวลาที่ T จากข้อมูลของระยะเวลาที่ 0
    newXT = relativeX - (e.getVelocity()/turnrate) *
    (Math.cos(initialHeading + T*turnrate) - Math.cos(initialHeading))


    newYT = relativeY + (e.getVelocity()/turnrate) *
    (Math.sin(initialHeading + T*turnrate) - Math.sin(initialHeading))


    สวยงามไหมล่ะครับ :D
    อ้างอิง : http://testwiki.roborumble.org/w/index.php?title=Circular_Targeting/Walkthrough


    ตอนต่อไปการเล็งและยิงแบบโปรขึ้นอีกครับ :D



    หน้าที่ 11 - การเล็งและยิงศัตรู(ขั้นสูง)

    ยิงสุ่มเป็นกลุ่มสู่เป้าหมาย (Random or Scatter Targeting)

    เป็นการยิงกระจายโดยสุ่มตำแหน่ง ยิงไปบริเวณแถวๆที่เราจับศัตรูครั้งล่าสุดได้ ไม่เกิน 46.6 องศาทั้งตามและทวนเข็มนาฬิกาสำหรับการยิงพลังงาน 3 เนื่องจากหุ่นยนต์เป้าหมายมีความเร็วจำกัดและไม่สามารถเคลื่อนที่ได้เร็วมากพอที่ผ่าวงกระสุนเกินกว่ารัศมีเหล่านี้ได้ (จากรุปหุ่นยนต์สีดำไม่มีทางเคลื่อนที่ไปถึงขอบสีดำของทั้งสองด้านได้เร็วกว่าความเร็วกระสุนเคลื่อนที่ถึงตัวหุ่นยนต์)
    โดยพลังงานที่เลือกใช้ยิงจะมีผลต่อความเร็วและองศาเป็นสูตรดังต่อไปนี้
    สมุมติเราเลือกยิงด้วยพลังงาน 3
    ความเร็วกระสุนเท่ากับ 20 - 3 x 3 = 11
    ความเร็วสูงสุดของหุ่นยนต์ศัตรูเท่ากับ 8 pixels/ตา
    ดังนั้นองศามากที่สุดที่หุ่นยนต์เคลื่อนที่หนีไปได้ = arcsin(8/11) = +-46.68 องศา
    พลังงานและองศามุมยิง
    พลังงาน 1 = arcsin(8/17) =  +-28.08 องศา
    พลังงาน 2 = arcsin(8/14) =  +-34.86 องศา
    พลังงาน 3 = arcsin(8/11) =  +-46.68 องศา
    พลังงาน 4 = arcsin(8/8) = +-90.04 องศา
    ยิงโดยคาดเดาและจดจำ (Guess Factor Targeting)

    อันนี้พัฒนาต่อเนื่องมาจาก Random Targeting เราเปลี่ยนจากยิงมั่วๆในขอบองศาที่ศัตรูไม่มีทางเคลื่อนที่ไปถึง มาเก็บด้วยว่าองศาไหนยิงแล้วได้ผลดีที่สุด
    Guess Factor Targeting เปลี่ยนจากองศามาเป็นคะแนนต่างๆดังนี้
    1.0 คือมุมที่กว้างที่สุด ถ้าหุ่นยนต์เคลื่อนที่ไปในทิศทางเดิมด้วยความเร็วสูงสุด โดยที่อ้างอิงตามพลังงานที่เราใช้ในการยิงกระสุน
    0.0 คือมุมยิงตรงๆ เหมือน Head-on Targeting
    -1.0 คือมุมที่กว้างที่สุด ถ้าหุ่นยนต์เคลื่อนที่ไปในทิศทางตรงกันข้ามด้วยความเร็วสูงสุด โดยที่อ้างอิงตามพลังงานที่เราใช้ในการยิงกระสุน


    ขั้นแรกลองยิงกระสุนกระจายๆดูก่อน แล้วหาว่าจะยิงโดนเมื่อเล็งด้วยคะแนนเท่าไร่ อย่างเช่นสมมุติเรายิงด้วยคะแนน  0.5 แล้วโดนศัตรู ขณะที่ศัตรูกำลังเคลื่อนที่ทวนเข็มนาฬิกา
    หุ่นยนต์ของเราจะยิงศัตรู ด้วยคะแนน 0.5 เมื่อเคลื่อนที่ทวนเข็ม และยิงศัตรูด้วยคะแนน 0.5 x -1 = -0.5 เมื่อเคลื่อนที่ตามเข็ม
    ก็จะทำให้หุ่นยนต์ของเรายิงโดนศัตรูได้ดีขึ้นมากครับ
    วิธีการนี้ Popular ที่สุดในบรรดา 1-vs-1 ทั้งหลายครับ :D
    ข้อมูลอ้างอิง : http://testwiki.roborumble.org/w/index.php?title=GuessFactor_Targeting_(traditional)



    อ่านทั้งหมด: 940, ความเห็นทั้งหมด: 0

    แสดงความเห็น
    ข้อความ
       
      
     
     
       
    แนบรูป *เฉพาะสมาชิกเท่านั้น
    จาก  
    พิมพ์คำว่า คนไทย ในช่องนี้ ->

    เรื่องราวอื่นๆจากบลอกเพื่อนบ้าน

    ไปเที่ยวเดอะกะตะรีสอร์ทที่ภูเก็ตมา(ดีโพลมา2557).
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ (ดีโพลมา2560)
    กฎหมายค่าส่วนกลาง(ดีโพลมา2559)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 24 (ดีโพลมา2558)
    กินอย่างไร เมื่อไตรกลีเซอไรด์ในเลือดสูง
    กินอย่างไรห่างไกลเบาหวาน
    กินอย่างไร เมื่อเป็นโรคเบาหวาน
    หางาน part time งานผ่านเน็ต รับงานทำที่บ้านได้ คลิก
    โรคความดันโลหิตสูง รักษาได้ แค่หลีกให้ไกลจากโซเดียม
    อีเมล และสมอง อัศจรรย์แห่งการเชื่อมโยง
    Japanese Language Course
    แค่หลับสนิท ก็ผอมได้ไม่น่าเชื่อ!
    อลังการอะ ศิลปะบนผนังที่ห้างรูปเกือกม้าในเนเธอร์แลนด์
    วิธีลดน้ําหนัก 5 กิโล 1 อาทิตย์ สูตรเด็ดที่สาว ๆ ต้องคิดก่อนลอง !
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2556)
    สตช. เพิ่งตื่น สั่งเข้มปราบปรามแหล่งเงินกู้นอกระบบ(ดีโพลมา2555)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 23(ดีโพลมา2554)
    30 วิธีฉลาดสุดๆ ที่ทำให้ชีวิตคุณ “ง่ายขึ้น” ไปดูว่ามีอะไรบ้าง!
    การปรับเปลี่ยนตัวเอง เพื่อเป็นคนที่มีความสุขทำอย่างสม่ำเสมอ
    งานพิเศษ งานรายได้เสริม ใช้เวลาว่างๆ 2-3 ชั่วโมง ทำงาน ที่นี่ค่ะ
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2553)
    อินไซด์ตำรวจประจำวันที่18ต.ค.2557(ดีโพลมา2552)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 22(ดีโพลมา2551)
    ตามหาญาติ (ดีโพลมา2550)
    หางานทำที่บ้าน งานทำทางเน็ต สร้างรายได้ที่บ้านค่ะ
    เลือกที่พัก รายวัน รายเดือน อย่างไรดี
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2549)
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2548)
    แต่งตั้งนายตำรวจราชสำนัก (ดีโพลมา2547)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 21ขอขอบคุณที่มาของข่าว/ภาพจากผู้ที่มีชื่ออยู่ด้านล่างนี้ทุก
    หนังเรื่องผีชี่วะ ภาค4 (ดีโพลมา2545)
    หนี้เสียเกิดจากการปล่อยสินเชื่อที่ไม่มีคุณภาพ (ดีโพลมา2544)
    หางาน หางานทำที่บ้าน คีย์งานผ่านเน็ต ง่ายๆ คลิกเลย
    9 สุดยอดผัก แหล่งสารต้านอนุมูลอิสระชั้นเลิศ
    ลดความเครียดและรอบเอวด้วยอาหาร 4 ชนิด ที่คิดไม่ถึง
    เช็กสิ 14 สัญญาณที่บ่งบอกว่าคุณกำลังเครียดมากเกินไป
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2541)
    "เอก" รองผบ.ตร. ตั้งกรรมการ กำกับแต่งตั้งตำรวจ ล้อมคอกร้องทุกข์(ดีโพลมา2540)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 20(ดีโพลมา2539)
    MAiSEN รีวิว เมนู ชุดสุกี้ยากี้ คุโรบูตะ ไข่ออนเซน ร้าน ไมเซน สยามสแควร์วัน
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2538)
    กฎหมายถอนฟ้อง(ดีโพลมา2537)
    กำเนิดเจ้าแม่กวนอิม - ตอนที่ 19(ดีโพลมา2536)
    “รพ.จุฬาลงกรณ์” เชิญผู้สูงวัยชาย-หญิง(ดีโพลมา2535)
    งานพิเศษ งาน part time พิมพ์ข้อมูลผ่านเว็บ หางานคลิกเลย
    International Course
    คลิปสรุปข่าวประจำวันนี้มีหลายข่าวต่อเนื่องอัตโนมัติ(ดีโพลมา2534)
    พิธีสวนสนาม นรต. วันตำรวจ (ดีโพลมา2533)
    ตำนานลูกทุ่งชุด 3 - อ๊อดโฟร์เอส(ดีโพลมา2532)
    จุฬาลงกรณ์ รับสมัครบุคคล(ดีโพลมา2530)

    เลือกดูบลอก Search:
    ใช้เวลาประมวลผลหน้านี้ 62.4001ms