บันทึกเข้าค่ายยุวคอมที่โรงเรียนสตรีศรีสุริโยทัย

ก็เกริ่นก่อนค่ายยุวคอมเนี่ยเป็นค่ายที่จัดมา 8 ปีแล้วมั้ง เป็นค่ายคอมค่ายแรกที่ผมได้ไปเข้าเลย สมัยผมเข้ายังสอน Delphi อยู่เลย แต่เมื่อประมาณ 2 ปีที่แล้วเปลี่ยนมาสอน C# โดยมากค่ายนี้จัดขึ้นช่วงเดือนตุลาคม ปีนี้คือ 1-5 ตุลาคม แต่ก็แล้วแต่ศูนย์ที่จัดด้วยครับ ปีนี้(และคิดว่าทุกๆปี)ผมจะเข้าไปเป็นพี่เลี้ยงของค่ายที่จัดที่โรงเรียน สตรีศรีสุริโยทัยครับ ปีนี้ผมเข้าไปช่วงเย็นของวันที่ 4 ตุลาคม(เกือบวันสุดท้าย) เพื่อไปช่วยน้องเค้าทำโปรเจคครับ ขอบอกตามตรงเลยว่าโปรเจคปีนี้ของน้องค่ายไม่ค่อยน่าสนใจส่วนมากเป็นแค่คลิกๆ แล้วแสดง กอปข้อมูลในเน็ตมาแปะๆ มันเลยดูไม่ค่อยน่าสนใจเท่าไหร่ แต่บางกลุ่มก็ทำยากเว่อร์เลย อย่างโปรแกรมจองตั๋วภาพยนต์ที่ออกแบบไว้หรูมาก แต่ทำตามจริงไม่ได้ทั้งหมด เพราะบางส่วนมันยากขนาดว่าผมยังต้องคิดนานเลย คือเค้าแบ่งเป็นวันได้ + มาแนวสายถึงปุ่ม 50 กว่าปุ่ม กลัวทำไม่ทันเลยปรับๆออกบ้าง โปรเจคน่าสนใจปีนี้คือเกมส์อาจารย์พูนศักดิ์ทะลุมิติ เพราะเป็นเกมส์ที่ถ้ามองแบบ marketing ในค่ายก็ดีคือทุกคนรู้จักและทำให้น่าสนใจได้ดี ถ้าถามว่าอาจารย์พูนศักดิ์คือใคร เค้าเป็น head ของค่ายที่นี่ครับ และก็ตอนนำเสนองานเค้าอยู่ห้องไหนโปรแกรมของห้องนั้นโดนเกรียนหมด คืออย่างเช่นตอนปีผมเข้าค่าย โปรแกรมเค้าทำให้ใส่เลขอาราบิกอาจารย์แกใส่เลขไทยไปเลย แต่ห้องที่มีเค้าอยู่ฮาดี เพราะอาจารย์แกเกรียนดี เรียกความสนใจให้เด็กสนใจได้ดี ปีนี้ไปไม่ได้รับเกีริติบัตรด้วย T_T โดนใช้นั่งเขียนแผ่น CD ให้น้องข้างล่าง + ไปช้าเลยไม่ได้ ปีนี้แย่สุดและ คงเป็นเพราะไปช้าโดนน้องเรียกอาจารย์ด้วย ผมไม่ได้แก่ขนาดนั้นสักหน่อย

ต่อไปเป็นปัญหาในการ Coding

  1. เป็นข้อผิดพลาดจากหนังสือเรื่องการเปิด Form ใหม่ขึ้นมาเพื่อเปลี่ยนหน้า ในหนังสือใช้ Code แบบนี้ครับ
    Form2 f2 = new Form2();  
    //สร้างตัวแปร f2 โดย f2 มีค่าเป็นการสร้าง Form2 ขึ้นมาใหม่(ดูจาก new) 
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        f2.Show(); //แสดง Form2
    }

    แล้ว Code นี้มันมีปัญหายังไงล่ะ น้องๆก็ทำได้ปกตินิ เราลองมาคิดกันว่า ถ้าสมมุติน้องอยากทำปุ่มกลับหน้าแรกจาก Form2 จะเกิดอะไรขึ้น?
    นี่เป็นบางส่วนของ Code ส่วน Form1
    Form2 f2 = new Form2();
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        f2.Show();
    }

    นี่เป็นบางส่วนของ Code ส่วนของ Form2 ที่ต้องการคลิกกลับหน้าแรก
    Form1 f1 = new Form1();
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        f1.Show();
    }

    มองผ่านๆ Code นี่ก็ปกติดีใช่ไหมครับ ใช่ครับตอนแรกผมก็มองว่าปกติดีจนน้องเจอ StackOverFlow ซึ่งไม่น่าเกิดขึ้นเมื่อมันมีแค่ 8 Form ถามว่ามันเกิดได้ยังไง จากการให้ปากคำของน้อง(?) บอกว่ามันเป็นเมื่อใส่ปุ่มกลับหน้าแรก ผมเลยคิดตามว่าทำไม แล้วผมก็เห็นสิ่งนี้ที่ผมไม่เคยทำครับ การประกาศตัวแปร Form2 เป็นแบบ Global และ Inititial ค่าทันที แล้วยังไงล่ะ ลองคิดตามนะครับ ตัวแปร Global แถมกำหนดค่าให้ทันทีหมายความว่ามันทำก่อนหรือเทียบเท่า Constructor (คือทำทันทีเมื่อสร้าง Class ผมไม่ชัวร์ว่าทำตอนไหน แต่คิดว่าทำก่อนด้วยซ้ำ เพราะเราเรียกใช้ใน Constructor ได้) งั้นลองคิดดูครับ เมื่อสร้าง Form1 ขึ้นมา มันจะทำอะไร  มันจะสร้างตัวแปร f2 เพื่อไปที่ Form2 แล้ว Form2 เมื่อถูกสร้างจะทำอะไรก็จะสร้าง f1 เพื่อกลับไปที่ f1 ทันที จากนั้นเมื่อสร้าง Form1 ขึ้นใหม่ มันก็จะสร้าง f2 ของตัวเองขึ้นมากใหม่ให้ลิงค์ไป Form2 ทำซ้ำไปเรื่อยๆ ราวกับ recursive เลยทีเดียว ผลคือ Stack Overflow จ้า

    แล้วเราจะแก้ยังไงล่ะ ตอนแรกผมแก้แบบนี้ครับ พอดีห่างหาย C# ไปนานจำไม่ได้ว่าสมัยก่อนทำยังไง

    Form2 f2;
    //สร้างตัวแปร f2 โดย f2 มีค่าเป็นการสร้าง Form2 ขึ้นมาใหม่(ดูจาก new) 
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        f2 = new Form2();
        f2.Show();
    }

    แต่จำนวนบรรทัดมันเพิ่มขึ้นผมเลยไปลองใหม่ เป็นแบบนี้
    //สร้างตัวแปร f2 โดย f2 มีค่าเป็นการสร้าง Form2 ขึ้นมาใหม่(ดูจาก new) 
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        Form2 f2 = new Form2();
        f2.Show();
    }

    ทั้ง 2 วิธีนี้ได้เหมือนกันเลยนะครับ เพียงเท่านี้ก็ลิงค์ไปลิงค์กลับได้แล้วครับ จนบัดนี้ผมยังไม่รู้เลยว่าไปทำเป็น Global ทำไม?
  2. การเปลี่ยน Form แล้วเมื่อปิด Form2 โปรแกรมไม่ถือว่าถูกปิดด้วย อันนี้ผมมีวิธีแก้สำหรับพวกโปรแกรมที่แสดงแค่ Form เดียวตลอดนะครับ(หมายถึงมีหลาย Form แต่แสดงทีละ Form) ปัญหาเกิดจากอะไร? โดยทั่วไปน้องๆใช้ Code นี้เพื่อทำการซ่อน Form เก่าแล้วแสดง Form ใหม่
    //สร้างตัวแปร f2 โดย f2 มีค่าเป็นการสร้าง Form2 ขึ้นมาใหม่(ดูจาก new) 
    public void button1_click(Object sender,EventArgs e){ 
    // บรรทัดนี้อาจจะไม่ถูกเพราะจำไม่ได้ แต่ที่ต้องการคือเมื่อคลิกที่ปุ่ม
        Form2 f2 = new Form2();
        f2.Show();
        this.Hide(); //ซ่อน Form ปัจจุบัน
    }

    ทำให้เมื่อปิด Form อื่นๆ แต่จริงๆมันก็จะยังถือว่า Form นั้นๆเปิดอยู่ ดังนั้นโปรแกรมจึงไม่ปิดสักทีครับ แล้วเราจะแก้ยังไงล่ะ อันนี้เป็นวิธีที่ผมไปแนะนำน้องๆครับ คือสร้าง Event ที่ชื่อ FormClosed ของ Form จะมี Code ประมาณนี้(พิมพ์เองไม่ได้นะครับ)
    public void Form2_FormClosed(object sender,EventArgs e){
    //บรรทัดบนนี้โปรแกรมสร้างให้ผมจำไม่ได้ว่าพิมพ์ยังไงเหมือนกัน
        Application.Exit();
        //คือบอกว่าเมื่อมีการปิด Form นี้ให้ออกจากโปรแกรม 
        //แน่นอนว่า .Hide() แค่ซ่อนไม่ได้ปิดนะครับ
    }
  3. ต่อไปอันนี้เป็นส่วนที่ยากที่สุดเลยก็ว่าได้เป็นการส่งค่าข้าม Form ซึ่งในหนังสือแนะนำให้ใช้ Delegate ครับ ซึ่งผมยังไม่เคยใช้มันเลย ผมเลยมีวิธีเกรียนๆนำเสนอ 2 วิธีคือ 1 สร้าง Constructor ไว้รับส่งค่า แต่สำหรับน้องอาจจะเข้าใจยากไปนิด ผมแนะนำอีกวิธี เป็นวิธีเกรียนสะท้านโลกเลยทีเดียว คือประกาศตัวแปรให้รู้จักทั้งโปรแกรม แล้วทำยังไงล่ะ สมมุติผมต้องการให้ตัวแปร score เป็น int และทั้งโปรแกรมรู้จัก ผมก็แค่ไปเปิด Program.cs แล้วเพิ่มบรรทัดนี้ไปล่าง Function ที่ชื่อ Main
    public static int score = 0;

    เป็นประมาณนี้ครับ
    private static void Main(string[] args)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainForm());
    }
    
    public static int score = 0;

    เพียงเท่านี้ทุก Form ก็รู้จักตัวแปรนี้แล้วครับ แต่เวลาเรียก ต้องเรียกแบบมีพิเศษหน่อยครับ คือต้องเรียกแปบนี้
    Program.score += 1; 
    //ประมาณนี้คือบอกให้ตัวแปร score + เพิ่มค่าไปอีก 1 เรียกที่ Form ไหนก็ได้ครับ

    จริงๆ ผมว่าถ้าประกาศแบบนี้ทำที่ Form1 หรือที่อื่นๆก็ได้แต่เวลาเรียกจะเป็น ชื่อClass.ชื่อตัวแปร เช่น
    Form1.score+=1;

    แต่แบบนี้ผมยังไม่ได้ทดสอบคิดว่าได้นะครับ

    นอกจากนั้นยังมีอีกแบบที่ทำได้ แต่ Code อาจจะยาวสักหน่อยนะครับ ไม่ Proof แนวคิดด้วย กลัว Proof แล้วแปก ยังไม่ได้ลองเหมือนกัน 55

    void Button1Click(object sender, EventArgs e)
    {
        this.Hide();
        //สั่งซ่อน Form ปัจจุบัน
        Form2 f2 = new Form2();
        f2.ShowDialog();
        //ShowDialog นั้นคือจะต้องมีการปิด Form ก่อนหน้าก่อน จึงจะทำบรรทัดต่อไป
        this.Close();
        // ปิด Form แม่ม
    }

ปัญหาอื่นๆที่เจอคือ ควรจะสอนหรือหา Solution สำหรับการทำงานร่วมกันที่ดีกว่านี้ เพราะจากที่สังเกต การทำงานจะทำได้แค่ทีละคนทำให้ช้า การแยก Project แล้วค่อยๆเอามารวม Form ก็เป็นไปได้ยาก + คงไม่ได้สอน ทำให้การทำ Project เป็นไปได้อย่างลำบาก Solution ที่คิดไว้แต่ไม่ได้ Proof คือ Share Folder ของแต่ละคนไปทำที่เดียวกัน โดยมีข้อแม้ว่าห้ามเปิด Form เดียวกัน ไม่งั้นอาจจะเกิดข้อมูลสูญหายได้

บันทึกอื่นๆ ไปค่ายปีนี้ก็ดีกลับมาเหมือนปกติ คือจัดตอนนักเรียนของเค้าติดธรรมศึกษา(ขอบอกว่าโรงเรียนหญิงล้วน แต่ไม่ได้ไปส่องหรอก) กับ เอมน่ารักดีนะ