
自從我踏入 CSDN 論壇并開始寫博文已經(jīng)過去一年多了。我的第一篇博文就是關(guān)于《數(shù)字炸彈》這款名副其實的“小游戲”的。事實上我一直在持續(xù)迭代這個小代碼它已從最初的僅有 28 行發(fā)展到現(xiàn)在功能較為齊全的游戲版本。這是最新的 V2.7.4 版本寫在下面。/** * Number Bomb Game V2.7.4 * This is a digital bomb code written by a single person for playing. * Therere some comments inside that may help you understand the code. * Enjoy the game! * Author: WP18Noru **/ #includecstdlib #includeiostream #ifdef _WIN32 #includewindows.h #else #includetime.h #endif #ifdef _WIN32 #includeconio.h #else #includetermios.h #includeunistd.h #includecstdio #endif #if __cplusplus201103L #includerandom #endif #includelimits #includecctype #if __cplusplus201103L #includectime #endif enum Language{ // enum for languages CHINESE,ENGLISH,JAPANESE }; Language languageCHINESE; inline void clear_screen(){ #ifdef _WIN32 std::system(CLS); #else std::system(clear); #endif } void input_error_prompt(){ switch(language){ case CHINESE: std::cout輸入錯誤請重新輸入std::endl; break; case ENGLISH: std::coutInput error, please re-enter! std::endl; break; case JAPANESE: std::cout入力エラーです。再入力してください。std::endl; break; } } int get_char(){ // a compatible function that mimics _getch() from conio.h #ifdef _WIN32 return _getch(); #else int received_character; struct termios old_termios,new_termios; tcgetattr(STDIN_FILENO,old_termios); new_termiosold_termios; new_termios.c_lflag~(ICANON|ECHO); tcsetattr(STDIN_FILENO,TCSANOW,new_termios); received_charactergetchar(); tcsetattr(STDIN_FILENO,TCSANOW,old_termios); if(received_characterEOF){ std::clearerr(stdin); } return received_character; #endif } void unified_sleep(long long time_millisecond){ #ifdef _WIN32 Sleep(static_castDWORD(time_millisecond)); #else struct timespec request; request.tv_sectime_millisecond/1000; request.tv_nsec(time_millisecond%1000)*1000000L; nanosleep(request,NULL); #endif } class number_bomb_game{ // main class of the program private: enum Difficulty{ // enum for difficulty EASY1,NORMAL,HARD,CUSTOM }; short game_mode,player_count; Difficulty difficulty; long long seed; short bomb,lower_limit,upper_limit,player_input,guess_count; #if __cplusplus201103L std::mt19937 random_engine; #endif protected: void select_language(){ short input; do{ std::cout請選擇語言。\tPlease select a language. \t言語を選択してください。 \n0. 簡體中文\t1. English\t2. 日本語std::endl; if(!(std::cininput)){ std::cin.clear(); std::cout輸入錯誤請重新輸入Input error, please re-enter! 入力エラーです。再入力してください。std::endl; input-1; }else if(input0||input2){ std::cout輸入錯誤請重新輸入Input error, please re-enter! 入力エラーです。再入力してください。std::endl; } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(input0||input2); languagestatic_castLanguage(input); clear_screen(); } void output_game_rules()const{ switch(language){ case CHINESE: std::cout是否查看游戲規(guī)則Y/其他任意鍵std::endl; break; case ENGLISH: std::coutDo you want to check the game rules?(Y/Any other key) std::endl; break; case JAPANESE: std::coutゲームのルールを表示しますかY/他の任意のキーstd::endl; break; } { int received_character0; received_characterget_char(); if(received_character!EOFstd::tolower(static_castunsigned char(received_character))y){ switch(language){ case CHINESE: std::cout數(shù)字炸彈是一款基于邏輯推理的猜數(shù)字游戲。游戲開始時系統(tǒng)會在預(yù)設(shè)范圍內(nèi)生成一個秘密數(shù)字稱為“炸彈”。玩家根據(jù)當(dāng)前數(shù)字范圍的提示依次輸入一個猜測數(shù)字。若玩家猜中炸彈數(shù)字則該玩家游戲失敗并接受懲罰若未猜中系統(tǒng)將根據(jù)猜測值縮小范圍若猜測值小于炸彈則下限調(diào)整為猜測值1若猜測值大于炸彈則上限調(diào)整為猜測值。\n\n游戲可通過種子值控制隨機生成結(jié)果種子為-1時完全隨機。每局結(jié)束后可選擇繼續(xù)游戲或退出。\n請按任意鍵繼續(xù)......std::endl; break; case ENGLISH: std::coutNumber Bomb is a logic-based number guessing game.\nAt the start of the game, the system generates a secret number (called the \bomb\) within a preset range.\nBased on the current range prompt, players take turns entering a guessed number.\nIf the player guesses the bomb number, they lose the game and must accept a penalty.\nIf the guess is incorrect, the system narrows the range based on the guess:\nif the guess is less than the bomb, the lower bound is adjusted to the guess 1;\nif the guess is greater than the bomb, the upper bound is adjusted to the guess.\n\nThe game can use a seed value to control random outcomes (a seed of -1 means completely random).\nAfter each round, players can choose to continue or quit.\nPress any key to continue...\n; break; case JAPANESE: std::coutデジタルボムは論理的推論に基づく數(shù)字當(dāng)てゲームです。\nゲーム開始時、システムは事前に設(shè)定された範(fàn)囲內(nèi)で秘密の數(shù)字「ボム」と呼びますを生成します。\nプレイヤーは現(xiàn)在の範(fàn)囲のヒントをもとに、數(shù)字を順に予想して入力します。\nもしボムの數(shù)字を當(dāng)ててしまった場合、そのプレイヤーはゲームに敗北し、ペナルティを受けます。\n予想が外れた場合、システムはその予想値に基づいて範(fàn)囲を狹めます。\n予想値がボムより小さい場合は下限を「予想値1」に調(diào)整し、予想値がボムより大きい場合は上限を予想値に調(diào)整します。\n\nシード値によってランダムな結(jié)果を制御できますシードが-1の場合は完全ランダム。\n各ゲーム終了後、続行するか終了するかを選択できます。\n任意のキーを押して続行してください......\n; break; } get_char(); // press any key to continue } } clear_screen(); } void choose_game_mode(){ do{ switch(language){ case CHINESE: std::cout請選擇游戲模式。0. 人機對戰(zhàn) 1. 多人游戲std::flush; break; case ENGLISH: std::coutPlease choose a game mode( 0. Player vs Computer 1. Player vs Player): std::flush; break; case JAPANESE: std::coutゲームモードを選択してください0. プレイヤー対コンピュータ 1. プレイヤー対プレイヤーstd::flush; break; } if(!(std::cingame_mode)){ std::cin.clear(); input_error_prompt(); game_mode-1; }else if(game_mode0||game_mode1){ input_error_prompt(); } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(game_mode0||game_mode1); clear_screen(); } void input_player_number(){ if(game_mode1){ do{ switch(language){ case CHINESE: std::cout請輸入游玩的人數(shù)2~20std::flush; break; case ENGLISH: std::coutPlease enter the number of players (2~20): std::flush; break; case JAPANESE: std::coutプレイヤー人數(shù)を入力してください2~20std::flush; break; } if(!(std::cinplayer_count)){ std::cin.clear(); input_error_prompt(); player_count1; }else if(player_count2||player_count20){ input_error_prompt(); } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(player_count2||player_count20); } clear_screen(); } void select_difficulty(){ short input; do{ switch(language){ case CHINESE: std::cout請選擇難度\n1. 簡單\n2. 普通\n3. 困難\n4. 自定義上下限std::endl; break; case ENGLISH: std::coutPlease select the difficulty level: \n1. Easy\n2. Normal\n3. Hard\n4. Custom upper and lower limitsstd::endl; break; case JAPANESE: std::cout難易度を選択してください\n1. 簡単\n2. 普通\n3. 難しい\n4. カスタム上下限std::endl; break; } if(!(std::cininput)){ std::cin.clear(); input_error_prompt(); input0; }else if(input1||input4){ input_error_prompt(); } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(input1||input4); difficultystatic_castDifficulty(input); clear_screen(); } void input_seed(){ do{ switch(language){ case CHINESE: std::cout請輸入種子-1~4294967295-1表示隨機std::flush; break; case ENGLISH: std::coutPlease input the seed (-1~4294967295, -1 represents random): std::flush; break; case JAPANESE: std::coutシード値を入力してください-1~4294967295、-1はランダムを表しますstd::flush; break; } if(!(std::cinseed)){ std::cin.clear(); input_error_prompt(); seed-2; }else if(seed-1||seed4294967295LL){ input_error_prompt(); } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(seed-1||seed4294967295LL); // 4294967295LL is 2^32 - 1. Its also the upper limit of unsigned int, the upper limit of the argument to the srand() function, and the upper limit of the seed() method } void custom_upper_and_lower_limits(){ if(difficultyCUSTOM){ // yes, we need to determine while(true){ // -32768 ~ 32767 is the range of short. here we dont need to validate, input error handling will take care of everything. switch(language){ case CHINESE: std::cout請輸入下限-32768~32767; break; case ENGLISH: std::coutEnter the lower limit (-32768 to 32767): ; break; case JAPANESE: std::cout下限を入力してください-3276832767; break; } if(!(std::cinlower_limit)){ std::cin.clear(); input_error_prompt(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }else{ std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); break; } } while(true){ switch(language){ case CHINESE: std::cout請輸入上限-32768~32767且大于下限; break; case ENGLISH: std::coutEnter the upper limit (-32768 to 32767), and it must be greater than the lower limit: ; break; case JAPANESE: std::cout上限を入力してください-3276832767。下限より大きい値を設(shè)定してください; break; } if(!(std::cinupper_limit)||upper_limitlower_limit){ std::cin.clear(); input_error_prompt(); std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }else{ std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); break; } } } } void generate_bomb(long long random_seed){ // it should be noted here that the bombs generation range is [lower_limit, upper_limit). #if __cplusplus201103L if(random_seed!-1){ random_engine.seed(random_seed); }else{ std::random_device random; random_engine.seed(random()); } std::uniform_int_distribution distribution(1,99); switch(difficulty){ case EASY: distributionstd::uniform_int_distribution(1,199); bombdistribution(random_engine); break; case NORMAL: bombdistribution(random_engine); break; case HARD: distributionstd::uniform_int_distribution(1,49); bombdistribution(random_engine); break; case CUSTOM: if(upper_limit-lower_limit0){ bomblower_limit; }else{ distributionstd::uniform_int_distribution(lower_limit,upper_limit-1); bombdistribution(random_engine); } break; } #else if(random_seed!-1){ std::srand(random_seed); }else{ std::srand(static_castunsigned int(std::time(0))); } switch(difficulty){ case EASY: bombstd::rand()%1991; break; case NORMAL: bombstd::rand()%991; break; case HARD: bombstd::rand()%491; break; case CUSTOM: if(upper_limit-lower_limit0){ bomblower_limit; }else{ bombstd::rand()%(upper_limit-lower_limit)lower_limit; } break; } #endif switch(language){ case CHINESE: std::cout炸彈已就緒std::endl; break; case ENGLISH: std::coutThe bomb is ready! std::endl; break; case JAPANESE: std::cout爆弾の準(zhǔn)備ができましたstd::endl; break; } } bool player_turn(short current_player0){ do{ switch(language){ case CHINESE: if(current_player0){ std::cout玩家lower_limit~upper_limitstd::flush; }else{ std::cout玩家current_playerlower_limit~upper_limitstd::flush; } break; case ENGLISH: if(current_player0){ std::coutPlayer(lower_limit~upper_limit):std::flush; }else{ std::coutPlayer current_player(lower_limit~upper_limit):std::flush; } break; case JAPANESE: if(current_player0){ std::coutプレイヤーlower_limit~upper_limitstd::flush; }else{ std::coutプレイヤーcurrent_playerlower_limit~upper_limitstd::flush; } break; } if(!(std::cinplayer_input)){ std::cin.clear(); input_error_prompt(); player_input-1; }else if(player_inputlower_limit||player_inputupper_limit){ input_error_prompt(); } std::cin.ignore(std::numeric_limitsstd::streamsize::max(),\n); }while(player_inputlower_limit||player_inputupper_limit); guess_count; if(player_inputbomb){ #ifdef _WIN32 std::system(COLOR cf); #else std::cout\033[97;101mstd::flush; #endif switch(language){ case CHINESE: std::cout炸彈爆炸你輸了接受懲罰吧玩家std::endl; break; case ENGLISH: std::coutThe bomb exploded, you lost! Accept the punishment, Player!!! std::endl; break; case JAPANESE: std::cout爆弾が爆発しました、あなたの負けです罰を受けてください、プレイヤーstd::endl; break; } return true; }else if(player_inputbomb){ lower_limitplayer_input1; }else{ upper_limitplayer_input; } return false; } bool computer_turn(){ short deviation_range4,deviation0,computer_guess0; switch(difficulty){ case EASY: deviation_range7; break; case NORMAL: break; case HARD: deviation_range2; break; case CUSTOM: break; } short current_deviationdeviation_range,range_sizeupper_limit-lower_limit; if(range_size50){ current_deviationdeviation_range2; }else if(range_size20){ current_deviationdeviation_range/2; if(current_deviation1){ current_deviation1; } } #if __cplusplus201103L std::uniform_int_distribution distribution(-current_deviation,current_deviation); deviationdistribution(random_engine); #else deviationstd::rand()%(current_deviation*21)-current_deviation; #endif computer_guessstatic_castshort((lower_limit(upper_limit-1))/2)1deviation; if(computer_guesslower_limit){ computer_guesslower_limit; } if(computer_guessupper_limit){ computer_guessupper_limit-1; } switch(language){ case CHINESE: std::cout計算機lower_limit~upper_limit; break; case ENGLISH: std::coutComputer(lower_limit~upper_limit):; break; case JAPANESE: std::coutコンピュータlower_limit~upper_limit; break; } unified_sleep(1000); std::coutcomputer_guessstd::endl; guess_count; if(computer_guessbomb){ #ifdef _WIN32 std::system(COLOR 8f); #else std::cout\033[37;100mstd::flush; #endif switch(language){ case CHINESE: std::cout哎呀一不小心觸發(fā)了炸彈std::endl; break; case ENGLISH: std::coutOops! I accidentally triggered the bomb! std::endl; break; case JAPANESE: std::coutおっとうっかり爆弾を觸發(fā)してしまいましたstd::endl; break; } return true; }else if(computer_guessbomb){ lower_limitcomputer_guess1; }else{ upper_limitcomputer_guess; } return false; } void reset_game(){ #ifdef _WIN32 std::system(COLOR 07); #else std::cout\033[0mstd::flush; #endif lower_limit1; upper_limit100; guess_count0; } public: number_bomb_game():game_mode(1),player_count(2),difficulty(NORMAL),seed(-1),bomb(50),lower_limit(1),upper_limit(100),player_input(0),guess_count(0){ #if __cplusplus201103L std::random_device game_random_device; random_engine.seed(game_random_device()); #endif } void player_versus_computer(){ while(true){ if(player_turn()||computer_turn()){ break; } } } void player_versus_player(){ short current_player1; while(true){ if(player_turn(current_player)){ break; } current_player(current_player!player_count)?current_player1:1; } } void play(){ select_language(); output_game_rules(); while(true){ choose_game_mode(); input_player_number(); select_difficulty(); input_seed(); switch(difficulty){ case EASY: lower_limit1; upper_limit200; break; case NORMAL: lower_limit1; upper_limit100; break; case HARD: lower_limit1; upper_limit50; break; case CUSTOM: break; } custom_upper_and_lower_limits(); generate_bomb(seed); unified_sleep(1000); clear_screen(); if(game_mode0){ player_versus_computer(); }else{ player_versus_player(); } unified_sleep(3000); switch(language){ case CHINESE: std::cout猜測次數(shù)guess_count\n再玩一局請按 c 鍵否則請按任意鍵以繼續(xù)std::endl; break; case ENGLISH: std::coutGuess counts: guess_count\nPlease press the c key to play another round, otherwise please press any key to continue! std::endl; break; case JAPANESE: std::cout試行回數(shù)guess_count\nもう一度プレイするには c キーを押してください。そうでない場合は任意のキーを押して続行しますstd::endl; break; } { int received_character0; received_characterget_char(); if(received_characterEOF||std::tolower(static_castunsigned char(received_character))!c){ break; } } reset_game(); clear_screen(); } } }; void start(){ std::cout正在啟動游戲中std::flush; for(short i1;i6;i){ unified_sleep(667); std::cout.; } std::cout\n啟動完成std::flush; unified_sleep(500); clear_screen(); } int main(){ #ifdef _WIN32 SetConsoleTitleA(Number Bomb Game V2.7.4); #else std::cout\033]0;Number Bomb Game V2.7.4\007std::flush; #endif start(); number_bomb_game game; game.play(); #ifdef _WIN32 std::system(COLOR 07); #else std::cout\033[0mstd::flush; #endif std::cout\nGame Over! std::endl; get_char(); return 0; } /** * Here are some thoughts on the future of the project: * Maybe: a major refactoring of the code structure; * Maybe: minor changes to the code logic; * Maybe (in the more distant future): update to a graphical interface; * Maybe (in the even more distant future): add online multiplayer! **/ // The code is provided for learning, but that does not mean you can infringe. // Thanks.這就是《數(shù)字炸彈》 V2.7.4 的完整實現(xiàn)。代碼已在 Windows 和 Linux 下測試通過支持中英日三語言。如果你有改進建議歡迎在評論區(qū)指出。感謝大家的閱讀