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