贪吃蛇游戏(c/c++)
? ? 根據以前玩的貪吃蛇游戲,它的核心在于實現動態的蛇:首先為了將蛇動態的描述出來,通過不斷的輸出,清屏,修改,再輸出這樣的循環來實現動畫的效果,動畫本身就是由一張張圖片表現出來的。
? ? 下一步需要一個類,它能存儲要輸出的數據,游戲界面包括四周的墻壁以及蛇的展示,采用一個二維字符數組來完整表示,設定蛇頭為‘#’,蛇身為‘*’,想一想,當要描述蛇在不斷前進時,如何實現蛇下一步所在位置字符的變化?根據當前的方向值,以蛇向右直行為例,計算出下一步的蛇頭坐標,x方向加1,y不變,更新新蛇頭(變為'#'),舊蛇頭('#'變為'*'),舊蛇尾(‘*’變為‘‘)所在位置的字符。在這更新的過程中,需要得到舊蛇頭舊蛇尾的坐標,新蛇尾仍然還是'*',保持不變,但下一次又需要新蛇尾的坐標(變為空字符),以此類推,需要將蛇的所有坐標都存儲起來。
????創建一個只包含坐標x和坐標y的簡單類,用這個類的數組來保存蛇身上每個點的坐標值,并不關心當前坐標上的字符是'#'還是'*',只起到存儲作用。蛇頭和蛇尾是這兩個類之間的紐帶。按照數組序號依次遞增,記錄了蛇不斷爬行的坐標,成為蛇爬行的痕跡。
?
? ? 注意:
1,全局變量的聲明應放在other.cpp(存放類方法定義的文件)中,放在.h文件中會造成多重定義,因為main.cpp和other.cpp中均包含頭文件。
2,使用getch()函數(在vs中強制使用_getch(),效果不變)來讀取用戶的輸入,如果要使用getchar()函數,那就需要在每一次使用之前清除緩沖區。因為每次從鍵盤輸入一個字符時,換行符殘留在緩沖區中,會干擾下一次的讀取。
3,在up_data方法中,為什么采用兩次_getch()來讀取鍵盤上的方向鍵,因為根據鍵盤掃描碼,實際鍵盤的一次按鍵并非是想象中如ASC||碼中的8位,而是16位。 第一次_getch()接受低8位的數值,第二次_getch()接受高8位的值,例如:字符'a' ?0x1e61, ? ? 'b' 0x3062, ? ?'c' ?0x2e63 ? ? ? ? ?普通字符按鍵的低8位值和其ASC||碼相同。但是四個方向鍵的值和ASC碼值不同 ↑ 0x4800, ? ?↓ 0x5000, ?← 0x4b00, ?→ ?0x4d00 ?,因此主要獲取第二次的_getch()返回值。
4,提示:按一次空格鍵暫停,按兩次空格鍵恢復。
頭文件:
#ifndef HEADER_H_ #define HEADER_H_ #define N 22 #include<iostream> #include<cstdlib>//食物的隨機分配rand() #include<ctime>//蛇的速度,等級clock() #include<conio.h>//控制臺_getch(),_kbhit()函數的使用 class positions//保存坐標,有一點要清楚,走的是留下的痕跡 { public:int x, y;void initialize(int&);//存儲蛇最初的位置坐標 };class Snake//可以再進行添加別的元素以使得游戲更加有趣 { private:char s[N][N];//用于保存游戲界面信息char direction;int head, tail;int gamespeed,grade; public:Snake(int h = 4, int t = 1, char d = 77, int g = 400) :head(h), tail(t), direction(d), gamespeed(400){}void initialize();void setfood();void getgrade();void show_game();bool updata_game(); }; #endifother.cpp文件
#include"header.h" using std::cout; using std::endl; using std::cin; bool gameover; char key; int xh, yh;//蛇頭位置坐標 int xf, yf;//食物坐標點 positions snakexy[(N - 2)*(N - 2)];//建立一個position類的數組 void positions::initialize(int& a) {x = 1;y = a; } void Snake::initialize() {int i, j;for (i = 0; i < N; i++)for (j = 0; j < N; j++){if (i == 0 || i == N - 1)s[i][j] = '-';elses[i][j] = ' ';}for (i = 1; i < N - 1; i++){s[i][0] = '|';s[i][N - 1] = '|';}for (j = 1; j < 4; j++)s[1][j] = '*';s[1][4] = '#'; } void Snake::setfood() {srand(time(0));while (1){xf = rand() % N;yf = rand() % N;if (s[xf][yf] == ' '){s[xf][yf] = '*';break;}} } void Snake::getgrade() {cout << "\n\n\n\n\t\t\t1:Grade speed 500"<< "\n\n\t\t\t1:Grade speed 250" << "\n\n\t\t\t3:Grade speed 125" << "\n\n\t\t\t4:Grade speed 50";cout << "\n\n\n\t\tPlease choose the grade(1 or 2 or 3 or4)";while (cin >> grade){if (grade == 1 || grade == 2 || grade == 3 || grade == 4)break;else{cout << "Input error!and input again..\n";}}switch (grade){case 1:gamespeed = 500;break;case 2:gamespeed = 250;break;case 3:gamespeed = 125;break;case 4:gamespeed = 50;} } void Snake::show_game() {system("CLS");cout << endl;cout << "\t\tHello,snake is waiting for you!!\n\n";int i, j;for (i = 0; i < N; i++){cout << '\t';for (j = 0; j < N; j++){cout << s[i][j]<< ' ';}if (i == 6)cout << "\t Speed: " << gamespeed;if (i == 10)cout << "\t Pause: press the space key!";if (i == 14)cout << "\t Recover: press the space key twice!!";cout << endl;} } bool Snake::updata_game() {gameover = 1;key = direction;long tt = clock();while ((gameover=(clock() - tt) <= gamespeed) && !_kbhit());//gamespeed實際上是作為每次蛇自動前進的時間間隔,gamespeed越小,速度越快。//在while語句中,若存在擊鍵,此時產生的時間之差肯定是小于設定的時間間隔的,gameover仍為1(真)繼而讀取鍵盤輸入;//否則等待時間之差越來越大,便會跳出while循環,gameover=0,使用上一次的方向;if (gameover){_getch();key = _getch();//獲取擊鍵的值}if (key == ' ')//空格暫停{while (_getch() != ' ')continue;}elsedirection = key;switch (direction)//計算下一步要顯示的蛇頭的坐標{case 72:xh = snakexy[head].x - 1;yh = snakexy[head].y;break;case 80:xh = snakexy[head].x + 1;yh = snakexy[head].y;break;case 77:xh = snakexy[head].x;yh = snakexy[head].y + 1;break;case 75: xh = snakexy[head].x;yh = snakexy[head].y - 1;}if (direction != 72 && direction != 80 && direction != 75 && direction != 77)gameover = 0;else if (xh == 0 || xh == N - 1 || yh == 0 || yh == N - 1)//碰到墻壁gameover = 0;else if (s[xh][yh] != ' '&&xh != xf&&yh != yf)//碰到蛇自己gameover = 0; else if (xh == xf&&yh == yf)//吃到食物{s[xh][yh] = '#';s[snakexy[head].x][snakexy[head].y] = '*';head = (head + 1) % ((N - 1)*(N - 2));snakexy[head].x = xh;snakexy[head].y = yh;setfood();gameover = 1;}else{//snakexy[head].x = xh;//snakexy[head].y = yh;//s[snakexy[head].x][snakexy[head].y] = '#';s[xh][yh] = '#';s[snakexy[head].x][snakexy[head].y] = '*';head = (head + 1) % ((N - 1)*(N - 2));snakexy[head].x = xh;snakexy[head].y = yh;s[snakexy[tail].x][snakexy[tail].y] = ' ';tail = (tail + 1) % ((N - 1)*(N - 2));gameover = 1;}return gameover; }main.cpp文件:
#include"header.h" int main() {using namespace std;extern positions snakexy[(N - 2)*(N - 2)];char input = 'y';bool live = 1;while (input == 'y'){ system("CLS");cout << "\n\n\n\n\n\n\n\n\n\t\t\tWelcome to the snakes.\n";cout << "\n\n\n\t\tAny key you push and the game will go...\n";_getch();system("CLS");Snake snake;snake.getgrade();snake.initialize();for (int i = 1; i <= 4; i++)snakexy[i].initialize(i);//存儲最初蛇的坐標。snake.setfood();while (live){snake.show_game();live = snake.updata_game();}system("CLS");cout << "\n\n\n\t\t\tGameover!\n\n" << endl;cout << "\n\n\n\t\t Want to continue ? y or n.\n\t\t\t\t";cin>> input;live = 1;}return 0; }?下面是用Qt寫出的貪吃蛇游戲截圖:
貓吃蛇?
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的贪吃蛇游戏(c/c++)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Qt文档趣事
- 下一篇: 插入排序之——直接插入排序(c/c++)