Wednesday, July 28, 2004

เกมส์จับคู่

หลายเดือนก่อน นก เมล์มาถามว่าคอมที่บ้านไม่รู้เป็นไร เล่นๆเกมส์อยู่ เกมส์ชอบตาย ไม่รู้ว่าเป็นที่เกมส์ หรือเป็นที่เครื่อง พร้อมส่งไฟล์เกมส์มาให้ลองเล่นดู

ปรากฏว่าเป็นเกมส์จับคู่ หน้าตาแบบนี้ เขาบอกว่ากำลังฮิตมากที่ออฟฟิส เล่นกับแทบทุกโต๊ะ

ลองเล่นดูแล้วเกมส์มันตายทุกครั้งที่เพลงแบคกราวด์จบ ทดลองปิดเพลงก็เล่นได้เรื่อยๆ ตกลงปัญหาเป็นที่เพลง พยายามลองเปิดเวบของเกมส์ เผื่อจะมีรุ่นใหม่แก้ Bug ออกมาแล้ว (ดู URL ในเมนู) http://home.kimo.com.tw/cps_chen/ ก็ปรากฏว่าเพจหายไปแล้ว ตกลงก็เล่นโดยไม่มีเสียงไปก็แล้วกัน

เกมส์นี้เล่นไม่ยาก ใช้เมาส์คลิกๆจับคู่เบี้ยที่มีรูปเหมือนๆกันให้หายไปทีละคู่จนหมดกระดาน แต่มีเงื่อนไขว่า จับคู่ได้เฉพาะเบี้ยที่ลากเส้นเชื่อมถึงกันได้ และเส้นนั้นหักมุมไม่เกินสองครั้ง ดังตัวอย่างในรูป

มีจำกัดเวลาไว้ ถ้าเล่นไม่ทันก็ตาย

เอาเข้าจริงๆตาลายมาก เล่นไปเล่นมา แพ้คนข้างๆทุกที (ข้อแก้ตัวคือจอมันเล็กกว่า)

แพ้หลายครั้งเข้าก็เกิดไอเดียทำโปรแกรมให้มันเล่นเองดีกว่า

  • เริ่มต้นจากหาทาง Capture หน้าจอของโปรแกรม ไปเจอโปรแกรมตัวอย่าง Window Finder รันแล้วลากไอคอนรูป "เป้ายิง" ไปวางบนหน้าต่างที่ต้องการจับ ข้อมูลหน้าต่างก็จะถูกจับมาไว้ใน Clipboard

    ลองๆกับโปรแกรมเกมส์จับคู่แล้ว มันจับได้จริง หน้าจอมาอยู่ใน Clipboard จริง เหมือนกด Alt+PrtSc เลย

  • จะให้ลาก "เป้ายิง" ไปหาโปรแกรมทุกครั้งที่เริ่มใช้ก็ลำบากมากเกินไป ควรแก้ให้มันหา Window ของเกมส์จับคู่ได้เอง ผลจากโปรแกรม WindowFinder บอกว่าโปรแกรมจับคู่นี้ใช้หน้าต่างชื่อ ThunderRT5Form/ThunderRT5PictureBox เลยแก้โค๊ดให้โปรแกรมหาหน้าต่างนี้เอง ดังนี้
    if(!g_hwndFoundWindow) {
     if(gwnd = FindWindow("ThunderRT5Form", NULL)) { 
      if(g_hwndFoundWindow = FindWindowEx(gwnd, NULL, 
         "ThunderRT5PictureBox", NULL)) 
       g_hwndFoundWindow = GetWindow(g_hwndFoundWindow, 
         GW_HWNDLAST);
       ...
    

  • ขั้นต่อมาก็ไปแก้ตรงก๊อปปี้ข้อมูลใส่ Clipboard ให้ไปเรียกฟังก์ชั่นหาคู่ที่เตรียมไว้แทน การหาคู่ก็ทำง่ายๆ เป็น depth-first-search เริ่มจากเบี้ยตัวหนึ่งลากเส้นตรงไปดูว่าเจอเบี้ยหน้าตาเหมือนกันหรือเปล่า ยอมให้เลี้ยวได้ 2 ครั้ง (recursive) ความลึกไม่เกิน 2 ทำหมดทั้งกระดานก็แป้บเดียวเสร็จ

  • ที่วุ่นวายหน่อยก็ตอนเปรียบเทียบเบี้ยว่ารูปเหมือนกันหรือเปล่า ถ้าเอา Bitmap มาเทียบกันเป็นจุดๆเลย มันช้าไป(มาก) ก็เลยคำนวนหาค่าตัวแทน (Hash เป็น int หนึ่งตัว) ของแต่ละตำแหน่งเก็บไว้ก่อน แล้วเปรียบเทียบค่า Hash นี้แทน

    ปัญหาคือเกมส์นี้มันมี Background เล่นไล่ระดับสี เบี้ยรูปเหมือนกันแต่อยู่คนละตำแหน่ง คำนวน Hash ออกมาไม่ตรงกัน สีตรง Background มันต่างกันหน่อย ต้องปรับแต่งวิธีคำนวนค่า Hash อยู่พักนึง

  • อีกปัญหาคือ เบี้ยที่หายไปแล้วจะเกิดเป็นช่องว่าง ช่องว่างนี้ไม่ ดำสนิท เสมอไป มันมีรูป Background อยู่ด้านหลังอีก ทำให้สมมติฐานว่าช่องว่างคือพื้นดำ ใช้ไม่ได้ โปรแกรมดูไม่ออกว่าเป็นช่องว่างหรือเปล่า

    ก็แก้ปัญหาโดยบังคับให้รันโปรแกรมตั้งแต่ต้นเกมส์ แล้วจำ Hash ของทั้งกระดานไว้ ระหว่างเล่นถ้าได้ Hash แบบที่ไม่เคยเห็นมาก่อนก็ถือว่าเป็นช่องว่าง

  • รุ่นแรก ให้โปรแกรมแสดงคู่ที่หาได้ บนจอ แล้วคนเล่นก็เล่นต่อเอง

  • รุ่นต่อๆมาเพิ่มปุ่ม AUTO ให้มันส่ง Message การกด Mouse ไปให้โปรแกรมด้วย จะได้เล่นเองเลยเรื่อยๆจนจบกระดาน
    SendMessage(g_hwndFoundWindow, WM_MOUSEMOVE, 
                0, offX+x*40+20+((offY+y*50+25)<<16));
    ::Sleep(50);
    
    SendMessage(g_hwndFoundWindow, WM_LBUTTONDOWN, 
                0, offX+x*40+20+((offY+y*50+25)<<16));
    ::Sleep(50);
    
    SendMessage(g_hwndFoundWindow, WM_LBUTTONUP, 
                0, offX+x*40+20+((offY+y*50+25)<<16));
    

    ใส่หน่วงเวลาระหว่าง Message ไว้นิดหน่อย ไม่งั้นโปรแกรมเกมส์มันจัดการไม่ทัน

เอาไปให้น้องดู เขาบอกถ้าจะเขียน Script เพื่อ Automate Task บน Windows ใช้ AutoIt ก็ได้

เข้าไปดูแล้วมันคงทำได้เหมือนกัน แต่ใช้ภาษาที่ AutoIt มีให้ อ่านค่าพิกเซลบนจอ คำนวน Hash และก็มาค้นหาคู่แบบนี้ คงช้ากว่าเขียนด้วย C แยะ

8 comments:

bact' said...

ข้าน้อยขอคารวะ

poonlap said...

อ้าวช่างประจวบเหมาะหมู่นี้ผมก็เล่นเกมส์คล้ายๆกันชื่อ kshisen อยู่ใน KDE ครับ.

ichris said...

สุดยอดครับพี่! -/|\-

NOI said...

กำลังจะเข้ามาบอกเหมือนกันว่า KDE's Game ก็มีคล้ายๆ อย่างนี้ครับ :) (เคยเล่นเหมือนกัน)

torasian said...

พอดีกำลังมองหาเกมส์นี้อยู่ ... มาเจอ Blog นี้แล้วขอชมหน่อยว่า "เยี่ยมจริง"

แล้วผมก็ได้ไปเจอกับเวบของ Chen Program Study (CPS) มาครับ มีเวอร์ชั่นของ kawai ใหม่ ๆ อีกหลายเวอร์ชันให้ดาวน์โหลดฟรี ๆ มาลองเล่นกันด้วยคับ

http://myweb.hinet.net/home4/cps-chen/main.htm

torasian said...

ฮัลโหล ...

ผมลองโหลดมาลองเล่นหลายเวอร์ชันแล้ว แต่เวอร์ชั่นที่กำลังฮิตนี้ ดันไม่เจอ

ใครมีไฟล์อยู่ (ขนาดคงไม่ใหญ่มาก) กรุณาส่งให้ผมบ้างนะครับ torasian@gmail.com (หรือทาง msn ก็ได้คับ ออนไลน์กลางคืนเกือบทุกวัน)

equltity said...

ครายมีลิ้งให้ดาวน์โหลดบ้างอ่ะครับ

SSaSS said...

http://www.tempf.com/getfile.php?id=461072&key=4bb1920289385

นี้คับ