沈?qū)m新
(南京化工職業(yè)技術(shù)學(xué)院,江蘇南京 210048)
C 語(yǔ)言與C++語(yǔ)言是不少高校廣泛開設(shè)的課程,從C 語(yǔ)言到C++語(yǔ)言的學(xué)習(xí)轉(zhuǎn)化是一個(gè)艱難的過程,因?yàn)樵谶@其中要實(shí)現(xiàn)結(jié)構(gòu)化程序設(shè)計(jì)向面向?qū)ο蟪绦蛟O(shè)計(jì)的轉(zhuǎn)化,同時(shí),操作系統(tǒng)的環(huán)境也有很大的不同,增大了教學(xué)的難度。為了說(shuō)明結(jié)構(gòu)化程序設(shè)計(jì)與面向?qū)ο蟪绦蛟O(shè)計(jì)的不同之處,同時(shí)簡(jiǎn)單了解WINDOWS 的基于消息的編程思維,我們將DOS 下用C 語(yǔ)言編寫的貪吃蛇小游戲改編為C++編寫,用面向?qū)ο蟮乃枷雭?lái)組織,用類來(lái)封裝,在 WINDOWS 下以窗口形式運(yùn)行WIN32 的應(yīng)用程序。
貪吃蛇小游戲包括注釋不到200 行,是一個(gè)經(jīng)典的游戲案例,能夠較好說(shuō)明結(jié)構(gòu)化編程的思想。主函數(shù)包括四塊,第一塊是初始化圖形系統(tǒng),在TURBO C 中包括圖形庫(kù)的引用,對(duì)應(yīng)顯卡驅(qū)動(dòng)的適配,進(jìn)入TURBO C 的圖形開發(fā)方式。第二塊是初始化游戲界面,設(shè)定游戲的范圍在圍墻中,并顯示圍墻。第四塊是退出圖形模式,響應(yīng)用戶任意鍵退出游戲。游戲的主要部分在第三個(gè)模塊中實(shí)現(xiàn),包括隨即產(chǎn)生和顯示食物,蛇的產(chǎn)生、顯示和移動(dòng)。蛇的三種情況的判斷,包括蛇吃食物,蛇會(huì)增長(zhǎng),蛇碰墻或蛇首尾相碰,蛇死退出游戲。整個(gè)小游戲的流程并不復(fù)雜,但對(duì)初學(xué)者還是有一定難度。
由于前面的小游戲是在DOS 下通過調(diào)用TURBO C 的圖形庫(kù)(GRAPHICS.LIB)來(lái)實(shí)現(xiàn)圖形工作方式的,而我們學(xué)習(xí)C++一般采用的是VC++6.0 的開發(fā)環(huán)境,該環(huán)境不支持圖形庫(kù)(GRAPHICS.LIB)。這使得很多DOS 下的C 語(yǔ)言游戲代碼在VC++6.0 中不能通過編譯,我們只能使用WINDOWS API 函數(shù)來(lái)完成圖形的繪制,要求在預(yù)編譯時(shí)包含“WINDOWS.H”,這樣就可以調(diào)用大部分的API 函數(shù),同時(shí)要熟悉WINDOWS 圖形編程中用到的設(shè)備上下文DC(DEVICE CONTEXT),包括創(chuàng)建 DC,創(chuàng)建畫刷,創(chuàng)建畫筆。
在C 語(yǔ)言結(jié)構(gòu)化編程中,代碼是順序執(zhí)行的,有固定的次序。在WINDOWS 消息驅(qū)動(dòng)的工作方式下,我們?yōu)椴煌南?zhǔn)備了不同的處理模塊,在程序運(yùn)行時(shí),程序一旦初始化結(jié)束就進(jìn)入等待消息狀態(tài),依照不同的消息來(lái)觸發(fā)不同處理順序,沒有固定的執(zhí)行次序。程序通過接受特定消息來(lái)結(jié)束程序的運(yùn)行。
(1)VC 工程的建立。在 VC++6.0 建立WIN32APPLICATION 工程,選擇建立典型的“HELLO WORLD”應(yīng)用,可以讓VC 的開發(fā)環(huán)境為我們自動(dòng)生成框架代碼。包括WINDOWS 系統(tǒng)下的主函數(shù)和回調(diào)函數(shù),要做的就是添加和改寫代碼,來(lái)實(shí)現(xiàn)自己的功能。進(jìn)入主函數(shù)后,在創(chuàng)建窗口類時(shí)改寫窗口的外觀、背景和光標(biāo)等樣式。然后,注冊(cè)剛剛創(chuàng)建的窗口類,顯示窗口,進(jìn)入WINDOWS 消息循環(huán)。
(2)對(duì)象化的改造。在DOS 下蛇和食物都是結(jié)構(gòu)體,在 WINDOWS 下改造成類和對(duì)象來(lái)實(shí)現(xiàn)。食物的改造比較簡(jiǎn)單,原來(lái)食物的結(jié)構(gòu)體包括食物出現(xiàn)的橫、縱坐標(biāo)和食物顯示、隱藏的一個(gè)BOOL 值,現(xiàn)在的食物類中不僅要包括上述變量,還要包括對(duì)食物的操作,主要有食物的顯示方法和隱藏方法,通過傳遞當(dāng)前的DC 句柄結(jié)合食物的位置來(lái)顯示和隱藏。食物顯示位置通過隨機(jī)函數(shù)在圍墻內(nèi)生成,食物隱藏發(fā)生在蛇吃掉食物后,在蛇的運(yùn)動(dòng)過程中存在判斷是否吃到食物的情況和是否要重新生成食物,而類的封裝特性不允許直接訪問類的成員變量,即成員變量一般設(shè)置為私有屬性,因此在食物類中有對(duì)應(yīng)的方法來(lái)訪問和設(shè)置到上述屬性。而蛇的改造要稍顯復(fù)雜,原來(lái)蛇的結(jié)構(gòu)體包括兩個(gè)整形的數(shù)組,分別存儲(chǔ)蛇每節(jié)的橫、縱坐標(biāo)。另外三個(gè)整型的變量分別存貯蛇的節(jié)數(shù),蛇的移動(dòng)方向和蛇的生命狀態(tài)。在構(gòu)造蛇類中可以把上述結(jié)構(gòu)體內(nèi)的成員改寫成類中的私有成員變量。在類的構(gòu)造函數(shù)中設(shè)定蛇的初始位置、節(jié)數(shù)、移動(dòng)方向。蛇的運(yùn)動(dòng)中要判斷是否吃到食物,需要有方法得到蛇頭的坐標(biāo)和改變蛇的節(jié)數(shù)的方法。蛇也要有顯示自身的方法和通過隱藏來(lái)顯示蛇運(yùn)動(dòng)效果的方法。蛇碰墻或蛇頭碰蛇尾蛇會(huì)死,蛇類中要有改變蛇生命狀態(tài)的方法。
(3)定時(shí)器的使用。DOS 下的蛇的運(yùn)動(dòng)間隔通過調(diào)用“DELAY”函數(shù)來(lái)實(shí)現(xiàn),在 WIN32APPLICATION中通過設(shè)定定時(shí)器和響應(yīng)定時(shí)事件來(lái)實(shí)現(xiàn)。首先在 WM_PAINT 消息來(lái)時(shí)實(shí)現(xiàn)游戲界面初始化,初始化結(jié)束設(shè)定定時(shí)器,在定時(shí)器事件觸發(fā)時(shí),來(lái)實(shí)現(xiàn)蛇的移動(dòng)的吃食等情況的判斷處理。
(4)蛇的運(yùn)動(dòng)控制。蛇的運(yùn)動(dòng)分為自動(dòng)和手動(dòng),DOS 下的蛇的自動(dòng)根據(jù)實(shí)時(shí)的方向來(lái)移動(dòng),手動(dòng)通過調(diào)用“BIOSKEY”函數(shù)接受鍵盤消息改變蛇頭移動(dòng)方向。在WIN32APPLICATION定時(shí)事件響應(yīng)中來(lái)實(shí)現(xiàn)自動(dòng),在鍵盤的按下或彈起事件中接受鍵盤消息改變蛇頭移動(dòng)方向。
上述要點(diǎn)還有待同學(xué)們?cè)趯?shí)際改造中認(rèn)真領(lǐng)會(huì),老師加以引導(dǎo)。在本案例的基礎(chǔ)上可以進(jìn)一步擴(kuò)充,讓同學(xué)們進(jìn)一步認(rèn)識(shí)到面向?qū)ο缶幊痰奶攸c(diǎn)和優(yōu)勢(shì),比如食物可以設(shè)定不同顏色來(lái)設(shè)定蛇吃到食物加分分值。分別在DOS 下的結(jié)構(gòu)化的C 代碼中改寫,和在 WINDOWS 下的面向?qū)ο蟮腃++中改寫,并加以比較。復(fù)雜一點(diǎn)的,可以對(duì)蛇的外觀和運(yùn)動(dòng)方式加以修改,再加以比較。
案例教學(xué)已經(jīng)是計(jì)算機(jī)教學(xué)的趨勢(shì),在C++教學(xué)的結(jié)束之時(shí),通過一個(gè)小游戲的改編,一方面可以提高同學(xué)們編程的興趣,另一方面可以進(jìn)一步強(qiáng)化面向?qū)ο蟾拍詈退枷搿km然本案例使用的是VC++的開發(fā)環(huán)境,但是在轉(zhuǎn)化過程中并不涉及MFC 框架的使用,可以作為面向?qū)ο蟮腤INDOWS 開發(fā)的入門案例。
1 候俊杰.深入淺出 MFC [M].武漢:華中理工大學(xué)出版社2001 ,5
2 楊正校.新概念車C 語(yǔ)言程序設(shè)計(jì) [M].南京:河海大學(xué)出版社 2008 ,5
3 熊歆斌.Visual C++程序設(shè)計(jì)培訓(xùn)教程 [M].北京:清華大學(xué)出版社.2002 ,7