Number Bomb Game V2.7.4

📅 2026/8/9 7:52:44
Number Bomb Game V2.7.4
自从我踏入 CSDN 论坛并开始写博文已经过去一年多了。我的第一篇博文就是关于《数字炸弹》这款名副其实的“小游戏”的。事实上我一直在持续迭代这个小代码它已从最初的仅有 28 行发展到现在功能较为齐全的游戏版本。这是最新的 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是否查看游戏规则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数字炸弹是一款基于逻辑推理的猜数字游戏。游戏开始时系统会在预设范围内生成一个秘密数字称为“炸弹”。玩家根据当前数字范围的提示依次输入一个猜测数字。若玩家猜中炸弹数字则该玩家游戏失败并接受惩罚若未猜中系统将根据猜测值缩小范围若猜测值小于炸弹则下限调整为猜测值1若猜测值大于炸弹则上限调整为猜测值。\n\n游戏可通过种子值控制随机生成结果种子为-1时完全随机。每局结束后可选择继续游戏或退出。\n请按任意键继续......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デジタルボムは論理的推論に基づく数字当てゲームです。\nゲーム開始時、システムは事前に設定された範囲内で秘密の数字「ボム」と呼びますを生成します。\nプレイヤーは現在の範囲のヒントをもとに、数字を順に予想して入力します。\nもしボムの数字を当ててしまった場合、そのプレイヤーはゲームに敗北し、ペナルティを受けます。\n予想が外れた場合、システムはその予想値に基づいて範囲を狭めます。\n予想値がボムより小さい場合は下限を「予想値1」に調整し、予想値がボムより大きい場合は上限を予想値に調整します。\n\nシード値によってランダムな結果を制御できますシードが-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. 人机对战 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请输入游玩的人数2~20std::flush; break; case ENGLISH: std::coutPlease enter the number of players (2~20): std::flush; break; case JAPANESE: std::coutプレイヤー人数を入力してください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。下限より大きい値を設定してください; 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爆弾の準備ができました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哎呀一不小心触发了炸弹std::endl; break; case ENGLISH: std::coutOops! I accidentally triggered the bomb! std::endl; break; case JAPANESE: std::coutおっとうっかり爆弾を触发してしまいました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猜测次数guess_count\n再玩一局请按 c 键否则请按任意键以继续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試行回数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.这就是《数字炸弹》 V2.7.4 的完整实现。代码已在 Windows 和 Linux 下测试通过支持中英日三语言。如果你有改进建议欢迎在评论区指出。感谢大家的阅读