CodeGym /จาวาบล็อก /สุ่ม /ส่วนเกมใน CodeGym: ทฤษฎีที่เป็นประโยชน์
John Squirrels
ระดับ
San Francisco

ส่วนเกมใน CodeGym: ทฤษฎีที่เป็นประโยชน์

เผยแพร่ในกลุ่ม
ในส่วน "เกม"บน CodeGym คุณจะพบโปรเจ็กต์ที่น่าตื่นเต้นที่เกี่ยวข้องกับการเขียนเกมคอมพิวเตอร์ยอดนิยม ต้องการสร้างเกมยอดนิยม 2048, Minesweeper, Snake และเกมอื่นๆ ในเวอร์ชั่นของคุณเองหรือไม่? มันง่าย เราได้เปลี่ยนการเขียนเกมให้เป็นกระบวนการทีละขั้นตอน ส่วน "เกม" ใน CodeGym: ทฤษฎีที่เป็นประโยชน์ - 1เพื่อทดสอบความสามารถของคุณในฐานะนักพัฒนาเกม คุณไม่จำเป็นต้องเป็นโปรแกรมเมอร์ขั้นสูง แต่จำเป็นต้องมีชุดความรู้เฉพาะของจาวา ที่นี่ คุณจะพบข้อมูลที่เป็นประโยชน์ในการเขียนเกม

1. มรดก

การทำงานกับเอ็นจิ้นเกม CodeGym เกี่ยวข้องกับการใช้การสืบทอด แต่ถ้าคุณไม่รู้ว่ามันคืออะไร? ในแง่หนึ่ง คุณต้องเข้าใจหัวข้อนี้: ศึกษาในระดับ 11. ในทางกลับกัน เครื่องยนต์ได้รับการออกแบบมาเป็นพิเศษให้มีความเรียบง่าย ดังนั้นคุณจึงสามารถหลีกเลี่ยงความรู้เพียงผิวเผินเกี่ยวกับการสืบทอดได้ ดังนั้นมรดกคืออะไร? พูดง่ายๆ ก็คือ การสืบทอดคือความสัมพันธ์ระหว่างสองคลาส คนหนึ่งกลายเป็นพ่อแม่และอีกคนกลายเป็นลูก (ผู้สืบสกุล) ยิ่งกว่านั้น ชนชั้นผู้ปกครองอาจไม่รู้ด้วยซ้ำว่ามีลูกหลาน กล่าวอีกนัยหนึ่งมันไม่ได้มีข้อได้เปรียบพิเศษใด ๆ จากการมีลูกหลาน แต่มรดกให้ประโยชน์มากมายแก่ลูกหลาน และที่สำคัญที่สุดก็คือตัวแปรและเมธอดของคลาสพาเรนต์ทั้งหมดจะปรากฏในคลาสลูกหลานราวกับว่ารหัสของคลาสพาเรนต์ถูกคัดลอกไปยังคลาสลูกหลาน นี่ไม่ใช่คำอธิบายที่ถูกต้องทั้งหมด แต่จะเพียงพอสำหรับการทำความเข้าใจเรื่องมรดกให้ง่ายขึ้น ตัวอย่างที่ 1:การสืบทอดที่ง่ายที่สุด

public class Parent {

}
คลาสลูกสืบทอด คลาส พาเรนต์โดยใช้คีย์เวิร์ดขยาย

public class Child extends Parent {

}
ตัวอย่างที่ 2:การใช้ตัวแปรของคลาสพาเรนต์

public class Parent {

   public int age;
   public String name;
}
คลาสลูก สามารถใช้ตัวแปร อายุและชื่อของคลาสพาเรนต์ได้เหมือนกับที่ประกาศในคลาสพาเรนต์

public class Child extends Parent {

   public void printInfo() {

     System.out.println(name+" "+age);
   }
}
ตัวอย่างที่ 3:การใช้เมธอดของคลาสพาเรนต์

public class Parent {

   public int age;
   public String name;

   public getName() {
      return name;
  }
}
คลาสลูกสามารถใช้ ตัวแปรและเมธอดของคลาส พาเรนต์ได้เหมือนกับที่ประกาศไว้ในคลาสลูก ในตัวอย่างนี้ เราใช้เมธอดgetName()

public class Child extends Parent {

   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}
นี่คือ ลักษณะของคลาส Childสำหรับคอมไพเลอร์:

public class Child extends Parent{

   public int age;  // Inherited variable
   public String name;  // Inherited variable

   public getName() {  // Inherited method.
      return name;
  }
   public void printInfo() {

     System.out.println(getName()+" "+age);
   }
}

2. วิธีการเอาชนะ

บางครั้งมีบางสถานการณ์ที่เราสร้างคลาส Child ของเราสืบทอดคลาส Parent ที่มีประโยชน์มากๆ พร้อมกับตัวแปรและเมธอดทั้งหมด แต่เมธอดบางเมธอดไม่ได้ผลตามที่เราต้องการ หรือไม่เป็นไปตามที่เราต้องการเลย เราจะทำอย่างไรในสถานการณ์นี้? เราสามารถแทนที่วิธีการที่เราไม่ชอบ สิ่งนี้ทำได้ง่ายมาก: ในคลาส Child ของเรา เราเพียงแค่ประกาศเมธอดที่มีลายเซ็นเดียวกับเมธอดในคลาส Parent จากนั้นเราก็เขียนโค้ดของเราเองลงไป ตัวอย่างที่ 1:การแทนที่เมธอด

public class Parent {

   public String name;

   public void setName(String nameNew) {
       name = nameNew;
  }

   public getName() {
      return name;
  }
}
เมธอด printInfo() จะแสดง"Luke, No!!!"

public class Child extends Parent{

   public void setName(String nameNew) {
       name = nameNew + ", No!!!";
  }

   public void printInfo() {
      setName("Luke");
      System.out.println(getName());
   }
}
นี่คือ ลักษณะของคลาส Childสำหรับคอมไพเลอร์:

public Child extends Parent {

   public String name;  // Inherited variable

   public void setName(String nameNew)  // Overridden method instead of the inherited method {

       name = nameNew + ", No!!!";
   }
   public getName() {  // Inherited method.

      return name;
   }
   public void printInfo() {

     setName("Luke");
     System.out.println( getName());
   }
}
ตัวอย่างที่ 2:เวทมนตร์สืบทอดบางอย่าง (และวิธีการเอาชนะ)

public class Parent {

   public getName() {
      return "Luke";
  }
   public void printInfo() {

     System.out.println(getName());
   }
}

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
  }
}
ในตัวอย่างนี้ ถ้าprintInfoเมธอด (จากคลาสพาเรนต์) ไม่ถูกแทนที่ในคลาสลูก เมื่อเมธอดนี้ถูกเรียกใช้บนวัตถุลูก เมธอดgetName()จะถูกเรียกแทนเมธอดของคลาสพาเรgetName()นต์

Parent parent = new Parent ();
parent.printnInfo();
รหัสนี้แสดง"ลุค"บนหน้าจอ

Child child = new Child ();
child.printnInfo();
รหัสนี้แสดง"Luke ฉันคือพ่อของคุณ"บนหน้าจอ
นี่คือ ลักษณะของคลาส Childสำหรับคอมไพเลอร์:

public class Child extends Parent {

   public getName() {
      return "Luke, I am your father";
   }
   public void printInfo() {

     System.out.println(getName());
   }
}

3. รายการ

หากคุณยังไม่ตรงตามรายการ (รายการ) นี่คือภาพรวมโดยย่อ คุณสามารถดูข้อมูลทั้งหมดได้ในระดับ6-7 ของหลักสูตร CodeGym รายการมีหลายอย่างเหมือนกันกับอาร์เรย์:
  • คุณสามารถจัดเก็บข้อมูลจำนวนมากในประเภทเฉพาะ
  • พวกเขาให้คุณรับรายการตามดัชนีของพวกเขา
  • ดัชนีองค์ประกอบเริ่มต้นจาก 0
ประโยชน์ของรายการ: แตกต่างจากอาร์เรย์ รายการสามารถเปลี่ยนขนาดไดนามิก เมื่อรายการถูกสร้างขึ้น ขนาดของรายการจะเป็น 0 เมื่อคุณเพิ่มรายการลงในรายการ ขนาดของรายการจะเพิ่มขึ้น นี่คือตัวอย่างการสร้างรายการ:

ArrayList<String> myList = new ArrayList<String>(); // Create a new ArrayList
ค่าในวงเล็บมุมระบุประเภทข้อมูลที่รายการสามารถจัดเก็บได้ ต่อไปนี้เป็นวิธีการบางอย่างสำหรับการทำงานกับรายการ:
รหัส คำอธิบายสั้น ๆ ว่ารหัสทำอะไร
ArrayList<String> list = new ArrayList<String>(); สร้างรายการสตริงใหม่
list.add("name"); เพิ่มองค์ประกอบที่ส่วนท้ายของรายการ
list.add(0, "name"); เพิ่มองค์ประกอบที่จุดเริ่มต้นของรายการ
String name = list.get(5); รับองค์ประกอบตามดัชนี
list.set(5, "new name"); เปลี่ยนองค์ประกอบตามดัชนี
int count = list.size(); รับจำนวนองค์ประกอบในรายการ
list.remove(4); ลบองค์ประกอบออกจากรายการ
คุณสามารถเรียนรู้เพิ่มเติมเกี่ยวกับรายการได้จากบทความต่อไปนี้:
  1. คลาส ArrayList
  2. ArrayList ในรูปภาพ
  3. การลบองค์ประกอบออกจาก ArrayList

4. อาร์เรย์

เมทริกซ์คืออะไร? เมทริกซ์ไม่มีอะไรมากไปกว่าตารางสี่เหลี่ยมที่สามารถเติมข้อมูลได้ กล่าวอีกนัยหนึ่ง มันเป็นอาร์เรย์สองมิติ อย่างที่คุณทราบ อาร์เรย์ใน Java เป็นวัตถุ อาร์เรย์ หนึ่งมิติมาตรฐานintมีลักษณะดังนี้:

int [] array = {12, 32, 43, 54, 15, 36, 67, 28};
เราสามารถนึกภาพได้ดังนี้
0 1 2 3 4 5 6 7
12 32 43 54 15 36 67 28
แถวบนสุดระบุที่อยู่ของเซลล์ กล่าวอีกนัยหนึ่ง ในการรับหมายเลข 67 คุณต้องเข้าถึงองค์ประกอบอาร์เรย์ด้วยดัชนี 6:

int number = array[6];
ทุกอย่างง่ายมาก อาร์เรย์สองมิติคืออาร์เรย์ของอาร์เรย์หนึ่งมิติ หากคุณเพิ่งได้ยินเรื่องนี้เป็นครั้งแรก ให้หยุดและจินตนาการในหัวของคุณ อาร์เรย์สองมิติมีลักษณะดังนี้:
0 อาร์เรย์หนึ่งมิติ อาร์เรย์หนึ่งมิติ
1 อาร์เรย์หนึ่งมิติ
2 อาร์เรย์หนึ่งมิติ
3 อาร์เรย์หนึ่งมิติ
4 อาร์เรย์หนึ่งมิติ
5 อาร์เรย์หนึ่งมิติ
6 อาร์เรย์หนึ่งมิติ
7 อาร์เรย์หนึ่งมิติ
ในรหัส:

int [][] matrix = {
{65, 99, 87, 90, 156, 75, 98, 78}, {76, 15, 76, 91, 66, 90, 15, 77}, {65, 96, 17, 25, 36, 75, 54, 78}, {59, 45, 68, 14, 57, 1, 9, 63}, {81, 74, 47, 52, 42, 785, 56, 96}, {66, 74, 58, 16, 98, 140, 55, 77}, {120, 99, 13, 90, 78, 98, 14, 78}, {20, 18, 74, 91, 96, 104, 105, 77} }
0 0 1 2 3 4 5 6 7
65 99 87 90 156 75 98 78
1 0 1 2 3 4 5 6 7
76 15 76 91 66 90 15 77
2 0 1 2 3 4 5 6 7
65 96 17 25 36 75 54 78
3 0 1 2 3 4 5 6 7
59 45 68 14 57 1 9 63
4 0 1 2 3 4 5 6 7
81 74 47 52 42 785 56 96
5 0 1 2 3 4 5 6 7
66 74 58 16 98 140 55 77
6 0 1 2 3 4 5 6 7
120 99 13 90 78 98 14 78
7 0 1 2 3 4 5 6 7
20 18 74 91 96 104 105 77
ในการรับค่า 47 คุณต้องอ้างอิงองค์ประกอบเมทริกซ์ที่ [4][2]

int number = matrix[4][2];
คุณอาจสังเกตเห็นว่าพิกัดเมทริกซ์แตกต่างจากระบบพิกัดสี่เหลี่ยมแบบดั้งเดิม (ระบบพิกัดคาร์ทีเซียน) เมื่อคุณเข้าถึงเมทริกซ์ คุณต้องระบุพิกัด y ก่อนแล้วจึงระบุพิกัด x ในวิชาคณิตศาสตร์ เป็นเรื่องปกติที่จะต้องระบุพิกัด x ก่อน นั่นคือ (x, y) คุณอาจสงสัยว่า: "ทำไมคุณไม่หมุนการแทนเมทริกซ์ของคุณแล้วเข้าถึงองค์ประกอบด้วยวิธีปกติโดยใช้ (x, y) การทำเช่นนี้จะไม่เปลี่ยนเนื้อหาของเมทริกซ์" ใช่ ไม่มีอะไรจะเปลี่ยนแปลง แต่ในโลกของการเขียนโปรแกรม วิธีปฏิบัติที่เป็นที่ยอมรับคือการเข้าถึงเมทริกซ์ "ก่อนโดย y จากนั้นตามด้วย x" คุณควรยอมรับว่าเป็นวิธีที่เหมาะสม ตอนนี้เรามาพูดถึงการฉายเมทริกซ์ไปยังเครื่องยนต์ของเรา (Gameระดับ). ดังที่คุณทราบ เครื่องยนต์มีวิธีการมากมายที่เปลี่ยนเซลล์ของสนามเด็กเล่นที่พิกัดเฉพาะ ตัวอย่างเช่นsetCellValue(int x, int y, String value)วิธีการ มันตั้งค่าเซลล์เฉพาะที่มีพิกัด (x, y) เท่ากับพารามิเตอร์ค่า คุณอาจสังเกตเห็นว่าวิธีนี้ใช้ x ก่อน เช่นเดียวกับในระบบพิกัดแบบดั้งเดิม วิธีการอื่นๆ ของเครื่องยนต์ทำงานในลักษณะเดียวกัน เมื่อพัฒนาเกม มักจะจำเป็นต้องสร้างสถานะของเมทริกซ์บนหน้าจอขึ้นมาใหม่ เราจะทำอย่างนั้นได้อย่างไร? ขั้นแรก คุณต้องวนซ้ำองค์ประกอบเมทริกซ์ทั้งหมดในลูป ประการที่สอง เรียกใช้วิธีการแสดงผลสำหรับแต่ละรายการ โดยใช้พิกัดย้อนกลับ ตัวอย่างเช่น:

private void drawScene() {
    for (int i = 0; i < matrix.length; i++) {
        for (int j = 0; j < matrix[i].length; j++) {
            setCellValue(j, i, String.valueOf(matrix[i][j]));
        }
    }
}
โดยธรรมชาติแล้ว การกลับตัวจะทำงานทั้งสองทิศทาง คุณสามารถส่ง (i, j) ไปยังsetCellValueเมธอดและรับองค์ประกอบ [j][i] จากเมทริกซ์ได้พร้อมกัน การกลับพิกัดอาจดูยากเล็กน้อย แต่คุณต้องจำให้ได้ และทุกครั้ง หากคุณพบปัญหาใดๆ คุณควรหยิบกระดาษและปากกา วาดเมทริกซ์ และสร้างกระบวนการที่เกี่ยวข้องกับเมทริกซ์ขึ้นมาใหม่

5. ตัวเลขสุ่ม

คุณทำงานกับเครื่องสร้างตัวเลขสุ่มได้อย่างไร คลาสGameกำหนดgetRandomNumber(int)วิธีการ ภายใต้ประทุน จะใช้Randomคลาสจากแพ็คเกจ java.util แต่วิธีที่คุณทำงานกับตัวสร้างตัวเลขสุ่มจะไม่เปลี่ยนแปลง getRandomNumber(int)ใช้จำนวนเต็มเป็นอาร์กิวเมนต์ ตัวเลขนี้จะเป็นขีดจำกัดสูงสุดของสิ่งที่ตัวสร้างสามารถส่งคืนได้ ขีดจำกัดล่างคือ 0 สำคัญ! เครื่องกำเนิดจะไม่ส่งคืนจำนวนขีดจำกัดบน ตัวอย่างเช่น ถ้าคุณเรียกgetRandomNumber(3)มันจะสุ่มกลับเป็น 0, 1 หรือ 2 อย่างที่คุณเห็น มันไม่สามารถคืนค่าเป็น 3 ได้ การใช้ตัวสร้างด้วยวิธีนี้ค่อนข้างง่าย แต่มีประสิทธิภาพสูงในหลายกรณี สมมติว่าคุณต้องการตัวเลขสุ่มในบางช่วง: สมมติว่าคุณต้องการตัวเลขสามหลักในช่วง [100..999] ดังที่คุณทราบแล้ว จำนวนขั้นต่ำที่ส่งคืนคือ 0 ดังนั้นคุณจะต้องเพิ่ม 100 แต่ในกรณีนี้ คุณต้องดูแลไม่ให้เกินขีดจำกัดบน หากต้องการรับ 999 เป็นค่าสุ่มสูงสุด ให้โทรหาgetRandomNumber(int)วิธีการที่มีอาร์กิวเมนต์ 1,000 แต่ตอนนี้เราจำได้ว่าเรากำลังเพิ่ม 100 ให้กับผลลัพธ์ ซึ่งหมายความว่าขอบเขตบนควรลดลง 100 กล่าวอีกนัยหนึ่ง โค้ดสำหรับรับตัวเลขสามหลักแบบสุ่มของเราจะมีลักษณะดังนี้ :

int number = 100 + getRandomNumber(900);
แต่เพื่อทำให้ขั้นตอนนี้ง่ายขึ้น กลไกจัดการจะจัดเตรียมgetRandomNumber(int, int)วิธีการที่พารามิเตอร์ตัวแรกเป็นจำนวนขั้นต่ำที่จะส่งคืน เมื่อใช้วิธีนี้ ตัวอย่างก่อนหน้านี้สามารถเขียนใหม่ได้ดังนี้:

int number = getRandomNumber(100, 1000);
สามารถใช้ตัวเลขสุ่มเพื่อรับองค์ประกอบอาร์เรย์แบบสุ่ม:

String [] names = {"Sarah", "Val", "Sergey"};
String randomName = names[getRandomNumber(names.length)]
สร้างเหตุการณ์บางอย่างด้วยความน่าจะเป็น สำหรับมนุษย์ ตอนเช้าเริ่มต้นด้วยสถานการณ์ที่เป็นไปได้สองสามอย่าง: นอนเกิน – มีโอกาส 50%; ตื่นตรงเวลา – โอกาส 40%; ตื่นเช้า 1 ชั่วโมง - โอกาส 10% ลองนึกภาพว่าคุณกำลังเขียนโปรแกรมสร้างผลลัพธ์ในตอนเช้า คุณต้องสร้างเหตุการณ์ที่มีความน่าจะเป็น ในการทำเช่นนี้ คุณต้องใช้ตัวสร้างตัวเลขสุ่มอีกครั้ง การใช้งานที่แตกต่างกันเป็นไปได้ แต่วิธีที่ง่ายที่สุดควรขึ้นอยู่กับอัลกอริทึมต่อไปนี้:
  1. กำหนดขีด จำกัด ที่ใช้ในการสร้างตัวเลข
  2. สร้างตัวเลขสุ่ม
  3. ประมวลผลหมายเลขที่ได้รับ
ในกรณีนี้ สูงสุดจะเป็น 10 โทรgetRandomNumber(10)วิธีการและวิเคราะห์ว่าเราสามารถกลับมาได้ สามารถส่งคืนตัวเลข 10 ตัว (ตั้งแต่ 0 ถึง 9) โดยแต่ละตัวมีความน่าจะเป็นเท่ากัน — 10% ตอนนี้เราต้องรวมผลลัพธ์ที่เป็นไปได้ทั้งหมดและจับคู่กับเหตุการณ์ที่เป็นไปได้ของเรา จินตนาการของคุณอาจนึกถึงชุดค่าผสมต่างๆ ที่เป็นไปได้มากมาย แต่ที่เห็นชัดเจนที่สุดคือ "หากตัวเลขสุ่มอยู่ในช่วง [0..4] เราจะมีเหตุการณ์ "นอนเกิน" หากตัวเลขอยู่ในช่วง [5 ..8], เรามีเหตุการณ์ "ตื่นตรงเวลา" และถ้าเลขเป็น 9 เราก็มีกิจกรรม "ตื่นก่อนเวลาหนึ่งชั่วโมง" ง่ายมาก มีตัวเลข 5 ตัวอยู่ในช่วง [0 ..4] ซึ่งแต่ละค่าอาจส่งคืนด้วยความน่าจะเป็น 10% รวมเป็น 50% มีตัวเลข 4 ตัวในช่วง [5..8] และ 9 เป็นเพียงตัวเลขเดียวที่ปรากฏพร้อมกับ ความน่าจะเป็น 10%

int randomNumber = getRandomNumber(10);
if (randomNumber < 5) {
    System.out.println("Overslept");
} else if (randomNumber < 9) {
    System.out.println("Woke up on time");
} else {
    System.out.println("Woke up an hour early");
}
โดยทั่วไป มีวิธีมากมายในการใช้ตัวเลขสุ่ม คุณถูกจำกัดด้วยจินตนาการของคุณเท่านั้น แต่จะใช้อย่างมีประสิทธิภาพมากที่สุดหากคุณต้องการผลลัพธ์ซ้ำ ๆ จากนั้นผลลัพธ์ใหม่จะแตกต่างจากผลลัพธ์ก่อนหน้า ด้วยความน่าจะเป็นแน่นอน นั่นคือทั้งหมดที่สำหรับตอนนี้! หากคุณต้องการเรียนรู้เพิ่มเติมเกี่ยวกับส่วน "เกม" ต่อไปนี้เป็นเอกสารที่มีประโยชน์ซึ่งสามารถช่วยได้:
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION