วันจันทร์ที่ 19 มกราคม พ.ศ. 2552

บทที่ 1 แนะนำการเขียนโปรแกรมเชิงวัตถุ

บทที่ 1 แนะนำการเขียนโปรแกรมเชิงวัตถุ



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

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

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



ความเป็นมาของแนวคิดแบบ OOP

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

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

อาลัน เคย์ (Alan Kay) เป็นผู้บุกเบิกแนวความคิดการเขียนโปรแกรมเชิงวัตถุคนหนึ่ง และเป็นผู้ที่มีส่วนในการพัฒนาตัวแปลภาษา Small Talk ที่เป็นต้นแบบของการเขียนโปรแกรมเชิงวัตถุได้เสนอกฎ 5 ข้อ ที่เป็นแนวทางของภาษาคอมพิวเตอร์เชิงวัตถุ หรือที่เรียกว่า Object-Oriented Programming (OOP) ไว้ดังนี้

1.ทุกๆ สิ่งเป็นวัตถุ (Everything is an Object)

2.โปรแกรม ก็คือ กลุ่มของวัตถุที่ส่งข่าวสารบอกกันและกันให้ทำงาน (A Program is a Bunch of Object Telling Each Other What to do by Sending Messages)

3.ในวัตถุแต่ละวัตถุจะต้องมีหน่วยความจำและประกอบไปด้วยวัตถุอื่นๆ (Each Object has Its Own Memory Made Up of Other Objects)

4.วัตถุทุกชนิดจะต้องจัดอยู่ในประเภทใดประเภทหนึ่ง (Every Object has a Type)

5.วัตถุที่จัดอยู่ในประเภทเดียวกันย่อมได้รับข่าวสารเหมือนกัน (All Objects of a Particular Type Can Receive the Same Messages)



แนวคิดแบบ OOP

ถ้าเราไม่มองในแง่มุมของการเขียนโปรแกรมเพียงอย่างเดียว ให้มองไปในภาพรวม มองไปในสิ่งรอบๆ ตัว เราสามารถบอกได้ว่าแนวคิดของ OOP ก็คือ “ธรรมชาติของวัตถุ” หมายความว่า OOP จะมองสิ่งแต่ละสิ่งถือเป็น “วัตถุชิ้นหนึ่ง” (Object) มันจะมีสีแดงหรือสีเขียวยาวหรือสั้น มันก็คือวัตถุชิ้นหนึ่งหมือนกัน และเราสามารถกำหนดประเภทหรือคลาสให้กับวัตถุเหล่านั้นได้ เช่น วัตถุสีแดงก็มารวมอยู่ในกลุ่มเดียวกัน หรือวัตถุที่มีขนาดยาวก็มารวมอยู่ในกลุ่มเดียวกัน เป็นต้น

นอกจากนี้ เมื่อ OOP มองทุกสิ่งถือเป็นวัตถุชิ้นหนึ่งแล้ว ยังสามารถคิดต่อไปอีกว่า

“วัตถุแต่ละอย่งนั้น ต่างก็มีลักษณะและวิธีการใช้งานเป็นของตัวเอง”

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

“ดินสอเป็นวัตถุที่มีลักษณะยาวเรียว ภายในเป็นไส้ถ่านใช้สำหรับเขียน การใช้ดินสอทำได้โดยใช้มือจับและเขียนลงบนวัสดุรองรับ”

จากประโยคในข้างต้นเราสามารถจับใจความได้ว่า คุณลักษณะของวัตถุ (Attribute) ก็คือ “ยาวเรียว ภายในเป็นไส้ถ่าน” ส่วนการใช้งาน (Method) ก็คือ “ใช้มือจับและเขียนลงบนวัสดุรองรับ”


Object-> วัตถุ-> ดินสอ



จากการยกตัวอย่างข้างต้นสามารถสรุปได้แล้วว่า ถ้าเกิดวัตถุใดมีลักษณะยาวเรียว มีไส้ เป็นถ่าน เมื่อจะใช้งานจะต้องใช้มือจับและเขียนลงบนวัสดุรองรับ เราสามารถบอกได้เลยว่าสิ่งนั้นก็คือ “ดินสอ” นั่นเอง

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



ข้อควรรู้เกี่ยวกับ OOP

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



การเชื่อมต่อ (Interface)

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

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



การซ่อนรายละเอียด (Encapsulation)

ส่วนประกอบของวัตถุตามแนวความคิดการเขียนโปรแกรมเชิงวัตถุ จะต้องประกอบด้วยสองส่วนเป็นอย่างน้อย คือ ส่วนของคุณสมบัติใช้เก็บข้อมูลรายละเอียด สถานะ โดยใช้ตัวแปรเก็บค่าต่างๆ ไว้ และส่วนของเมธทอดที่เป็นตัวเชื่อมการทำงานของวัตถุนั้นๆ โดยผู้ใช้จะไม่สามารถติดต่อใช้งานตัวแปรที่อยู่ข้างในได้ ในภาษา C++ จะใช้คำ Public,Private และ Protected เข้ามาช่วยกำหนดขอบเขตการใช้









Private
Protected
Public







รูปที่ 1-2 คำที่ช่วยกำหนดขอบเขตการใช้ในภาษา C++





การนำวัตถุมาใช้ใหม่ (Reuse the Object)

จุดประสงค์ใหญ่ของการเขียนโปรแกรมเชิงวัตถุ ก็คือ การนำส่วนต่างๆ ของวัตถุที่สร้างขึ้นกลับมาใช้ใหม่หรือที่เรียกในภาษาอังกฤษว่า “Reuse” เมื่อผู้เขียนโปรแกรมสร้างวัตถุมีจำนวนมากพอก็สามารถนำวัตถุที่สร้างขึ้นมาประกอบเป็นวัตถุใหม่ หรือที่เรียกว่าคอมโพสิตชั่น “Composition” ดังตัวอย่างการสร้างรถยนต์ ผู้ใช้ไม่จำเป็นจะต้องสร้างรถโดยเริ่มจากส่วนประกอบต่างๆ ที่ทำใหม่ทุกครั้ง แต่ผู้ใช้สามารถสร้างจากส่วนประกอบที่มีอยู่แล้วได้










รูปที่ 1-3 รถยนต์และส่วนประกอบของรถยนต์ เช่น ล้อ หลังคา ฝากระโปรง





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



การพ้องรูป (Polymorphism)

รากฐานของการพ้องรูป (Polymorphism) ก็คือ การถ่ายทอดคุณสมบัติ เพราะถ้าไม่มีการถ่ายทอดคุณสมบัติก็จะไมเกิดสภาวะการพ้องรูป การถ่ายทอดคุณสมบัติเป็นเครื่องยืนยันได้ว่า คลาสลูกที่เกิดจากคลาสแม่เดียวกันย่อมมีคุณสมบัติเหมือนกัน



การเขียนโปรแกรมและการออกแบบระบบงาน

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





ประโยชน์ของการโปรแกรมแบบ OOP

เทคโนโลยีของออบเจ็กต์โอเรียนเท็ดได้นำประโยชน์ของการพัฒนาซอฟต์แวร์มาให้ ดังนี้

1.ความสามารถในการเรียกใช้ได้หลายครั้ง ออบเจ็กต์ได้ถูกออกแบบตามหลักการที่ว่าสามารถเรียกใช้งานได้หลายๆ ครั้ง ในหลักการนี้ทำให้ Application ของ OOP ตัวแรกอาจจะทำได้ยาก แต่ว่าโปรแกรมแอปพลิเคชันที่เขียนภายหลังจะสร้างง่ายเพราะสามารถเรียกใช้ออบเจ็กต์ที่ถูกสร้างไว้ตั้งแต่โครงงานแรกได้

2.ความเชื่อถือได้ โปรแกรมแอปพลิเคชันของ OOP จะมีความเชื่อถือได้สูงเพราะจะรวมเอาส่วนย่อยที่ทดสอบจนได้มาตรฐานแล้วมารวมเข้าไว้ด้วยกัน รหัส (Code) ที่เขียนขึ้นมาใหม่ในแต่ละแอพพลิเคชันจะมีไม่มากนัก เนื่องจากรหัสส่วนใหญ่จะถูกดึงมาจากไลบรารีที่มีความเชื่อถือได้สูงอยู่แล้ว และในการโปรแกรมภาษา C++ ยังมีคุณประโยชน์อื่นอีก

3.ความต่อเนื่องกัน การพัฒนาซอฟต์แวร์แบบ OOP ใน C++ จะเปลี่ยนไปตามฝีมือและจำนวนนักเขียนโปรแกรมภาษา C นักโปรแกรมภาษา C ที่ชำนาญสามารถเรียนรู้หลักการของ OOP ได้ภายในเวลาไม่นาน และสามารถเข้าใจในเนื้อหาได้ไม่ยาก อีกทั้งสามารถแปลงโปรแกรมแอพพลิเคชั่นของ C เป็น C++ ได้

วันจันทร์ที่ 29 กันยายน พ.ศ. 2551

เปิดรูป BMP 16 BIT

#include
#include
#include
#include
#include


struct BMP
{
char Type[2]; //File type. Set to "BM".
unsigned long Size; //Size in BYTES of the file.
unsigned long Reserved; //Reserved. Set to zero.
unsigned long OffSet; //Offset to the data.
unsigned long headsize; //Size of rest of header. Set to 40.
unsigned long Width; //Width of bitmap in pixels.
unsigned long Height; // Height of bitmap in pixels.
unsigned int Planes; //Number of Planes. Set to 1.
unsigned int BitsPerPixel; //Number of Bits per pixels.
unsigned long Compression; //Compression. Usually set to 0.
unsigned long SizeImage; //Size in bytes of the bitmap.
unsigned long XPixelsPreMeter; //Horizontal pixels per meter.
unsigned long YPixelsPreMeter; //Vertical pixels per meter.
unsigned long ColorsUsed; //Number of colors used.
unsigned long ColorsImportant; //Number of "important" colors.
} Obj;

int ShowBMP(int x, int y, char* FileName)
{
int b,a,im;

unsigned char* Datas;
int in=0;
unsigned char c=0;
FILE * fp;

fp = fopen(FileName,"rb");
if(!fp){
printf("Error : Unable to open file ..");
exit(0);
}

fread(&Obj, sizeof(Obj), 1, fp);
if(Obj.BitsPerPixel!=4) // This isn't a 16 color bmp we can read;
{
fclose(fp);
printf("Error : File format not supported ..");
exit(0);
};
fseek(fp,Obj.OffSet,SEEK_SET);
Datas=(unsigned char*) calloc(Obj.Width, sizeof(unsigned char));
im = 0;
for(b=Obj.Height;b>=0;b--)
{
fread(Datas, sizeof(unsigned char), Obj.Width/2, fp);
c=0;
in=0;
for(a=0;a<=Obj.Width;a+=2)
{
c = (Datas[in] | 0x00) >>4;
putpixel(a+x,b+y,c);
c = (Datas[in] | 0xF0) & 0x0F;
putpixel(a+1+x,b+y,c);
in++;
}
//fread(Datas, sizeof(unsigned char),1, fp);
//getch();
}
free (Datas);
fclose(fp);
return 1;
}


void main()
{
int color;
int gd , gm ;
gd = VGA ; gm = VGAHI;

initgraph(&gd,&gm,"");
ShowBMP(0,0,"test.bmp");
getch();
closegraph();
}

เกมงูกินหาง

#include
#include
#include
#include
#include
#include

check();
end();
win();
int m[500],n[500],con=20;
clock_t start,stop;
void main(void)
{

int gd=DETECT,gm,ch,maxx,maxy,x=13,y=14,p,q,spd=100;

initgraph(&gd,&gm,"..\bgi");

setcolor(WHITE);
settextstyle(3,0,6);
outtextxy(200,2," SNAKE 2 ");
settextstyle(6,0,2);
outtextxy(20,80," Use Arrow Keys To Direct The Snake ");
outtextxy(20,140," Avoid The Head Of Snake Not To Hit Any Part Of Snake");
outtextxy(20,160," Pick The Beats Untill You Win The Game ");
outtextxy(20,200," Press 'Esc' Anytime To Exit ");
outtextxy(20,220," Press Any Key To Continue ");
ch=getch();
if(ch==27) exit(0);
cleardevice();
maxx=getmaxx();
maxy=getmaxy();

randomize();

p=random(maxx);
int temp=p%13;
p=p-temp;
q=random(maxy);
temp=q%14;
q=q-temp;



start=clock();
int a=0,i=0,j,t;
while(1)
{

setcolor(WHITE);
setfillstyle(SOLID_FILL,con+5);
circle(p,q,5);
floodfill(p,q,WHITE);

if( kbhit() )
{
ch=getch(); if(ch==0) ch=getch();
if(ch==72&& a!=2) a=1;
if(ch==80&& a!=1) a=2;
if(ch==75&& a!=4) a=3;
if(ch==77&& a!=3) a=4;
}
else
{
if(ch==27
) break;
}

if(i<20){
m[i]=x;
n[i]=y;
i++;
}

if(i>=20)

{
for(j=con;j>=0;j--){
m[1+j]=m[j];
n[1+j]=n[j];
}
m[0]=x;
n[0]=y;

setcolor(WHITE);
setfillstyle(SOLID_FILL,con);
circle(m[0],n[0],8);
floodfill(m[0],n[0],WHITE);

setcolor(WHITE);
for(j=1;j setfillstyle(SOLID_FILL,con+j%3);
circle(m[j],n[j],5);
floodfill(m[j],n[j],WHITE);
}
delay(spd);

setcolor(BLACK);
setfillstyle(SOLID_FILL,BLACK);
circle(m[0],n[0],8);
floodfill(m[0],n[0],BLACK);

setcolor(BLACK);
setfillstyle(SOLID_FILL,BLACK);
circle(m[j],n[j],5);
floodfill(m[j],n[j],BLACK);

}
stop=clock();
t=(stop-start)/CLK_TCK;

//printf(" TIME %d sec ",t);
//printf("SCORE %d",con-5);
check();

if(x==p&&y==q) { con=con+5; if(spd>=5) spd=spd-5; else spd=5;
if(con>490) win();
p=random(maxx); temp=p%13; p=p-temp;
q=random(maxy); temp=q%14; q=q-temp;
}
if(a==1) y = y-14; if(y<0) { temp=maxy%14;y=maxy-temp;}
if(a==2) y = y+14; if(y>maxy) y=0;
if(a==3) x = x-13; if(x<0) { temp=maxx%13;x=maxx-temp;}
if(a==4) x = x+13; if(x>maxx) x=0;
if(a==0){ y = y+14 ; x=x+13; }
}

}


check(){
int a;
for(a=1;a
if(m[0]==m[a] && n[0]==n[a]) end();
else continue;

}
end()

{

int j,i;
setcolor(WHITE);
for(i=0;i<5;i++){
delay(500);
cleardevice();
delay(500);
for(j=0;j<=con;j++){
setfillstyle(SOLID_FILL,RED);
circle(m[j],n[j],5);
floodfill(m[j],n[j],WHITE);
}

}

settextstyle(3,0,4);
outtextxy(150,150," GAME OVER ");
getch();
getch();
exit(0);
}

win()
{
int j,i;
setcolor(WHITE);
for(i=0;i<5;i++){
for(j=0;j<=con;j++){
setfillstyle(SOLID_FILL,con);
circle(m[j],n[j],5);
floodfill(m[j],n[j],WHITE);
}
delay(500);
cleardevice();
delay(500);
}
settextstyle(3,0,4);
outtextxy(210,320," YOU WIN ");
getch();
exit(0);
}

สี่เหลี่ยม พิศวง

//n[n*n+1]/2.
void BuildMagicSquare()
{
int order=5,loop;
int MagicMat[5][5];
int SqrOfOrder = order * order;
int nCount=0, mid=order/2;
for(loop=1; loop<=SqrOfOrder ; ++loop)
{
MagicMat[nCount--][mid++] = loop;
if (loop % order == 0)
{
nCount += 2;
--mid;
}
else
{
if (mid==order)
mid -= order;
else if (nCount<0)
nCount += order;
}
}
}

สร้างเกม Tetris

/* Tetris in C*/

#include
#include
#include
#include
#include

#define NUM_OF_BLCKS 30

// Symbolic Constants
const int Sys_MAXX=640,Sys_MAXY=480;
const int EMPTY=-1,TRUE=1,FALSE=0;

// Global Variables
int driver=DETECT,mode,error;

// Structure and Class Declarations
class Window;
class Tetris;

class Window
{
private:
int xleft,ytop,xright,ybottom;
int Win_MAXX_Span,Win_MAXY_Span;
int linecolor,bgcolor;
public:
Window()
{
// NULL CONSTRUCTOR
// Assigning in the Sequence :
// Upper_Left(UL) , Lower_Right(LR)
xleft=ytop=0;
xright=Sys_MAXX;ybottom=Sys_MAXY;
Win_MAXX_Span=Sys_MAXX;
Win_MAXY_Span=Sys_MAXY;
linecolor=WHITE;
bgcolor=BLACK;
}
void set_window_par(int[],int,int);
void draw_window(void);
void putstring(char*,int,int);
int get_parameter(int);
};

void Window :: set_window_par(int xyco[],int lc=WHITE,int bgc=BLACK)
{
// Assigning in the Sequence :
// Upper_Left(UL) , Lower_Right(LR)
xleft=xyco[0];
ytop=xyco[1];
xright=xyco[2];
ybottom=xyco[3];

Win_MAXX_Span=xright-xleft;
Win_MAXY_Span=ybottom-ytop;
linecolor=lc;
bgcolor=bgc;
}

void Window :: draw_window(void)
{
setcolor(linecolor);
setlinestyle(0,0,1);
rectangle(xleft,ytop,xright,ybottom);
setfillstyle(1,bgcolor);
floodfill(xleft+1,ytop+1,linecolor);
}

void Window :: putstring(char s[],int xco,int yco)
{
moveto(xco,yco);
settextstyle(TRIPLEX_FONT,HORIZ_DIR,0);
setcolor(WHITE);
setusercharsize(1,2,1,2);
outtext(s);
}

int Window :: get_parameter(int Para_id)
{
int Para_value;
switch(Para_id)
{
case 1: Para_value=xleft;
case 2: Para_value=ytop;
case 3: Para_value=xright;
case 4: Para_value=ybottom;
case 5: Para_value=Win_MAXX_Span;break;
case 6: Para_value=Win_MAXY_Span;break;
case 7: Para_value=linecolor;break;
case 8: Para_value=bgcolor;break;
}
return Para_value;
}


class Tetris
{
private:
int SCode,PCode,TCode;
int **tarr,fbsize,boxtype;
int VXCh,HYCh,fillcol;
Window W1; // Main Window
Window W2; // Side Window
Window W3; // Next_Piece Window
Window W4; // Total Score Window
Window W5; // "Total Lines Destroyed" Window
Window W6; // "Lines Remaining for Game Over" Window
Window W7; // "Level" Window
public:
Tetris(){fbsize=10;fillcol=RED;}
void regulate_play(void);
void initialize_windows(void);
void gen_randshape(void);
void draw_shape(int,int,int,Window*);
int verify_vert_movement(int,int);
}Temp;


void Tetris :: regulate_play(void)
{
int i,j,r;
int channel,y=0;
int prevchan,prevy;

initialize_windows();

/*
Looping as many times as user desires .Each time, one Tetris-Block is
produced randomly at the top of Main Window, slides in Free-fall
and settles at floor of the Tetris Window. In the meanwhile, next piece
is produced randomly(displayed in "Next Piece Window"), which is used as
the Falling Tetris-Block in next iteration.
Please note, here:
'T' - the invoking object from main() is object for Tetris Main Window
'Temp' - Is the Object for "Next Piece Window"
*/
for(r=0;r {
if(r==0)
// Very 1st Looping
{
// Hence, Generating shape to be used currently/initially by using Next_Piece Object
Temp.gen_randshape();

// Randomly Selecting the FillColor of the Shape that will be drawn in Main Window
do{
fillcol=random(16);
}while(fillcol==WHITE||fillcol==YELLOW||fillcol==BLACK);
}
else
// Subsequent Iterations
{
// Erasing "Next Piece Window" Graphically
W3.draw_window();
// Erasing "Next Piece Window" Logically (i.e. contents of tarr[][] reset)
Temp.draw_shape(3,3,EMPTY,&W3);
}

// Making the Next Piece Obj contents as the Main Window Piece Obj contents
SCode=Temp.SCode;
PCode=Temp.PCode;
TCode=Temp.TCode;
if(r!=0)
fillcol=Temp.fillcol;

// Generating a Random Next-Piece =>
// This will by above assignments become
// the Current Piece in next iteration
Temp.gen_randshape();

// Randomly Selecting the Channel =>
// One of the (45-3) Vertical Channels that the piece can be launched
// into Free-Fall from Top of the Tetris Window
channel=random(VXCh-3);

// Randomly Selecting the FillColor of the Shape that will be drawn in the Next Piece Window
do{
Temp.fillcol=random(16);
}while(Temp.fillcol==WHITE||Temp.fillcol==YELLOW|| Temp.fillcol==BLACK);

// Drawing the Pieces in Main & Next Piece Window respectively
draw_shape(channel,y,fillcol,&W1);
Temp.draw_shape(3,3,Temp.fillcol,&W3);

// Erasing Piece from Main Window
W1.draw_window();draw_shape(channel,y,EMPTY,&W1);


// Iterating for Current Piece for Free-Fall Motion to floor of Tetris Window
// Here:
// 1. 'j' will control the FREE-FALLING Motion of Tetris Block
// 2. 'channel' will control Horizontal/Sideways Motion of Tetris Block
for(j=y;(j ||(j ||(j {
prevchan=channel;

if(channel==0)
// We have reached the LEFTMOST boundary
// Hence, we may either let 'channel' be or Increment it
// We CANNOT and MUST NOT Decrement 'channel'
{
switch(random(2))
{
case 0:break;
case 1:channel++;
}
}

else if((channel==VXCh-2&&boxtype==23) || (channel==VXCh-3&&boxtype==32) ||
(channel==VXCh-1&&boxtype==14) || (channel==VXCh-4&&boxtype==41) ||(channel==VXCh-2&&boxtype==22))
// We have reached the RIGHTMOST boundary
// Hence, we may either let 'channel' be or Decrement it
// We CANNOT and MUST NOT Increment 'channel'
{
switch(random(2))
{
case 0:break;
case 1:channel--;
}
}
else
// We are somewhere in the middle
// Hence, we may move leftwards, rightwards or stay as it is
{
switch(random(3))
{
case 0:channel++;break;
case 1:channel--;break;
case 2:break;
}
}

if(j!=y)
// Executing for all iterations except the 1st one
{
// Erasing contents of Tetris Main Window Graphically
W1.draw_window();

// Erasing contents of Tetris Main Window Logically
// (i.e. contents of tarr[][] are reset)
draw_shape(prevchan,j-1,EMPTY,&W1);
}

// Drawing the Tetris Block with new values of 'channel' & 'j'
draw_shape(channel,j,fillcol,&W1);

// Testing whether further vertical motion is possible or not
// Depending upon that, we either continue or abandon iterating
if(!verify_vert_movement(channel,j))
break;
delay(1000);
}
}
}


void Tetris :: initialize_windows(void)
{
//TESTING Window Drawings
initgraph(&driver,&mode,"\\TC\\BGI");
error=graphresult();
if(error!=grOk)
{
printf("GRAPHICS ERROR!!");
getch();
exit(1);
}

int xy1[4],xy2[4],xy3[4],xy4[4],xy5[4],xy6[4],xy7[4];

// Setting Window Parameters
xy1[0]=10;xy1[1]=10;
xy1[2]=460;xy1[3]=470;

xy2[0]=480;xy2[1]=10;
xy2[2]=630;xy2[3]=470;

xy3[0]=510;xy3[1]=40;
xy3[2]=600;xy3[3]=120;

xy4[0]=495;xy4[1]=160;
xy4[2]=615;xy4[3]=190;

xy5[0]=495;xy5[1]=230;
xy5[2]=615;xy5[3]=260;

xy6[0]=495;xy6[1]=300;
xy6[2]=615;xy6[3]=330;

xy7[0]=495;xy7[1]=370;
xy7[2]=615;xy7[3]=400;

W1.set_window_par(xy1);
W2.set_window_par(xy2);
W3.set_window_par(xy3);
W4.set_window_par(xy4);
W5.set_window_par(xy5);
W6.set_window_par(xy6);
W7.set_window_par(xy7);


// Initializing for the Main Window Tetris Obj 'T/Temp' the following parameters ;
// 1. No. of Vertical Channels or Vertical Span (VXCh)
// 2. No. of Horizontal Channels ot Horizontal Span (HYCh)
// 3. 2D-Array 'tarr' where -
// tarr[i][j] => 10pixel by 10pixel block, 3-4 of which put together forms ONE Tetris Block
VXCh=W1.get_parameter(5)/fbsize;
HYCh=W1.get_parameter(6)/fbsize;
tarr=(int**)malloc((VXCh)*sizeof(int));
for(int i=0;i tarr[i]=(int*)malloc((HYCh)*sizeof(int));

for(int j=0;j for(int k=0;k tarr[j][k]=EMPTY;


// Initializing for the Next Piece Window Tetris Obj 'Temp' the following parameters ;
// 1. No. of Vertical Channels or Vertical Span (HYCh)
// 2. No. of Horizontal Channels ot Horizontal Span (HYCh)
// 3. 2D-Array 'tarr' where -
// tarr[i][j] => 10pixel by 10pixel block, 3-4 of which put together forms ONE Tetris Block
Temp.VXCh=W3.get_parameter(5)/fbsize;
Temp.HYCh=W3.get_parameter(6)/fbsize;
Temp.tarr=(int**)malloc((Temp.VXCh)*sizeof(int));
for(i=0;i Temp.tarr[i]=(int*)malloc((Temp.HYCh)*sizeof(int));

for(j=0;j for(k=0;k Temp.tarr[j][k]=EMPTY;


// Drawing all the Windows
W1.draw_window();
W2.draw_window();
W3.draw_window();
W4.draw_window();
W5.draw_window();
W6.draw_window();
W7.draw_window();

// Writing String Entries in Windows
W2.putstring("Next Piece :",495,20);
W2.putstring("SCORE :",495,140);
W2.putstring("Tot. Lines Dest. :",495,210);
W2.putstring("Lines Rem. :",495,280);
W2.putstring("LEVEL :",495,350);
}


void Tetris :: gen_randshape(void)
{
SCode=random(7);
// Scode=0 --> L-Shape , Scode=1 --> InvL-Shape
// Scode=2 --> T-Shape , Scode=3 --> Z-Shape
// Scode=4 --> InvZ-Shape , Scode=5 --> I-Shape
// Scode=6 --> Sq-Shape

// Tcode=0 --> L1 , Tcode=1 --> L2 , Tcode=2 --> L3
// Tcode=3 --> L4 , Tcode=4 --> IL1 , Tcode=5 --> IL2
// Tcode=6 --> IL3 , Tcode=7 --> IL4 , Tcode=8 --> T1
// Tcode=9 --> T2 , Tcode=10 --> T3 , Tcode=11 --> T4
// Tcode=12 --> Z1 , Tcode=13 --> Z2 , Tcode=14 --> IZ1
// Tcode=15 --> IZ2 , Tcode=16 --> I1 , Tcode=17 --> I2
// Tcode=18 --> Sq

/*
NOTE:
1. TCode=0 --> L1 => Normal 'L' Shaped Block, i.e. '|_'
Give Anti-Clockwise Rotation to visualize L2, L3 & L4

2. TCode=4 --> IL1 => Inverted 'L' Shaped Block, i.e. '_|'
Give Anti-Clockwise Rotation to visualize IL2, IL3 & IL4

3. TCode=8 --> T1 => '_|_' Shaped Block
Give Anti-Clockwise Rotation to visualize T2, T3 & T4
_
4. TCode=12 -->Z1 => Normal 'Z' Shaped Block, i.e. ' |_'
Give Anti-Clockwise Rotation to visualize Z2

_
5. TCode=14 -->IZ1 => Inverted 'Z' Shaped Block, i.e. '_| '
Give Anti-Clockwise Rotation to visualize IZ2

6. TCode=16 -->I1 => Long Vertically Standing Block
7. TCode=17 -->I2 => Long Horizontally Sleeping Block
8. TCode=18 -->Sq => Sq Block consisting of 2 by 2 fundamental blocks

Each of the above 8 sets consist of 4 Fundamental Blocks
*/

switch(SCode)
{
case 0:
case 1:
case 2: PCode=random(4);TCode=4*SCode+PCode;break;
case 3: PCode=random(2);TCode=12+PCode;break;
case 4: PCode=random(2);TCode=14+PCode;break;
case 5: PCode=random(2);TCode=16+PCode;break;
case 6: PCode=0;TCode=18;
}
}


void Tetris :: draw_shape(int channel,int y,int DMode,Window *W)
{
if(TCode==18)
{
// Boxtype is 2Col by 2Rows (i.e. 2VXPix by 2HYPix)
boxtype=22;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel+1][y]=tarr[channel+1][y+1]=DMode;
}

else if(TCode==16)
{
// Boxtype is 1Col by 4Row (i.e. 1VXPix by 4HYPix)
boxtype=14;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel][y+2]=tarr[channel][y+3]=DMode;
}

else if(TCode==17)
{
// Boxtype is 4Col by 1Row (i.e. 4VXPix by 1HYPix)
boxtype=41;
// Drawing the 4 Blocks Logically
tarr[channel][y]=tarr[channel+1][y]=tarr[channel+2][y]=tarr[channel+3][y]=DMode;
}

else if(TCode==0||TCode==2||TCode==4||TCode==6||
TCode==9||TCode==11||TCode==13||TCode==15)
{
// Boxtype is 2Col by 3Rows (i.e. 2VXPix by 3HYPix)
boxtype=23;
if(TCode==0||TCode==6||TCode==9)
// Drawing the Common Blocks Logically
tarr[channel][y]=tarr[channel][y+1]=tarr[channel][y+2]=DMode;
else if(TCode==2||TCode==4||TCode==11)
// Drawing the Common Blocks Logically
tarr[channel+1][y]=tarr[channel+1][y+1]=tarr[channel+1][y+2]=DMode;
else if(TCode==13||TCode==15)
// Drawing the Common Blocks Logically
tarr[channel][y+1]=tarr[channel+1][y+1]=DMode;
}

else if(TCode==1||TCode==3||TCode==5||TCode==7||
TCode==8||TCode==10||TCode==12||TCode==14)
{
// Boxtype is 3Col by 2Rows (i.e. 3VXPix by 2HYPix)
boxtype=32;
if(TCode==1||TCode==7||TCode==8)
// Drawing the Common Blocks Logically
tarr[channel][y+1]=tarr[channel+1][y+1]=tarr[channel+2][y+1]=DMode;
else if(TCode==3||TCode==5||TCode==10)
// Drawing the Common Blocks Logically
tarr[channel][y]=tarr[channel+1][y]=tarr[channel+2][y]=DMode;
else if(TCode==12||TCode==14)
// Drawing the Common Blocks Logically
tarr[channel+1][y]=tarr[channel+1][y+1]=DMode;
}

// Drawing the Specialized Xtra Blocks Logically
switch(TCode)
{
case 0: tarr[channel+1][y+2]=DMode;break;
case 1: tarr[channel+2][y]=DMode;break;
case 2: tarr[channel][y]=DMode;break;
case 3: tarr[channel][y+1]=DMode;break;
case 4: tarr[channel][y+2]=DMode;break;
case 5: tarr[channel+2][y+1]=DMode;break;
case 6: tarr[channel+1][y]=DMode;break;
case 7: tarr[channel][y]=DMode;break;
case 8: tarr[channel+1][y]=DMode;break;
case 9: tarr[channel+1][y+1]=DMode;break;
case 10:tarr[channel+1][y+1]=DMode;break;
case 11:tarr[channel][y+1]=DMode;break;
case 12:tarr[channel][y]=DMode;tarr[channel+2][y+1]=DMode;break;
case 13:tarr[channel+1][y]=DMode;tarr[channel][y+2]=DMode;break;
case 14:tarr[channel][y+1]=DMode;tarr[channel+2][y]=DMode;break;
case 15:tarr[channel][y]=DMode;tarr[channel+1][y+2]=DMode;break;
}

// Actually Drawing it Graphically for Window W1
if(W==&W1)
{
for(int i=0;i for(int j=0;j if(tarr[i][j]!=EMPTY)
{
setcolor(YELLOW);
setlinestyle(0,0,1);
rectangle(fbsize*(i+1),fbsize*(j+1),fbsize*(i+2),fbsize*(j+2));
setfillstyle(1,tarr[i][j]);
floodfill(fbsize*(i+1)+1,fbsize*(j+1)+1,YELLOW);
}
}
else
{
for(int i=0;i for(int j=0;j if(tarr[i][j]!=EMPTY)
{
setcolor(YELLOW);
setlinestyle(0,0,1);
rectangle(fbsize*(i+51),fbsize*(j+4),fbsize*(i+52) ,fbsize*(j+5));
setfillstyle(1,tarr[i][j]);
floodfill(fbsize*(i+51)+1,fbsize*(j+4)+1,YELLOW);
}
}
}


int Tetris :: verify_vert_movement(int channel,int y)
{
if(TCode==18)
{
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}

else if(TCode==16)
{
if(tarr[channel][y+4]!=EMPTY)
return FALSE;
else
return TRUE;
}

else if(TCode==17)
{
if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+1]!=EMPTY||tarr[channel+3][y+1]!=EMPTY)
return FALSE;
else
return TRUE;
}

else if(TCode==0||TCode==2||TCode==4||TCode==6||
TCode==9||TCode==11||TCode==13||TCode==15)
{
if(TCode==0||TCode==6||TCode==9)
{
// Analysing the Common Blocks Logically
if(tarr[channel][y+3]!=EMPTY)
return FALSE;
}

else if(TCode==2||TCode==4||TCode==11)
{
// Analysing the Common Blocks Logically
if(tarr[channel+1][y+3]!=EMPTY)
return FALSE;
}

else if(TCode==13)
{
// Analysing the Blocks Logically
if(tarr[channel][y+3]!=EMPTY||tarr[channel+1][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}

else if(TCode==15)
{
// Analysing the Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+3]!=EMPTY)
return FALSE;
else
return TRUE;
}
}

else if(TCode==1||TCode==3||TCode==5||TCode==7||
TCode==8||TCode==10||TCode==12||TCode==14)
{
if(TCode==1||TCode==7||TCode==8)
{
// Analysing the Common Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==12)
{
// Analysing the Blocks Logically
if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)
return FALSE;
else
return TRUE;
}
else if(TCode==14)
{
// Analysing the Blocks Logically
if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)
return FALSE;
else
return TRUE;
}
}

// Analysing the Specialized Xtra Blocks Logically
switch(TCode)
{
case 0: if(tarr[channel+1][y+3]!=EMPTY)return FALSE;break;
case 6: if(tarr[channel+1][y+1]!=EMPTY)return FALSE;break;
case 9: if(tarr[channel+1][y+2]!=EMPTY)return FALSE;break;

case 2: if(tarr[channel][y+1]!=EMPTY)return FALSE;break;
case 4: if(tarr[channel][y+3]!=EMPTY)return FALSE;break;
case 11:if(tarr[channel][y+2]!=EMPTY)return FALSE;break;

case 3: if(tarr[channel][y+2]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)return FALSE;break;
case 5: if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+1]!=EMPTY||tarr[channel+2][y+2]!=EMPTY)return FALSE;break;
case 10:if(tarr[channel][y+1]!=EMPTY||tarr[channel+1][y+2]!=EMPTY||tarr[channel+2][y+1]!=EMPTY)return FALSE;//break;
}
return TRUE;
}



// Main Prog :
void main()
{
//Seeding the Random Number Generator
randomize();
Tetris T;

printf("\n\nWelcome to Tetris \n\n");
printf("\n\nThis Demo is a glimpse into a preliminary Version and just shows the Movement of Various Tetris Pieces along the Tetris Play Space\n\n");
printf("\n\nUser I/P is NOT Expected\n\n");
printf("\n\n\nPress ENTER to goto Graphics Mode and See the DEMO\n\n\n");
getch();clrscr();
T.regulate_play();
getch();
}

สร้างเกม PONG ในภาษา C แบบ 2

/* Program for a basic 2 player Pong match with no specialized shot/bounce physics */

/*
Programmed By:
Rajiv Iyer,
T.E. Computers,
SIES GST, Nerul
*/

/* SOURCE CODE */
#include
#include
#include
#include
#include
#include
#include

#define BARSIZE 4
#define DEFRAD 10
#define DEFDELAY 20
#define LONGDELAY 1500
#define HFSND 70000
#define DEFPENALTY 50
#define DEFREWARD 25

/* Global Variables */
// Symbolic Constants
const int BARYCH=10;
const int DXCH=3,DYCH=3;
const int TRUE=1,FALSE=0;
const int FWD=0,BCK=1,UP=0,DWN=1;
const int LEFT=1,RIGHT=2,TOP=3,BOTTOM=4;

// Other Variables
int gd,gm,MAXX,MAXY;
int bounce=TRUE,cuttingbound;
int linecol,fillcol;

/* Structure Declaration */
struct Player
{
int num;
int bar[BARSIZE];
int points;
int returned,missed;
}P1,P2;

struct Sphere
{
int xinst,yinst;
int xdir,ydir;
int radius;
}Ball;

/* Function Prototypes */
void instructions(void);
void initGraphics(void);
void testResolution(void);
void moveBall(void);
int testBoundary(void);
int keyhit(void);
void rebound(void);
void drawBall(void);
void drawUserBars(void);
void pauseMenu(void);
void displayStats(void);

void main()
{
testResolution();
instructions();
moveBall();
}

void instructions(void)
{
clrscr();
printf("Welcome to the Basic 2D Tennis Program!");
printf("\n\nKeys for User I :-\n");
printf("MOVE BAR UP : 'W' or 'w'\n");
printf("MOVE BAR DOWN : 'S' or 's'\n");
printf("\n\nKeys for User II :-\n");
printf("MOVE BAR UP : 'P' or 'p'\n");
printf("MOVE BAR DOWN : 'L' or 'l'\n");

printf("\n\nCommon Keys:\n");
printf("Terminate Game : 'T' or 't'\n");
printf("Halt/Pause Game : 'H' or 'h'\n");

printf("\n\nAll Keys are Case Insensitive!");
printf("\n\n\nPress Any Key to Enter Graphics Mode & PLAY ! ..... ");
getch();
}

void initGraphics(void)
{
int error;
initgraph(&gd,&gm,"\\TC\\BGI");
error=graphresult();
if(error!=grOk)
{
printf("\n\n\aGRAPHICS ERROR! Error Code : %d",error);
getch();exit(1);
}
}

void testResolution(void)
{
clrscr();
printf("Testing System Resolution! Press Any Key to enter Graphics Mode ....");
getch();

initGraphics();
MAXX=getmaxx();
MAXY=getmaxy();
closegraph();

printf("System Resolution Detected!\n");
printf("\nHORIZONTAL PIXEL SPAN : %d (0 to %d)",MAXX+1,MAXX);
printf("\nVERTICAL PIXEL SPAN : %d (0 to %d)",MAXY+1,MAXY);
getch();
clrscr();
}

void moveBall(void)
{
// Seeding Random Number Generator
randomize();
// Initializing the Graphics Mode
initGraphics();

// Initializing the Position of the Two Player Bars
P1.bar[0]=20 ; P1.bar[1]=200; P1.bar[2]=30 ; P1.bar[3]=280;
P2.bar[0]=610; P2.bar[1]=200; P2.bar[2]=620; P2.bar[3]=280;
// Initializing the Marks Tally of Both Players to Zero
P1.points=P2.points=0;
P1.returned=P2.returned=0;
P1.missed=P2.missed=0;
// Initializing the Position of the Ball
Ball.xinst=MAXX/2;
Ball.yinst=MAXY/2;
Ball.radius=DEFRAD;
// Randomizing the Initial Direction of Travel of Ball
Ball.xdir=random(2);
Ball.ydir=random(2);
// Iterating Till Either User Hits TERMINATE(T) Key
while(!keyhit())
{
if(testBoundary())
{
// Drawing the Ball
cleardevice();
//setfillstyle(1,0);
//bar(0,0,640,480);
drawBall();
drawUserBars();
delay(DEFDELAY);
// Making Changes
if(Ball.xdir==FWD)
Ball.xinst+=DXCH;
else
Ball.xinst-=DXCH;
if(Ball.ydir==UP)
Ball.yinst-=DYCH;
else
Ball.yinst+=DYCH;
}
else
rebound();
}
closegraph();
displayStats();
}

int keyhit(void)
{
int i;
char uch,tempch;
if(kbhit())
{
uch=getch();
switch(uch)
{
case 't':
case 'T':
// The TERMINATE (T) Key was hit - so Returning True
return TRUE;
case 'w':
case 'W':
// The UP-Direction Key for Player I has been pressed
// Testing Whether Player Bar goes out of window with such a move
if(P1.bar[1]-BARYCH<0)
{
//sound(HFSND);
//nosound();
}
else
{
for(i=1;i P1.bar[i]-=BARYCH;
}
return FALSE;
case 's':
case 'S':
// The DOWN-Direction Key for Player I has been pressed
// Testing Whether Player Bar goes out of window with such a move
if(P1.bar[3]+BARYCH>MAXY)
{
//sound(HFSND);
//nosound();
}
else
{
for(i=1;i P1.bar[i]+=BARYCH;
}
return FALSE;
case 'p':
case 'P':
// The UP-Direction Key for Player II has been pressed
// Testing Whether Player Bar goes out of window with such a move
if(P2.bar[1]-BARYCH<0)
{
//sound(HFSND);
//nosound();
}
else
{
for(i=1;i P2.bar[i]-=BARYCH;
}
return FALSE;
case 'l':
case 'L':
// The DOWN-Direction Key for Player II has been pressed
// Testing Whether Player Bar goes out of window with such a move
if(P2.bar[3]+BARYCH>MAXY)
{
//sound(HFSND);
//nosound();
}
else
{
for(i=1;i P2.bar[i]+=BARYCH;
}
return FALSE;

case 'h':
case 'H':
//do{
pauseMenu();
//tempch=getch();
//}while(tempch!='h' && tempch!='H');
return FALSE;
default:
return FALSE;
}
}
else
return FALSE;
}

int testBoundary(void)
{
if(bounce==TRUE)
return TRUE;
else
{
if((Ball.xinst+Ball.radius)>=MAXX || (Ball.xinst-Ball.radius)<=0)
{
if((Ball.xinst+Ball.radius)>=MAXX)
{
cuttingbound=RIGHT;
// Player 2 misses Shot => Hence Deducting Points
P2.points-=DEFPENALTY;
P2.missed++;
}
else if((Ball.xinst-Ball.radius)<=0)
{
cuttingbound=LEFT;
// Player 1 misses Shot => Hence Deducting Points
P1.points-=DEFPENALTY;
P1.missed++;
}
// Resetting Ball to Center of Screen
Ball.xinst=MAXX/2;
Ball.yinst=MAXY/2;
// Randomizing the Initial Direction of Travel
Ball.xdir=random(2);
Ball.ydir=random(2);
// Delaying for Short Period before Graphically Resetting
delay(LONGDELAY);
return TRUE;
}
else if((Ball.yinst+Ball.radius)>=MAXY || (Ball.yinst-Ball.radius)<=0)
{
if((Ball.yinst+Ball.radius)>=MAXY)
cuttingbound=BOTTOM;
else if((Ball.yinst-Ball.radius)<=0)
cuttingbound=TOP;
return FALSE;
}
else if((Ball.xinst+Ball.radius)>=P2.bar[0] && (Ball.yinst>P2.bar[1] && Ball.yinst {
cuttingbound=RIGHT;
// Player 2 Returns Shot Successfully => Hence Rewarding Points
P2.points+=DEFREWARD;
P2.returned++;
return FALSE;
}
else if((Ball.xinst-Ball.radius)<=P1.bar[2] && (Ball.yinst>P1.bar[1] && Ball.yinst {
cuttingbound=LEFT;
// Player 1 Returns Shot Successfully => Hence Rewarding Points
P1.points+=DEFREWARD;
P1.returned++;
return FALSE;
}
else
return TRUE;
}
}

void rebound(void)
{
bounce=TRUE;
switch(cuttingbound)
{
case LEFT:Ball.xdir=FWD;break;
case RIGHT:Ball.xdir=BCK;break;
case TOP:Ball.ydir=DWN;break;
case BOTTOM:Ball.ydir=UP;break;
}
}

void drawBall(void)
{
if(bounce==TRUE)
{
bounce=FALSE;
//do{
linecol=(15);
fillcol=(15);
//}while(linecol==BLACK || fillcol==BLACK || linecol==fillcol);
}
setcolor(linecol);
circle(Ball.xinst,Ball.yinst,Ball.radius);
setfillstyle(1,fillcol);
floodfill(Ball.xinst,Ball.yinst,linecol);
}

void drawUserBars(void)
{
// Drawing Player I Bar
setcolor(linecol);
rectangle(P1.bar[0],P1.bar[1],P1.bar[2],P1.bar[3]);
setfillstyle(1,fillcol);
floodfill(P1.bar[0]+5,P1.bar[1]+5,linecol);
// Drawing Player I Bar
setcolor(linecol);
rectangle(P2.bar[0],P2.bar[1],P2.bar[2],P2.bar[3]);
setfillstyle(1,fillcol);
floodfill(P2.bar[0]+5,P2.bar[1]+5,linecol);
}

void pauseMenu(void)
{
char pch;

do{
settextstyle(TRIPLEX_FONT,HORIZ_DIR,3);
outtextxy(150,100,"1. Resume Game");
outtextxy(150,200,"2. Display Statistics");
outtextxy(150,300,"3. Controls");

pch=getch();
switch(pch)
{
case '1':
break;
case '2':
closegraph();
displayStats();
initGraphics();
break;
case '3':
closegraph();
instructions();
initGraphics();
break;
default:
printf("\n\n\aInvalid Choice!\n\n\a");
}
}while(pch!='1');
}

void displayStats(void)
{
// Printing All Collected Statistics
printf("Statistics Score-Card :\n");
printf("\n\nFor User I :\nShots Taken : %d\nShots Missed : %d\nTotal Score : %d",P1.returned,P1.missed,P1.points);
printf("\n\nFor User II :\nShots Taken : %d\nShots Missed : %d\nTotal Score : %d",P2.returned,P2.missed,P2.points);
printf("\n\n\nWINNER : ");
if(P1.points>P2.points)
printf("Player I !!");
else if(P1.points printf("Player II !!");
else
printf("Undeterminable !!");
getch();
}

สร้างเกม PONG ในภาษา C

/* SOURCE CODE */
#include
#include
#include
#include
#include
#include
#include

#define DEFDELAY 5

/* Global Variables */
// Symbolic Constants
const int xincr=1,yincr=1;
const int TRUE=1,FALSE=0;
const int FWD=0,BCK=1,UP=0,DWN=1;
const int LEFT=1,RIGHT=2,TOP=3,BOTTOM=4;

// Other Variables
int gd,gm,MAXX,MAXY;
int xstart,ystart,ballrad;
int xinst,yinst;
int xdir,ydir,cuttingbound;
int bounce=TRUE,linecol,fillcol;

/* Function Prototypes */
void initgraphics(void);
void testresolution(void);
void moveball(void);
int testboundary(void);
void rebound(void);
void drawball(void);
void showimpact(void);

void main()
{
testresolution();
printf("Please Enter XY Co-Ordinates of Starting Point : ");
scanf("%d%d",&xstart,&ystart);
printf("\n\nEnter the Size of Ball (Radius) : ");
scanf("%d",&ballrad);

printf("\n\n\nPress Any Key to Enter Graphics Mode ..... ");
getch();
moveball();
}

void initgraphics(void)
{
int error;
initgraph(&gd,&gm,"\\TC\\BGI");
error=graphresult();
if(error!=grOk)
{
printf("\n\n\aGRAPHICS ERROR! Error Code : %d",error);
getch();exit(1);
}
}

void testresolution(void)
{
clrscr();
printf("Testing System Resolution! Press Any Key to enter Graphics Mode ....");
getch();

initgraphics();
MAXX=getmaxx();
MAXY=getmaxy();
closegraph();

printf("System Resolution Detected!\n");
printf("\nHORIZONTAL PIXEL SPAN : %d (0 to %d)",MAXX+1,MAXX);
printf("\nVERTICAL PIXEL SPAN : %d (0 to %d)",MAXY+1,MAXY);
getch();
clrscr();
}

void moveball(void)
{
// Seeding Random Number Generator
randomize();
// Initializing the Graphics Mode
initgraphics();

// Initializing the Position of the Ball
xinst=xstart;
yinst=ystart;
// Iterating Till User Hits a Key
xdir=random(2);
ydir=random(2);
while(!kbhit())
{
if(testboundary())
{
// Drawing the Ball
cleardevice();
drawball();
delay(DEFDELAY);
// Making Changes
if(xdir==FWD)
xinst+=xincr;
else
xinst-=xincr;
if(ydir==UP)
yinst-=yincr;
else
yinst+=yincr;
}
else
rebound();
}
closegraph();
}

int testboundary(void)
{
if(bounce==TRUE)
return TRUE;
else
{
if((xinst+ballrad)>=MAXX || (xinst-ballrad)<=0 ||
(yinst+ballrad)>=MAXY || (yinst-ballrad)<=0)
{
if((xinst+ballrad)>=MAXX)
cuttingbound=RIGHT;
else if((xinst-ballrad)<=0)
cuttingbound=LEFT;
else if((yinst+ballrad)>=MAXY)
cuttingbound=BOTTOM;
else
cuttingbound=TOP;
return FALSE;
}
else
return TRUE;
}
}

void rebound(void)
{
bounce=TRUE;
switch(cuttingbound)
{
case LEFT:xdir=FWD;break;
case RIGHT:xdir=BCK;break;
case TOP:ydir=DWN;break;
case BOTTOM:ydir=UP;break;
}
}

void drawball(void)
{
if(bounce==TRUE)
{
bounce=FALSE;
do{
linecol=random(15);
fillcol=random(15);
}while(linecol==BLACK || fillcol==BLACK || linecol==fillcol);
}
setcolor(linecol);
circle(xinst,yinst,ballrad);
setfillstyle(1,fillcol);
floodfill(xinst,yinst,linecol);
}