# 小恐龍專題 ## 修改部分 ### 遊戲介面及規則 * 增加遊戲封面以及遊戲結束的畫面,按下空白鍵開始遊戲或重玩。 * 增加顏色顯示 * 另外分數的部分要跳過障礙物或是破壞障礙物才能得分 * 分數每多200分,地圖會加速一點點。 ### 功能部分 * 增加了**無敵星星道具**,地圖上隨機增加 * 符號,當角色碰到時會變成 O) ,並獲得30秒無敵效果。 * 增加了**迴力鏢道具**,當使用者按下B按鍵時,丟出迴力鏢,沿途壞障礙物並進入道具**冷卻時間(50秒)**,p.s **(要謹慎使用,因為迴力鏢也會把無敵星星破壞掉)**,另外之所以叫做迴力鏢是因為它會飛回來,而這時也要**躲避**飛回來的迴力鏢,否則就死掉了。 * 增加了**旋風砲**道具,當使用者按下C按鍵時,發射旋風砲彈,破壞**全地圖所有障礙物(包含無敵星星以及飛回來的迴力鏢)** 並進入道具**冷卻時間(120秒)** --- ## 遊戲介面及規則 ### 遊戲封面以及結束畫面 ```c++= void display_start(void) { system("cls"); printf("\t __\n"); printf("\t / _) __\033[33mHello!!!\033[0m\n"); printf("\t _.----._/ / \n"); printf("\t / / \n"); printf("\t __/ ( | ( |\n"); printf("\t/__.-'|_|--|_|\n"); printf("\n\n\t"); printf("\033[36mWelcome to the Dino Game!\n\n\n\033[0m"); printf("\tPress Space to start the game!\n"); return; } void display_gameover(Dino* MyDino) { system("cls"); printf("\n\n\t"); printf("\033[31mGame Over!\033[0m\n\n\n"); printf("\tYour final score is: \033[33m%d\033[0m\n\n", MyDino->score); printf("\tPress Space to play again.\n"); // 加入等待按下空白鍵的功能 while (!_kbhit() || _getch() != 32) { Sleep(100); } return; } ``` ### 遊戲封面 ![](https://i.imgur.com/1z2Ktq2.png) ### 結束畫面 ![](https://i.imgur.com/Obpc2Pk.png) ### 顏色顯示範例 ```c++= printf("\033[36mWelcome to the Dino Game!\n\n\n\033[0m"); ``` ### 跳過障礙物或是破壞障礙物才可以得分 ```C++= //跳過了障礙物才能加分 (10分) if (MyDino->jump_time_left != 0 && MyDino->road[DINO_PLACE] == 'X') { MyDino->score += 10; } //破壞障礙物加分 (20分) if (MyDino->jump_time_left == 0 && MyDino->road[DINO_PLACE] == '.') { MyDino->score += 20; } ``` ### 地圖加速 ```C++= void move(Dino* MyDino) { for (int i = 0; i < ROAD_LENGTH - 1; i++) { MyDino->road[i] = MyDino->road[i + 1]; } // 加入根據分數增加小恐龍速度的功能 if (MyDino->score > 0 && MyDino->score % 200 == 0) { MyDino->wait_time -= 10; } MyDino->road[ROAD_LENGTH - 1] = '_'; } ``` --- ## 功能部分 ## 無敵星星功能 ### 碰到無敵星星時,障礙物會變成 . 角色可直接穿過(表示破壞障礙物) ```C++= //當碰到無敵星星時,障礙物會變成 '.' 且角色可直接穿過(加20分) if (MyDino->star_time > 0) { MyDino->star_time -= 1; for (int i = 0; i < ROAD_LENGTH; i++) { if (MyDino->road[i] == 'X') { MyDino->road[i] = '.'; } } } ``` ### 碰到無敵星星時,改變角色型態 ```C++= if (MyDino->star_time != 0) { printf("\033[33mO)\033[0m"); } else { printf("O"); } ``` ### * 產生 ```C++= bool spawn_star(Dino* MyDino) { int random_number = rand() % 100; if (random_number < MyDino->star_chance) return true; return false; } ``` ### 判斷是否有吃到無敵星星 ```C++= bool star_bumped(Dino* MyDino) { return MyDino->jump_time_left == 0 && MyDino->road[DINO_PLACE] == '*'; } ``` ### 出現無敵星星 ```C++= if (spawn_star(MyDino)) { MyDino->road[ROAD_LENGTH - 1] = '*'; } ``` ### 判斷是否為無敵時間 ```C++= if (is_bumped(MyDino)) { if (MyDino->star_time != 0) { display(MyDino); } else { display_gameover(MyDino); // 遊戲結束,顯示遊戲結束畫面 break; } } ``` ### 無敵星星展示畫面 ![](https://i.imgur.com/y6E1dZk.png) --- ## 迴力鏢功能 ### 當B按鍵按下 ```C++= bool b_pressed(void) { return _kbhit() != 0 && _getch() == 66; } ``` ### 顯示迴力鏢 ```C++= // 顯示迴力鏢 else if (MyDino->boomerangright > 0 && i == MyDino->boomerangright) { printf("\033[36m>\033[0m"); } ``` ### 迴力鏢破壞沿途障礙物(包含無敵星星) ```c++= // 迴力鏢破壞沿途障礙物(包含 * 無敵星星) if (MyDino->boomerangright > 0 && MyDino->boomerangright < ROAD_LENGTH) { MyDino->boomerangright++; MyDino->boomerang_count--; if (MyDino->road[MyDino->boomerangright] == 'X' || MyDino->road[MyDino->boomerangright] == '*') { MyDino->road[MyDino->boomerangright] = '.'; } if (MyDino->road[MyDino->boomerangright - 1] == 'X' || MyDino->road[MyDino->boomerangright - 1] == '*') { MyDino->road[MyDino->boomerangright - 1] = '.'; } } // 迴力鏢到底時返回 else if (MyDino->boomerangright == ROAD_LENGTH) { MyDino->boomerangright = 0; MyDino->boomerang_count = 0; MyDino->road[ROAD_LENGTH - 1] = '<'; } if (MyDino->key == 'B' && MyDino->boomerangright == 0) { // continue; MyDino->boomerangright = DINO_PLACE; MyDino->boomerang_count = 50; } ``` ### 顯示迴力鏢可用及冷卻 ```c++= // 迴力鏢可用及冷卻顯示 if (MyDino->boomerangright == 0) { printf("\033[42;37m\n\t\tBoomerang Available : Press \033[30mB\033[42;37m to use it\n\033[0m"); } else if (MyDino->boomerangright != 0 && MyDino->key == 'B') { printf("\033[47;30m\n\t\tBoomerang Cooling : %d\n\033[0m", MyDino->boomerang_count); } else if (MyDino->boomerangright != 0) { printf("\033[41;37m\n\t\tWARRNING!!!\n\033[0m \t\t\033[41;37mWATCH OUT for your Boomerang WHEN IT FLIES BACK!!!\n\033[0m"); printf("\033[43;31m\n\t\tBoomerang Cooling : %d\n\033[0m", MyDino->boomerang_count); } ``` ### 迴力鏢展示畫面 ![](https://i.imgur.com/O8cizsn.png) ![](https://i.imgur.com/ERcZk6P.png) --- ## 旋風炮功能 ### 當C按鍵按下 ```C++= // C鍵按下 bool c_pressed(void) { return _kbhit() != 0 && _getch() == 67; } ``` ### 顯示旋風砲 ```C++= // 顯示旋風砲 else if (MyDino->cannon_time == 119 && i > DINO_PLACE) { printf("\033[43;31m!\033[0m"); } ``` ### 旋風炮函式 ```C++= // 旋風砲函式 void cannon(Dino* MyDino) { if (MyDino->key == 'C' && MyDino->cannon_time == 0) { for (int i = DINO_PLACE + 1; i < ROAD_LENGTH; i++) { if (MyDino->road[i] == 'X' || MyDino->road[i] == '*' || MyDino->road[i] == '<') { MyDino->road[i] = '.'; } } MyDino->cannon_time = 120; // 設定冷卻時間為120秒 } if (MyDino->cannon_time > 0) { MyDino->cannon_time--; // 每次執行,冷卻時間減1 } } ``` ### 顯示旋風炮可用及冷卻 ```C++= // 旋風砲可用及冷卻顯示 if (MyDino->cannon_time == 0) { printf("\033[42;37m\n\t\tCannon Available : Press \033[30mC\033[42;37m to use it\n\033[0m"); } else if (MyDino->cannon_time != 0 && MyDino->key == 'C') { printf("\033[47;30m\n\t\tCannon Cooling : %d\033[0m", MyDino->cannon_time); } else if (MyDino->cannon_time != 0) { printf("\033[43;31m\n\t\tCannon Cooling : %d\033[0m", MyDino->cannon_time); } ``` ### 旋風炮展示畫面 ![](https://i.imgur.com/5k7Dbgb.png) --- ## 完整程式碼 ```C++ #include <stdio.h> #include <stdlib.h> #include <stdbool.h> #include <windows.h> #include <time.h> #define ROAD_LENGTH 50 // 路面長度 #define DINO_PLACE 6 // 小恐龍在路面上的第幾格 struct dino { char road[ROAD_LENGTH + 1]; // 字串結尾需要'\0' int jump_time_left; // 還剩多久掉回地面 int score; // 分數 int wait_time; // 每次迴圈之間等待的時間 int barrier_chance; // 放置障礙物的機率 int star_chance; // 無敵星星的機率 int star_time; // 無敵倒數 int boomerangright; // 迴力鏢位置 int boomerang_count; // 迴力鏢冷卻 int cannon_time; // 旋風砲冷卻 int key; // 按鍵 }; typedef struct dino Dino; bool space_pressed(void) { return _kbhit() != 0 && _getch() == 32; } int keyboard() { if (_kbhit()) { return _getch(); } else { return -1; } } // B鍵按下 bool b_pressed(void) { return _kbhit() != 0 && _getch() == 66; } // C鍵按下 bool c_pressed(void) { return _kbhit() != 0 && _getch() == 67; } void move(Dino* MyDino) { for (int i = 0; i < ROAD_LENGTH - 1; i++) { MyDino->road[i] = MyDino->road[i + 1]; } // 加入根據分數增加小恐龍速度的功能 if (MyDino->score > 0 && MyDino->score % 200 == 0) { MyDino->wait_time -= 10; } MyDino->road[ROAD_LENGTH - 1] = '_'; } Dino* init(void) { Dino* MyDino = (Dino*)malloc(sizeof(Dino)); if (MyDino != NULL) { MyDino->score = 0; MyDino->jump_time_left = 0; MyDino->wait_time = 150; MyDino->barrier_chance = 10; MyDino->star_chance = 1; MyDino->star_time = 0; MyDino->boomerangright = 0; MyDino->boomerang_count = 50; MyDino->cannon_time = 0; for (int i = 0; i < ROAD_LENGTH; i++) { MyDino->road[i] = '_'; } MyDino->road[ROAD_LENGTH] = '\0'; } return MyDino; } void display_start(void) { system("cls"); printf("\t __\n"); printf("\t / _) __\033[33mHello!!!\033[0m\n"); printf("\t _.----._/ / \n"); printf("\t / / \n"); printf("\t __/ ( | ( |\n"); printf("\t/__.-'|_|--|_|\n"); printf("\n\n\t"); printf("\033[36mWelcome to the Dino Game!\n\n\n\033[0m"); printf("\tPress Space to start the game!\n"); return; } void display_gameover(Dino* MyDino) { system("cls"); printf("\n\n\t"); printf("\033[31mGame Over!\033[0m\n\n\n"); printf("\tYour final score is: \033[33m%d\033[0m\n\n", MyDino->score); printf("\tPress Space to play again.\n"); // 加入等待按下空白鍵的功能 while (!_kbhit() || _getch() != 32) { Sleep(100); } return; } void display(Dino* MyDino) { system("cls"); printf("\n\n\t"); for (int i = 0; i < ROAD_LENGTH; i++) { if (i == DINO_PLACE && MyDino->jump_time_left > 0) { if (MyDino->star_time != 0) { printf("\033[33mO)\033[0m"); } else { printf("O"); } } else { printf(" "); } } printf("\n\t"); for (int i = 0; i < ROAD_LENGTH; i++) { if (i == DINO_PLACE && MyDino->jump_time_left == 0) { if (MyDino->star_time != 0) { printf("\033[33mO)\033[0m"); } else { printf("O"); } } // 顯示迴力鏢 else if (MyDino->boomerangright > 0 && i == MyDino->boomerangright) { printf("\033[36m>\033[0m"); } // 顯示旋風砲 else if (MyDino->cannon_time == 119 && i > DINO_PLACE) { printf("\033[43;31m!\033[0m"); } else { printf("%c", MyDino->road[i]); } } printf("\n\n\n\t"); printf("\t\tCurrent Score : %d\n", MyDino->score); if (MyDino->star_time != 0) { printf("\033[47;30m\n\t\t\tInvincibility Countdown : %d\n\033[0m", MyDino->star_time); } // 迴力鏢可用及冷卻顯示 if (MyDino->boomerangright == 0) { printf("\033[42;37m\n\t\tBoomerang Available : Press \033[30mB\033[42;37m to use it\n\033[0m"); } else if (MyDino->boomerangright != 0 && MyDino->key == 'B') { printf("\033[47;30m\n\t\tBoomerang Cooling : %d\n\033[0m", MyDino->boomerang_count); } else if (MyDino->boomerangright != 0) { printf("\033[41;37m\n\t\tWARRNING!!!\n\033[0m \t\t\033[41;37mWATCH OUT for your Boomerang WHEN IT FLIES BACK!!!\n\033[0m"); printf("\033[43;31m\n\t\tBoomerang Cooling : %d\n\033[0m", MyDino->boomerang_count); } // 旋風砲可用及冷卻顯示 if (MyDino->cannon_time == 0) { printf("\033[42;37m\n\t\tCannon Available : Press \033[30mC\033[42;37m to use it\n\033[0m"); } else if (MyDino->cannon_time != 0 && MyDino->key == 'C') { printf("\033[47;30m\n\t\tCannon Cooling : %d\033[0m", MyDino->cannon_time); } else if (MyDino->cannon_time != 0) { printf("\033[43;31m\n\t\tCannon Cooling : %d\033[0m", MyDino->cannon_time); } return; } bool is_bumped(Dino* MyDino) { if (MyDino->star_time != 0) { return MyDino->jump_time_left == 0 && MyDino->road[DINO_PLACE] == '.'; } else { return MyDino->jump_time_left == 0 && (MyDino->road[DINO_PLACE] == 'X' || MyDino->road[DINO_PLACE] == '<'); } } bool spawn_barrier(Dino* MyDino) { int random_number = rand() % 100; if (random_number < MyDino->barrier_chance) return true; return false; } bool star_bumped(Dino* MyDino) { return MyDino->jump_time_left == 0 && MyDino->road[DINO_PLACE] == '*'; } bool spawn_star(Dino* MyDino) { int random_number = rand() % 100; if (random_number < MyDino->star_chance) return true; return false; } // 旋風砲函式 void cannon(Dino* MyDino) { if (MyDino->key == 'C' && MyDino->cannon_time == 0) { for (int i = DINO_PLACE + 1; i < ROAD_LENGTH; i++) { if (MyDino->road[i] == 'X' || MyDino->road[i] == '*' || MyDino->road[i] == '<') { MyDino->road[i] = '.'; } } MyDino->cannon_time = 120; // 設定冷卻時間為120秒 } if (MyDino->cannon_time > 0) { MyDino->cannon_time--; // 每次執行,冷卻時間減1 } } int main() { /* 初始化 */ srand(time(NULL)); Dino* MyDino = init(); display_start(); // 新增遊戲開始畫面 /* 遊戲本體 */ while (true) { /* 開始遊戲 */ if (space_pressed()) { display(MyDino); /* 遊戲循環 */ while (true) { /* 遊戲邏輯 */ MyDino->key = keyboard(); if (MyDino->key == 32 && MyDino->jump_time_left == 0) { MyDino->jump_time_left = 3; } move(MyDino); cannon(MyDino); if (spawn_barrier(MyDino)) { if (MyDino->star_time != 0) { MyDino->road[ROAD_LENGTH - 1] = '.'; } else { MyDino->road[ROAD_LENGTH - 1] = 'X'; } } if (MyDino->jump_time_left > 0) MyDino->jump_time_left -= 1; if (is_bumped(MyDino)) { if (MyDino->star_time != 0) { display(MyDino); } else { display_gameover(MyDino); // 遊戲結束,顯示遊戲結束畫面 break; } } // 迴力鏢破壞沿途障礙物(包含 * 無敵星星) if (MyDino->boomerangright > 0 && MyDino->boomerangright < ROAD_LENGTH) { MyDino->boomerangright++; MyDino->boomerang_count--; if (MyDino->road[MyDino->boomerangright] == 'X' || MyDino->road[MyDino->boomerangright] == '*') { MyDino->road[MyDino->boomerangright] = '.'; } if (MyDino->road[MyDino->boomerangright - 1] == 'X' || MyDino->road[MyDino->boomerangright - 1] == '*') { MyDino->road[MyDino->boomerangright - 1] = '.'; } } // 迴力鏢到底時返回 else if (MyDino->boomerangright == ROAD_LENGTH) { MyDino->boomerangright = 0; MyDino->boomerang_count = 0; MyDino->road[ROAD_LENGTH - 1] = '<'; } if (MyDino->key == 'B' && MyDino->boomerangright == 0) { // continue; MyDino->boomerangright = DINO_PLACE; MyDino->boomerang_count = 50; } // 跳過了障礙物才能加分 (10分) if (MyDino->jump_time_left != 0 && MyDino->road[DINO_PLACE] == 'X') { MyDino->score += 10; } if (spawn_star(MyDino)) { MyDino->road[ROAD_LENGTH - 1] = '*'; } // 當碰到無敵星星時,障礙物會變成 '.' 且角色可直接穿過(加20分) if (MyDino->star_time > 0) { MyDino->star_time -= 1; for (int i = 0; i < ROAD_LENGTH; i++) { if (MyDino->road[i] == 'X') { MyDino->road[i] = '.'; } } } if (star_bumped(MyDino)) { MyDino->star_time = 30; } // 破壞障礙物加分 (20分) if (MyDino->jump_time_left == 0 && MyDino->road[DINO_PLACE] == '.') { MyDino->score += 20; } /* 渲染呈現 */ display(MyDino); Sleep(MyDino->wait_time); } /* 重新初始化遊戲 */ free(MyDino); MyDino = init(); display_start(); } } return 0; } ``` ## 示範影片 [連結](https://youtu.be/RQCLYNoIAlM)