c++ max 的头文件_学用C/C++编写小游戏程序(2.2 打字练习游戏)
2.2 打字練習(xí)游戲(隨機(jī)數(shù)與特殊輸入)
有了上面的繪制簡(jiǎn)單動(dòng)畫(huà)的技術(shù),現(xiàn)在來(lái)看一下簡(jiǎn)易的打字練習(xí)游戲。
【程序2-2】編寫(xiě)一個(gè)簡(jiǎn)易的打字訓(xùn)練游戲:計(jì)算機(jī)每次隨機(jī)生成一個(gè)小寫(xiě)英文字符,從屏幕一行的左側(cè)開(kāi)始逐漸地向右移動(dòng),走過(guò)的位置逐個(gè)顯示為'-'字符。在行走過(guò)程中,如果用戶正確地鍵入這個(gè)字符,則該字符就停止在當(dāng)前位置,輸出'*'字符并響鈴,表示用戶贏了;如果字符從左側(cè)走到幾乎接近于右側(cè)邊界時(shí)(通常的字符窗口為80列,在此設(shè)定為第75列為右界),用戶仍然沒(méi)有正確鍵入這個(gè)字符,則該字符停止在右界處不動(dòng)。用戶鍵入ESC鍵時(shí)可以選擇結(jié)束游戲。
分析這個(gè)游戲中所需的一些操作,有些用前面的知識(shí)已經(jīng)可以寫(xiě)出來(lái)了,有些則需要新的知識(shí)才能處理。
首先來(lái)看動(dòng)畫(huà)輸出字符。根據(jù)上一節(jié)中的繪制簡(jiǎn)單動(dòng)畫(huà)的方法,讓字符從左向右運(yùn)動(dòng)并留下'-'痕跡是很容易的,在循環(huán)中可寫(xiě)以下語(yǔ)句:
cout << "b--" << (char)ch;注意這里因?yàn)槭褂?cout方法,所以不能直接輸出ch(那樣會(huì)把它作為整數(shù)輸出),需要把它強(qiáng)制轉(zhuǎn)換為char類(lèi)型再輸出。
程序中要求“隨機(jī)生成一個(gè)小寫(xiě)英文字符”。這需要學(xué)習(xí)使用標(biāo)準(zhǔn)庫(kù)中與隨機(jī)數(shù)相關(guān)的知識(shí)。
1、隨機(jī)數(shù)相關(guān)函數(shù)
計(jì)算機(jī)程序通常實(shí)現(xiàn)的都是確定性的計(jì)算:給一個(gè)或者一組初始數(shù)據(jù),計(jì)算出一批確定的結(jié)果。然而計(jì)算機(jī)應(yīng)用中有時(shí)也需要帶有隨機(jī)性的計(jì)算,需要用計(jì)算機(jī)生成隨機(jī)數(shù)。例如以下場(chǎng)合:
(1)在程序調(diào)試中需要使用隨機(jī)性數(shù)據(jù)作為試驗(yàn)數(shù)據(jù);
(2)用計(jì)算機(jī)模擬某種實(shí)際情況或過(guò)程,揭示其中的規(guī)律性,使用隨機(jī)數(shù)可以較好地反映客觀過(guò)程的實(shí)際情況。
(3)在游戲程序中需要使用隨機(jī)數(shù)展開(kāi)或控制游戲過(guò)程。
計(jì)算機(jī)實(shí)際上無(wú)法生成真正的隨機(jī)數(shù),只能生成所謂的偽隨機(jī)數(shù):這些數(shù)字并不真正的隨機(jī),但具有類(lèi)似于隨機(jī)數(shù)的統(tǒng)計(jì)特征,如均勻性、獨(dú)立性等。如何用計(jì)算機(jī)生成隨機(jī)性較好的隨機(jī)數(shù)仍是一個(gè)研究問(wèn)題。最簡(jiǎn)單的生成方法是定義一種遞推關(guān)系,通過(guò)它生成一個(gè)數(shù)值序列,設(shè)法使這個(gè)序列中的數(shù)看起來(lái)比較具有隨機(jī)性。
C/C++標(biāo)準(zhǔn)庫(kù)提供了基本的隨機(jī)數(shù)相關(guān)功能。要想使用它們,C++程序頭部應(yīng)包含系統(tǒng)文件cstdlib(而C語(yǔ)言中要求包含頭文件stdlib.h),即在文件頭部寫(xiě)上如下代碼行:
#include <cstdlib>這個(gè)頭文件里描述了與隨機(jī)數(shù)相關(guān)的兩個(gè)函數(shù):
1、隨機(jī)數(shù)種子函數(shù)srand,它的類(lèi)型特征說(shuō)明是:
void srand(unsigned seed)這個(gè)函數(shù)用參數(shù) seed 的值重新設(shè)置種子值,即為生成下一個(gè)隨機(jī)數(shù)而保存的一個(gè)整數(shù)值(由它出發(fā)遞推,取得下一個(gè)隨機(jī)數(shù))。函數(shù)類(lèi)型特征說(shuō)明中的“void”表示這個(gè)函數(shù)沒(méi)有返回值。默認(rèn)的初始種子值是1。用戶可以使用如下語(yǔ)句指定另一個(gè)種子值(例如,10):
srand(10);當(dāng)然,如果每次都使用一個(gè)固定的種子數(shù),那么多次運(yùn)行程序時(shí)所生成的隨機(jī)數(shù)序列總是一模一樣的。為此,一個(gè)常用的技巧是使用標(biāo)準(zhǔn)庫(kù)中的時(shí)間函數(shù)time()取得從威林威治時(shí)間1970年1月1日零時(shí)整開(kāi)始計(jì)時(shí)所經(jīng)過(guò)的時(shí)間秒數(shù),把它視為一個(gè)整數(shù),并用作為種子數(shù)。time()函數(shù)可以使用比較復(fù)雜的實(shí)參,在簡(jiǎn)單使用時(shí),通常以0作為實(shí)參。因此,程序中通常這樣寫(xiě):
srand(time(0));從而可以讓多次運(yùn)行程序時(shí)所生成的隨機(jī)數(shù)序列不同。
而為了使用時(shí)間函數(shù)time(),需要包含標(biāo)準(zhǔn)庫(kù)頭文件ctime或time.h。為此,C++源程序頭部需要寫(xiě)上如下代碼行:
#include <ctime>2、隨機(jī)數(shù)生成函數(shù)rand。它的類(lèi)型特征說(shuō)明是:
int rand(void)這是一個(gè)無(wú)參函數(shù),每次調(diào)用將得到一個(gè)新隨機(jī)整數(shù),其值在0和系統(tǒng)定義的符號(hào)常量RAND_MAX (其值隨系統(tǒng)而不同)之間。例如,在定義了整型變量k之后,可用如下語(yǔ)句調(diào)用該函數(shù):
k = rand();用戶可能實(shí)際需要生成的隨機(jī)數(shù)處于一個(gè)自定義的范圍,則需要對(duì)由rand()產(chǎn)生的隨機(jī)數(shù)進(jìn)行轉(zhuǎn)換。如果希望產(chǎn)生的隨機(jī)數(shù)為整數(shù),且處于整數(shù)區(qū)間[min, max](滿足max - min ≤ RAND_MAX),則可以使用如下語(yǔ)句:
k = rand() % (max + 1 - min) + min;如果希望產(chǎn)生的隨機(jī)數(shù)為小數(shù),且處于實(shí)數(shù)區(qū)間[dmin, dmax](滿足max - dmin ≤ RAND_MAX),則可以使用如下語(yǔ)句(假設(shè)已定義了double類(lèi)型的變量x):
x = double(rand()) / RAND_MAX * (dmax - dmin) + dmin;以上介紹了用標(biāo)準(zhǔn)庫(kù)函數(shù)中的隨機(jī)函數(shù)生成整數(shù)和小數(shù)。但是怎么生成一個(gè)小寫(xiě)英文字符呢?這就需要兩點(diǎn)知識(shí):
(1)計(jì)算機(jī)系統(tǒng)中常用的是ASCII字符集,其中的小寫(xiě)英文字符的編碼是97~122(即小寫(xiě)字母'a'的編碼是97,其它字母的編碼依次增加,直到小寫(xiě)字母'z'的編碼為122)。
(2)在C/C++系統(tǒng)中,ASCII字符可以視為范圍在[0, 127]內(nèi)的數(shù)字來(lái)使用。
因此,假設(shè)程序中用變量ch存儲(chǔ)生成的字符,則可用如下方式實(shí)現(xiàn)隨機(jī)生成一個(gè)小寫(xiě)英文字符:
int ch; ch = rand() % ('z' + 1 - 'a') + 'a';請(qǐng)注意其中的變量ch被定義為int類(lèi)型而非char類(lèi)型。后面章節(jié)中將會(huì)解釋原因。
2、特殊輸入函數(shù)kbhit和getch
此程序的難點(diǎn)是:如何讓程序在自動(dòng)地以動(dòng)畫(huà)效果輸出字符的同時(shí),又能接受用戶鍵入字符呢?讀者一般都已知道多種輸入操作方法:在C++中通常用“cin >>”進(jìn)行流式輸入;在C和C++中都可以用標(biāo)準(zhǔn)庫(kù)中的格式化輸入函數(shù)scanf或字符輸入函數(shù)getchar”。但是這些輸入操作都是阻塞式的:程序運(yùn)行到使用這些方法進(jìn)行輸入的語(yǔ)句時(shí),就會(huì)停止下來(lái)什么都不做,等待用戶進(jìn)行輸入;用戶鍵入的所有字符都會(huì)回顯在屏幕上;只有等用戶按下回車(chē)鍵完成輸入之后,程序才會(huì)繼續(xù)往下執(zhí)行。因此這些輸入操作方法不適用于這個(gè)游戲程序。
為了實(shí)現(xiàn)程序的功能,需要用到兩個(gè)非標(biāo)準(zhǔn)庫(kù)中的函數(shù)kbhit和getch。
在Windows平臺(tái)上發(fā)行的C/C++編譯器和集成開(kāi)發(fā)環(huán)境,通常都包含了一些非標(biāo)準(zhǔn)庫(kù)(擴(kuò)充庫(kù))函數(shù),其中使用較多的頭文件就是conio.h(其名稱是“Console Input/Output,控制臺(tái)輸入輸出”的簡(jiǎn)寫(xiě)),在該頭文件中聲明了通過(guò)控制臺(tái)進(jìn)行數(shù)據(jù)輸入和數(shù)據(jù)輸出的函數(shù)。如果要使用該頭文件中所聲明的函數(shù),就需要在程序中包含該頭文件,即在源程序開(kāi)始處寫(xiě)如下的代碼行:
#include <conio.h>kbhit函數(shù)(名字來(lái)源于英文“keyboard hit”的縮寫(xiě))用于非阻塞地響應(yīng)鍵盤(pán)輸入事件。它將檢查當(dāng)前是否有鍵盤(pán)輸入,若有就返回一個(gè)非0值,否則返回0。也可以通過(guò)該函數(shù)順便獲得一個(gè)字符,但并不顯示在屏幕上。
getch函數(shù)的功能是從控制臺(tái)讀取一個(gè)字符,但并不顯示在屏幕上。它的常見(jiàn)用法有兩種:
getch();或
int ch; //或 char ch; ch = getch();前一用法并不關(guān)心用戶的實(shí)際輸入,可用于讓程序暫停并等待用戶按任意鍵后繼續(xù)執(zhí)行。后一用法導(dǎo)致程序等待用戶按鍵,并將把實(shí)際輸入字符所對(duì)應(yīng)的編碼賦給ch,然后繼續(xù)執(zhí)行。無(wú)論是哪種用法,getch()執(zhí)行時(shí)都會(huì)一直等待直到用戶按下某個(gè)鍵。用戶不按鍵時(shí)該函數(shù)不會(huì)返回,程序也就不會(huì)向下執(zhí)行,所以這個(gè)函數(shù)也是相當(dāng)于一個(gè)阻塞函數(shù)。
在編寫(xiě)字符界面的小游戲時(shí)常常需要組合使用kbhit和getch這兩個(gè)函數(shù)。一種簡(jiǎn)單的寫(xiě)法是:
if (kbhit())ch = getch();即在用kbhit檢測(cè)到鍵盤(pán)輸入時(shí),就用getch讀入一個(gè)字符。
順便看一個(gè)小例子:如果需要對(duì)編號(hào)為0 ~ n-1的n個(gè)人進(jìn)行一次抽獎(jiǎng),就需要在屏幕上連續(xù)隨機(jī)顯示編號(hào),按下任意鍵時(shí)停止??捎萌缦麓a片段實(shí)現(xiàn)這一功能:
int n = 1000; srand(time(0)); do {cout << "bbb" << rand() % n; //"b"是控制輸出時(shí)向左退回一個(gè)字符 } while (!kbhit());3、打字練習(xí)游戲程序
有了上面的分析,大致地可以寫(xiě)出程序的主體結(jié)構(gòu)如下:
定義所需的變量 while (用戶鍵入字符不是ESC鍵) {產(chǎn)生一個(gè)新的小寫(xiě)英文字符;for (從左邊界開(kāi)始; 尚未到達(dá)右邊界; 變量自增) {以動(dòng)畫(huà)形式向右繪制字符如果玩家按鍵讀入字符并進(jìn)行處理(字符正確則此局贏)}如果用戶鍵入ESC鍵則再次確認(rèn)是否退出如果已到達(dá)右邊界則此局輸 } 游戲結(jié)束查閱ASCII碼表可知,其中編碼為7的特殊字符代表“響鈴”,使用時(shí)可以用轉(zhuǎn)換描述的形式寫(xiě)為'b';輸出這個(gè)字符就實(shí)現(xiàn)響鈴操作。需要注意的是,響鈴操作耗時(shí)較長(zhǎng),程序中只能少量地使用它(例如本程序中是每次打字成功時(shí)響鈴一次),不過(guò)太頻繁地使用它。
而編碼為27的特殊字符代表ESC鍵,在程序中可以直接用字符值與數(shù)值27進(jìn)行比較。。
據(jù)此寫(xiě)出完整的源程序如下:
//https://gitee.com/devcpp/cgames anbangli@foxmail.com GNU GPL v3 //cgame2-2(type).cpp 字符橫向移動(dòng)的打字游戲 #include <iostream> #include <cstdlib> #include <ctime> #include <windows.h> //非標(biāo)準(zhǔn)庫(kù)函數(shù) Sleep 所需的頭文件 #include <conio.h> //非標(biāo)準(zhǔn)庫(kù)函數(shù) kbhit 和 getch 所需的頭文件 using namespace std;int main() {const int ESCKEY = 27; //定義整型常量ESCKEY,賦值為ESC鍵的ASCII編碼int pos, posmax = 72; //當(dāng)前位置,右邊界最大位置int win = 0, loss = 0; //已贏局?jǐn)?shù)和已輸局?jǐn)?shù)cout << "打字游戲(按回車(chē)鍵開(kāi)始,游戲過(guò)程中按 ESC 結(jié)束)" << endl;getchar();int ch = 0, key = 0; //隨機(jī)字符,玩家鍵入字符srand(time(0)); //設(shè)置隨機(jī)數(shù)種子while (key != ESCKEY) { //主循環(huán)。key 不是 ESC鍵時(shí)玩游戲ch = rand() % ('z' + 1 - 'a') + 'a'; //產(chǎn)生隨機(jī)字符for (pos = 0; pos < posmax && key != 27; pos++) {cout << "b--" << (char)ch;pos++;Sleep(150);if (kbhit() && (key = getch()) == ch) {win++;cout << "*a"; //輸出 * 并響鈴break;}}if (key == ESCKEY) { //用戶鍵入ESC鍵,需要確認(rèn)cout << "n結(jié)束游戲嗎?(y/n)";while ((key = tolower(getchar())) != 'y' && ch != 'n'); //空循環(huán)體key = (key == 'y' ? ESCKEY : 0); //如果為'y'則改為 ESCKEY,用于控制主循環(huán)}if (pos >= posmax) { //到達(dá)右邊界loss ++;}cout << endl;}cout << "字符練習(xí)個(gè)數(shù):" << win + loss << " 正確鍵入個(gè)數(shù):" << win << endl;cout << "游戲結(jié)束,謝謝使用" << endl;return 0; }如果用戶多次使用這個(gè)打字游戲程序,會(huì)覺(jué)得這個(gè)游戲的基本功能還是可以的,但是比市場(chǎng)上的其它打字程序相比,還有所欠缺,還有很多可以改進(jìn)之處:
(1)現(xiàn)在的字符是從左向右移動(dòng),能不能讓字符從上往下運(yùn)動(dòng)?
(2)每次只能顯示一個(gè)字符進(jìn)行訓(xùn)練,能不能同時(shí)顯示多個(gè)字符?
(3)每次只是在打字成功時(shí)響鈴一次,能不能播放其它聲音?或者在整個(gè)打字游戲過(guò)程中都播放音樂(lè)?
這些功能都是可以考慮增加的功能。但是需要學(xué)習(xí)和使用更多的編程技巧。例如要想讓字符從上往下運(yùn)動(dòng)就需要學(xué)習(xí)更多的字符輸出控制(見(jiàn)下一章中的gotoxy函數(shù)),要同時(shí)顯示多個(gè)字符則需要在程序中學(xué)習(xí)使用數(shù)組。至于播放背景音樂(lè),我覺(jué)得超出了本書(shū)涵蓋的內(nèi)容,所以在此不作介紹。
還有,讀者在運(yùn)行這些程序時(shí),可能會(huì)覺(jué)得程序運(yùn)行時(shí)的控制臺(tái)窗口中的字符比較小,看起來(lái)不夠舒服。這是因?yàn)閃indows系統(tǒng)默認(rèn)的控制臺(tái)窗口中的字體是點(diǎn)陣字體,字體大小為16磅。在此順便要說(shuō)到另一個(gè)常規(guī)的操作:調(diào)整控制臺(tái)窗口的字體和字號(hào)。具體操作如下:
1、在控制臺(tái)窗口的標(biāo)題欄上點(diǎn)擊鼠標(biāo)右鍵,在彈出菜單中點(diǎn)擊“默認(rèn)值”(如下面左圖所示);
2、在彈出的“控制臺(tái)窗口 屬性”對(duì)話框中(如下面右邊所示),在“字體”選項(xiàng)卡下,在字體列表中選擇“
新宋體”,并在“大小”列表中選擇24或28磅。點(diǎn)擊“確定”按鈕關(guān)閉此對(duì)話框。
3、關(guān)閉當(dāng)前控制臺(tái)窗口。在將來(lái)所有的控制臺(tái)窗口中將會(huì)使用調(diào)整后的字體和字號(hào)。
總結(jié)
以上是生活随笔為你收集整理的c++ max 的头文件_学用C/C++编写小游戏程序(2.2 打字练习游戏)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pythonunicode转为字符串_p
- 下一篇: l源码安装mysql升级_[Linux]