[Project Solution] Queue … step by step

บทความนี้เป็นบทความเก่า ย้ายบล๊อกมาจาก nartra.blogspot.com

Queue

ต้องการสร้างโปรแกรมสำหรับจำลองการเข้าแถวจ่ายเงินที่แคชเชียร์ เช่นตามซุปเปอร์มาร์เก็ตโดยมีกฎว่า

  1.  จะมีแคชเชียร์หลักอยู่ 2 อันเสมอ
  2. เวลาลูกค้าเดินมาถึงแคชเชียร์ (เพื่อจะจ่ายตังค์อ่ะนะ) ลูกค้าจะเลือกเข้าแถวที่สั้นที่สุด .. ถ้ามีแถวที่สั้นที่สุดหลายแถว (เช่น แถว 1 มีคนต่อแถวอยู่ 3 คน, แถว 2 มีคนต่อแถวอยู่ 3 คนเท่านั้นเลย จะเลือกเข้าแถวที่เลขน้อยกว่า ในกรณีนี้คือแถว 1 นะ)
  3. แคชเชียร์แต่ละอัน รับลูกค้าได้อย่างมากสุดแค่ 5 คน
  4. ถ้าลูกค้าเข้ามาเพิ่ม และแคชเชียร์ทุกตัวที่มีอยู่ในตอนนี้เต็มหมดแล้ว (ทุกแถวมี 5 คนเต็มเอี้ยด) จะมีการสร้างแถวแคชเชียร์ใหม่เพิ่มเข้ามาอีก 1 แถว
  5. ถ้าแคชเชียร์คิดเงินลูกค้าเสร็จแล้วจะทำการลบลูกค้าออกจากหัวแถวไป .. ในกรณีนี้มีโอกาสที่แคชเชียร์ช่องนึงจะลบลูกค้าออกจากแถวไปจนไม่เหลือลูกค้าในแถวเลย เรียกว่ากลายเป็นแถวว่างกันเลยทีเดียว
  6. ถ้าแคชเชียร์ลบลูกค้าออกไปจนกลายเป็นแถวว่าง และในตอนนั้นมีแถวว่างรวมทั้งหมดเกิน 3 แถว (รวมตัวมันเองที่เพิ่งจะว่างด้วย) .. แคชเชียร์ตัวที่เพิ่งจะว่างล่าสุดอ่ะ จะถูกลบทิ้งออกไป หายไปเลย
  7. แต่ไม่ว่าจะยังไง ก็ห้ามลบแถวให้เหลือน้อยกว่า 2 (กลับไปดูข้อ 1)

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

AddCustomer(10)
 0,1
 AddCustomer(2)
 AddCustomer(3)
 1,3
 0,4

  • คำสั่ง AddCustomer(n) ใช้สำหรับบอกว่ามีลูกค้าเดินเข้ามาใหม่ n คน
  • m,n ใช่สำหรับบอกว่า แคชเชียร์ตัวที่ m คิดเงินลูกค้าเสร็จแล้ว (และลบลูกค้าหัวแถวออกไป) จำนวนเท่ากัน n คน

ซึ่งคำสั่งจำลองเหตุการณ์พวกนี้อ่ะนะ ถ้าเอาไปรันแล้วจะให้ผลแบบนี้

POS 0 | 1 3 5 7 9
 POS 1 | 2 4 6 8 10
 =======================
 POS 0 | 3 5 7 9
 POS 1 | 2 4 6 8 10
 =======================
 POS 0 | 3 5 7 9 11
 POS 1 | 2 4 6 8 10
 POS 2 | 12
 =======================
 POS 0 | 3 5 7 9 11
 POS 1 | 2 4 6 8 10
 POS 2 | 12 13 14 15
 =======================
 POS 0 | 3 5 7 9 11
 POS 1 | 8 10
 POS 2 | 12 13 14 15
 =======================
 POS 0 | 11
 POS 1 | 8 10
 POS 2 | 12 13 14 15
 =======================

POS แทนแคชเชียร์ เบอร์ 0, 1, 2, .. ไปเรื่อยๆ
ซึ่งผลลัพท์จะแสดงสถานะของแคชเชียร์ทุกตัวที่มีอยู่ในตอนนั้นในแต่ละรอบ พร้อมจำนวนลูกค้าที่เข้าแถวอยู่
ลูกค้าจะแทนด้วย ตัวเลข อ่ะนะ คนที่หนึ่งก็เป็นเลข 1, คนต่อไปก็ 2 3 4 .. ไปเรื่อยๆ

หลักการ

คิว หรือ ที่ตำราไทยแปลว่า "แถวคอย"

คิวเป็น Data Structure ประเภทหนึ่ง ไม่ต้องอธิบายให้มากนักกับคิวเพราะเราเจอมันในชีวิตจริงอยู่แล้ว

เข้าแถวๆๆๆ

หลักการก็คือใครมาก่อน ก็ออกไปก่อน ใครมาหลักก็ออกไปที่หลัง ไม่ยากเลย หรือที่เราเรียกอีกแบบว่า FIFO (First-In, First-Out) ง๊ายง่าย

ถ้าพูดถึงสิ่งที่คิวน่าจะทำได้ก็คงมีจะมีประมาณ

  • ใส่คนเพิ่มเข้าไป
  • ถึงคนหัวแถวออกมา
  • เช็กดูได้ว่าตอนนี้มีแถวมีกี่คน
  • เช็กว่าแถวนี้เต็มรึยัง (ตามโจทย์ข้อนี้ ต้องมีความสามารถนี้ด้วย)

ซึ่งถ้าเขียนเป็น code ก็จะได้ประมาณนี้

public class Queue {
    public static final int MAX = 5;
    private ArrayList<Integer> q = new ArrayList<Integer>();
    
    public boolean enqueue(int n) {...}

    public int dequeue() {...}

    public int size() {...}

    public boolean avairable() {...}
}

ก็คือมี enqueue (เพิ่มคนเข้าไป), dequeue (ดึงหัวแถวออกมา), size (ถามขนาดว่าตอนนี้มีกี่คน), avairable (เช็กว่าใส่คนเข้าไปเพิ่มได้มั้ย ถ้าตอนนี้มีคนอยู่ 5 คนก็จะใส่ไม่ได้ไรเงี้ยอ่ะนะ)

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

ส่วนการเพิ่มคนเข้าไปวิธีการทำก็คือรันคนใหม่ไป (เป็นหมายเลข Integer อ่ะนะ) แต่รับไปแล้วก็เช็กก่อนว่าตอนนี้คิวเรามันเต็มไปแล้วรึเปล่า ถ้าไม่เต็มก็ .add เข้าไปใน ArrayList ตัวเมื่อกี้นะ แต่ถ้ามันล้นแล้วก็อย่าใส่เข้าไป
ป.ล.จริงๆ method นี้สามารถเขียนแบบ void ก็ได้ แต่ในที่นี้จะใช้ boolean เพื่อส่งค่าตอบกลับด้วยว่ามันใส่เข้าไปในคิวได้รึเปล่า

public boolean enqueue(int n) {
    if (q.size() < MAX) {
        q.add(n);
        return true;
    }
    else {
        return false;
    }
} 

ต่อไปคือการดึงคนออกมาจากหัวแถว ก็เช็กก่อนว่าตอนนี้มีคนอยู่ในแถวม๊ะ (มีคนให้ดึงออกมารึเปล่านั่นแหละ) ถ้ามีก็ดึงออกมาแล้วลบข้อมูลตำแหน่งที่ 0 ซึ่งเป็นตำแหน่งหัวแถวทิ้งไป (ก็คนถูกดึงออกไปแล้วอ่ะนะ)

public int dequeue() {
    if (q.size() > 0) {
        int result = q.get(0);
        q.remove(0);
        return result;
    }
    else {
        return -1;
    }
}

ต่อไปคือการถามว่าตอนนี้มีคนกี่คนในแถว ก็ไม่ยากเลย ใน ArrayList เรามีอยู่เท่าไหร่ก็เท่านั้นแหละ

public int size() {
    return q.size();
}

ส่วนตัว avairable คือการเช็กว่าคิวนี้เหลือที่มั้ย ดังนั้นถ้าจำนวนคนใน ArrayList เรามันน้อยกว่าจำนวนมากสุดที่รับได้ก็ถือว่ามันยังว่างอยู่ ใส่คนเพิ่มมาได้เลยนะถ้าอยากใส่

public boolean avairable() {
    return q.size() < MAX;
}

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

public void display() {
    System.out.print("POS " + serial_number + " | ");
    for (int i = 0; i < q.size(); i++) {
        System.out.print(q.get(i) + " ");
    }
    System.out.println();
} 

กลับมาที่ main

อ่านคำสั่งว่าต้องทำอะไรบ้างจาก text file

เพราะว่าคำสั่งของเราอยู่ใน text file เราเลยต้องอ่านคำสั่งพวกนั้นมาก่อน ซึ่งถ้าจะทำให้ง่ายก็ควรอ่านมาแล้วสร้างเป็น array ของ String ไปเลย จะได้เอาไปใช้ต่อได้ง่าย
ก็จัดการสร้าง method ใน class หลักที่จะใช้เรียกซะ

String[] readfile(String filename) {
    String[] result;
    try {
        Scanner scan = new Scanner(new FileReader(filename));
        ArrayList<String> readtext = new ArrayList<String>();
        while (scan.hasNextLine()) {
            readtext.add(scan.nextLine());
        }
        result = new String[readtext.size()];
        result = readtext.toArray(result);
    }
    catch (Exception e) {
        result = new String[0];
    }
    return result;
}
ป.ล.สำหรับ class อะไรที่เรียกมาใช้ ตัวไหนต้องสั่ง import จัดการสั่งด้วยนะ
หลักการอ่านไฟล์ไม่มีอะไรมาก (ส่วนใหญ่ไม่ว่าจะเขียนกี่ครั้งมันก็ฟอร์มเดิมๆ นั่นแหละ) อันนี้เป็นโค้ดสำเร็จ เราจะไม่พูดถึงมันมากเพราะประเด็นของเรื่องนี้อยู่ที่คิวเป็นหลัก

ทำการประมวลผลคำสั่งว่ามันเป็น enqueue หรือ dequeue

พอเริ่มปุ๊บ สิ่งที่ต้องทำก็คืออ่านคำสั่งมาก่อน แล้วเก็บไว้ในตัวแปร array ของ String
String[] commands = readfile("index.txt");
ซึ่งจากคำสั่งใน input.txt ตามตัวอย่างข้างบนก็จะได้ว่า commands ที่เราสร้างไปเมื่อกี้เก็บค่าเป็น
commands[0]เก็บค่า: AddCustomer(10)
 commands[1]เก็บค่า: 0,1
 commands[2]เก็บค่า: AddCustomer(2)
 commands[3]เก็บค่า: AddCustomer(3)
 commands[4]เก็บค่า: 1,3
 commands[5]เก็บค่า: 0,4
ซึ่งพอมันเป็น array แล้วก็เอาไปวนลูปได้อย่างง่ายดายกว่ามาอ่านไฟล์
แต่แค่เป็น String มาเราก็ดูไม่ออกว่ามันเป็นแบบไหน ก็สร้าง method เพิ่มมาอีกตัวเพื่อช่วยดูว่า type ของ commands[i] นี้น่ะมันเป็นแบบไหนกันแน่
int UNKNOWN = 0, ENQUEUE = 1, DEQUEUE = 2;

int typeOfCommand(String str) {
    str = str.trim();
    String enqueue_format = "^(AddCustomer)\\([0-9]+\\)$";
    String dequeue_format = "^([0-9]+)(,)([0-9]+)$";

    Pattern pattern;
    Matcher matcher;

    pattern = Pattern.compile(enqueue_format);
    matcher = pattern.matcher(str);
    if (matcher.find()) {
      return ENQUEUE;
    }

    pattern = Pattern.compile(dequeue_format);
    matcher = pattern.matcher(str);
    if (matcher.find()) {
      return DEQUEUE;
    }

    return UNKNOWN;
}
เนื่องจาก 0, 1, 2  มันอ่านไม่รู้เรื่องว่ามันคือ type อะไร เลยขอกำหนดค่าเป็น UNKNOWN = 0, ENQUEUE = 1, DEQUEUE = 2 แทนเพื่อความอ่านง่าย
 
ส่วนวิธีเช็กว่ามันเป็นฟอร์มของ AddCustomer(10)หรือ 0,1 ก็ทำได้หลายวิธี แต่ที่จะเขียนให้ดูเป็นวิธีการที่ใช้ Regular Expression ในการเช็ก ซึ่งรูปแบบของการเขียน regexpฯ นั้นถ้าอยากรู้ลอง google ดูเอาเอง
enqueue_format = "^(AddCustomer)\\([0-9]+\\)$";

dequeue_format = "^([0-9]+)(,)([0-9]+)$";
อธิบายคร่าวๆ สำหรับรูปแบบ enqueue เราบอกว่าถ้ามันขึ้นต้นด้วยคำว่า AddCustomer( แล้วตามตัวตัวเลข 0-9 กี่ตัวก็ได้ แล้วจบด้วย ) เราจะถึงว่าเป็นฟอร์มนี้
ส่วนแบบรูปแบบ dequeue เราบอกว่าถ้ามันขึ้นต้นด้วย ตัวตัวเลข 0-9 กี่ตัวก็ได้ คั่นด้วย , ก่อนจะจบด้วยตัวตัวเลข 0-9 กี่ตัวก็ได้อีกทีก็เข้าทาง
matcher = pattern.matcher(str)
แล้วก็เช็กว่ามันเป็นฟอร์มที่เราจะเอารึเปล่าด้วย matcher แล้วก็รีเทิร์นกลับเป็น

UNKNOWN, ENQUEUE, DEQUEUE แล้วแต่ว่าตรงกับรูปแบบไหน

ประกาศค่าตัวแปรที่จะต้องใช้กันสักหน่อย

private static int order_of_queue = 0;
private ArrayList<Queue> cashiers = new ArrayList<Queue>();
เราต้องสร้างแคชเชียร์ขึ้นมาก่อน ซึ่งมันก็มีหลายตัวได้ และจำนวนไม่แน่นอน เดี๋ยวเพิ่มเดี๋ยวลดตามจำนวนลูกค้าในตอนนั้น (ก็ใช้ ArrayList อีกล่ะ) ซึ่งแคชเชียร์แต่ละตัวก็เป็น Queue แบบที่เราสร้าง class ไปข้างบนโน้น
แต่ก็ต้องมีตัวแปรที่เอามานับด้วยว่าตอนนี้แคชเชียร์มันสร้างไปถึงไหนแล้วด้วย  order_of_queue

แล้วก็มาถึงการเขียน main

เริ่มแรก ก็กำหนดขึ้นมาก่อนเลย
class Main{
     private static int order_of_queue = 0;
     private ArrayList<Queue> cashiers = new ArrayList<Queue>();
     private static String[] readfile(String filename) {...}
     private static int UNKNOWN = 0, ENQUEUE = 1, DEQUEUE = 2;
     private static int typeOfCommand(String str) {...}
 
     public static void main(String[] args){
         int customer_no = 1;
         //เดี๋ยวทำต่อตรงนี้นะ
     }
}
ถือว่าลูกค้าคนแรกจะเป็นหมายเลข 1 นะ
แต่ตามโจทย์ยังบอกอีกว่าอย่างน้อยที่สุดเราต้องมีแคชเชียร์ทั้งหมด 2 ตัวเป็นค่าเริ่มต้น
//สร้างคิวแรก
 cashiers.add(new Queue(order_of_queue++));
//สร้างคิวที่สอง
 cashiers.add(new Queue(order_of_queue++));
สร้างคิวตัวใหม่ขึ้นมา 2 ตัวเลย แต่คิว (แคชเชียร์) แต่ละตัวนั้นต้องมีหมายเลขประจำตัวด้วยก็ใส่ลงไป
แต่ถ้าใส่แบบนี้เราต้องไปแก้โค้ดคิวให้มันมี constructure ด้วยแบบนี้
public int serial_number;public Queue(int serialNumbar) {
    serial_number = serialNumbar;
}
แล้วเราก็จัดการวนลูปคำสั่งที่อ่านมาแล้วก็ใช้ typeOfCommand ตัวนี้ที่เมื่อกี้เขียนมาเพื่อเช็กว่ามันเป็น ENQUEUE หรือ DEQUEUE แล้วก็ switch ซะ
for (i = 0; i < copmmands.length; i++) {
    switch (typeOfCommand(copmmands[i])) {
        case ENQUEUE:            
          //มีการเพิ่มลูกค้ามาใหม่
          break;
        case DEQUEUE:
          //ลบลูกค้าออกไปจากแถว
          break;
    }
}

enqueue

ส่วนเมื่อเรามีการเพิ่มลูกค้ามาใหม่เราต้องอ่านมาให้ได้ก่อนว่าต้องเพิ่มลูกค้ากี่คน ซึ่งก็ดูจาก AddCustomer(10) ตัวนี้ อยากได้เลข 10 มาต้องทำไงล่ะ?
ก็ตัด AddCustomer( และ ) ทิ้งไปก็จะได้ค่า n ว่ามีลูกค้าเพิ่มมากี่คนแล้ว
หลังจากนั้นก็วนลูปตามจำนวน n (โค้ดข้างล่าง ลูปที่ใช้ c เป็นตัวนับ)
 
หลังจากนั้นก็ต้องหาว่าตำแหน่งที่เราจะ enqueue ต่อไปได้คือตรงไหน เพราะตามกฎข้อที่ 2 ซึ่งกล่าวไว้ว่าลูกค้าจะเลือกเข้าแถวที่สั้นที่สุดเสมอ เราจึงต้องสร้าง position_to_enqueue ขึ้นมา แล้วไปวนลูปทุกตัวใน cashiers ว่าแถวไหนที่สั้นที่สุด (ด้วยลูปที่ใช้ j เป็นตัวนับ)
แต่ทว่า..! หาแถวสั้นที่สุดอย่างเดียวก็ยังไม่พอนะ
เพราะบางทีแถวแคชเชียร์ที่มีอยู่ตอนนี้มันอาจจะไม่ว่างเลยสักแถวไง คือมีกี่แคชเชียร์เต็มหมดเลย (แปลว่าเรา add เข้าคิวไม่ได้นะ)
ดังนั้นเราต้องสร้างคิวตัวใหม่ขึ้นมาในกรณีนี้ด้วยนะ
int n = Integer.parseInt(copmmands[i].replace("AddCustomer(", "").replace(")", ""));
for (c = 0; c < n; c++) {
    int position_to_enqueue = 0;
    for (j = 0; j < cashiers.size(); j++) {
        if (cashiers.get(j).size() < cashiers.get(position_to_enqueue).size() && cashiers.get(j).avairable()) {
            position_to_enqueue = j;
        }
    }
    if (!cashiers.get(position_to_enqueue).enqueue(customer_no)) {
       cashiers.add(new Queue(order_of_queue++));
       cashiers.get(cashiers.size() - 1).enqueue(customer_no);
    }
    customer_no++;
}
enqueue(customer_no) คือการเพิ่มลูกค้าคนที่ customer_no เข้าไปในคิวตัวที่ position_to_enqueue ซึ่งเป็นตำแหน่งที่หามาแล้วว่ามันสั้นสุดแน่ๆ แต่อย่างที่บอกไปในตอนแรกว่า class Queue ของเรามี .enqueue สำหรับการยัดลูกค้าคนใหม่เข้าคิว แล้วมันจะ return true หรือ false กลับมาเพื่อแสดงว่ามันใส่คิวไปได้มั้ย?
ถ้ามันใส่ไม่ได้แสดงว่าคิวเต็ม!
แต่ตำแหน่ง position_to_enqueue มันคือตำแหน่งที่แถวสั้นที่สุดแล้วนะ? ใช่แล้ว..แปลว่าแม้แต่ตำแหน่งที่แถวคิวมีลูกค้าต่อสั้นที่สุดก็เต็มแล้ว เราเลยต้องสร้างแถวใหม่ไงล่ะ
ถ้ายังงงอยู่มาค่อยๆ คิด
if( enqueue ไม่ได้ ){
 สร้างแถวใหม่
}
มันก็คือ
if( ! cashiers.get(position_to_enqueue).enqueue(customer_no)){
 cashiers.add(new Queue(order_of_queue++));
}
แต่อย่าลืมนะว่าสร้างแถวใหม่ปุ๊บ เราก็ต้องเอาลูกค้าคนล่าสุดใส่แถวใหม่ไปด้วย
cashiers.get(cashiers.size() - 1).enqueue(customer_no);
ป.ล. แถวสุดท้าย ก็คือ cashiers ตัวที่ cashiers.size() - 1 นั่นเอง

dequeue

ส่วนการลบลูกค้าออกไป (ประมาณว่าเมื่อคิดเงินเสร็แล้วอ่ะ) ก็ทำคล้ายกัน คือต้องตัดตัวเลข 0,1 ออกมาเป็น 0 กับ 1 เสียก่อน
ตัวอย่างโค้ดนี้ใช้คำสั่ง .split ด้วยตัวอักษร ,
เราก็จะได้ pos (แคชเชียร์ที่จะลบลูกค้าออก) กับ n (จำนวนลูกค้าที่จะลบออกไป)
String[] pos_and_n = cmd[i].split(",");
pos = Integer.parseInt(pos_and_n[0]);
n = Integer.parseInt(pos_and_n[1]);
for (j = 0; j < cashiers.size(); j++) {
 if (cashiers.get(j).serial_number == pos) {
 for (k = 0; k < n; k++) {
  cashiers.get(j).dequeue();
 }
 //removeEmptyQueue(j);
 }
}
แล้วก็วนลูปเพื่อหาว่าแคชเชียร์ตัวไหนที่มี serial_number หมายเลขประจำตัวตรงกับที่เราจะลบ
พอเจอแล้วก็ลูปย่อยอีกที (เพราะต้องสั่ง dequeue ตามจำนวน n)
ตบท้ายด้วยการเช็กดูว่าตอนนี้มีคิวว่างเกิน 2 ตัวรึเปล่า (ต้องลบทิ้งตามกฎข้อ 6)
int empty = 0;
for (i = 0; i < cashiers.size(); i++) {
 if( cashiers.get(i).size() == 0 ){
  empty++;
 }
}
if (empty > REMOVE_EMPTY_N && cashiers.size() > MIN_CASHIER) {
 cashiers.remove(j); //jก็คือตำแหน่งแคชเชียร์สุดท้ายที่ลบลูกค้าออก
}
วิธีเช็กก็สร้างตัวนับ empty ขึ้นมาก่อน แล้วก็ลูปทุกตัวใน cashiers เพื่อนับว่าตัวไหนที่มี size เท่ากับ 0 บ้าง (empty++ ไปเรื่อยๆ ถ้าเจอนะ)
แล้วพอนับเสร็จเงื่อนไขที่เราจะลบแคชเชียร์ตัวที่ j (ต่อเนื่องจากโค้ดข้างบน เราลบลูกค้าที่แถวตำแหน่ง j .. ดังนั้นถ้ามันมีแถวว่างเกิน 2 ตำแหน่ง j นั่นแหละที่จะโดนลบออก) ก็คือ
  • จำนวนแถวว่างมากกว่า REMOVE_EMPTY_N (ในกรณีนี้คือ 2)
  • จำนวนแคชเชียร์ในตอนนี้มากกว่าจำนวนน้อยสุด MIN_CASHIER ที่โจทย์อนุญาต(ในกรณีนี้คือ 2 อีกเหมือนกัน)
ก็ใส่ if ไป ถ้าใช่ก็ remove ตัวที่ j ทิ้ง
แล้วพอทำทุกอย่างจบ กลับไปที่นี่นิดส์นึง
for (i = 0; i < copmmands.length; i++) {
  switch (typeOfCommand(copmmands[i])) {
    //นั่นแหละ
  }
}
for ใหญ่สุดตอนแรกเลย เมื่อจบการทำคำสั่งแต่ละรอบเราจำเป็นต้องแสดงให้เขาเห็นด้วยว่าแคชเชียร์แต่ละตัวตอนนี้มีลูกค้าอยู่กี่คน

โดยการเติม

for (j = 0; j < cashiers.size(); j++) {
  cashiers.get(j).display();
}
System.out.println("=======================");
ลงไปหลังจาก switch ก่อนจบ for มันก็จะวนลูป display ข้อมูลในคิวทุกตัวทุกรอบ
 
เย้!

ถือจบทุกอย่าง เรียบร้อย ดูไม่ยากเนอะ (แค่เยอะ) 555

* ขอไม่รวม code ให้ละกัน ลองอ่านตามดูแล้วทำไปเรื่อยๆ step by step

704 Total Views 3 Views Today
Ta

Ta

สิ่งมีชีวิตตัวอ้วนๆ กลมๆ เคลื่อนที่ไปไหนโดยการกลิ้ง .. ถนัดการดำรงชีวิตโดยไม่โดนแสงแดด
ปัจจุบันเป็น Senior Software Engineer อยู่ที่ Centrillion Technology
งานอดิเรกคือ เขียนโปรแกรม อ่านหนังสือ เขียนบทความ วาดรูป และ เล่นแบดมินตัน

You may also like...

ใส่ความเห็น

อีเมลของคุณจะไม่แสดงให้คนอื่นเห็น ช่องที่ต้องการถูกทำเครื่องหมาย *