Advertisement
Guest User

/r/arkadye hangman

a guest
Nov 19th, 2014
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.30 KB | None | 0 0
  1. #include <iostream>
  2. #include <algorithm>
  3.  
  4. #include <string>
  5. #include <vector>
  6. #include <sstream>
  7. #include <fstream>
  8. #include <random>
  9. #include <cstdlib>
  10.  
  11. using namespace std; // Toy projects only.
  12.  
  13. random_device rd;
  14. default_random_engine engine(rd());
  15.  
  16. template<class Container, class Value>
  17. bool contains(const Container& c , const Value& v)
  18. {
  19.     return find(begin(c), end(c), v) != end(c);
  20. }
  21.  
  22. string cleanSolution(const string& dsolution)
  23. {
  24.     auto solution = string{ "" };
  25.     for (auto ch : dsolution)
  26.     {
  27.         if (ch >= 'a' &&
  28.             ch <= 'z')
  29.         {
  30.             ch = toupper(ch);
  31.         }
  32.  
  33.         if ((ch >= 'A' &&
  34.             ch <= 'Z') ||
  35.             ch == ' ')
  36.         {
  37.             solution.push_back(static_cast<char>(ch));
  38.         }
  39.         else if (ch == '\'')
  40.         {
  41.             continue;
  42.         }
  43.         else
  44.         {
  45.             cout << "\nError handling word: " << dsolution
  46.                 << " (unrecognised symbol: '" << ch << "')\n";
  47.             return "";
  48.         }
  49.     }
  50.     // Handle whitespace.
  51.     auto input = istringstream{ solution };
  52.     auto output = ostringstream{};
  53.     while (!input.eof())
  54.     {
  55.         auto temp = string{ "" };
  56.         input >> temp;
  57.         output << ' ' << temp;
  58.     }
  59.     auto result = output.str();
  60.     return string(begin(result) + 1, end(result));
  61. }
  62.  
  63. void printHangedMan(int stage)
  64. {
  65.     auto hangedMan = vector<string>{
  66.         "    +---+  \n",
  67.         "    |   |  \n",
  68.         "        |  \n",
  69.         "        |  \n",
  70.         "        |  \n",
  71.         "        |  \n",
  72.         "        |  \n",
  73.         "        |  \n",
  74.         "        |  \n",
  75.         "        |  \n",
  76.         "--------+--\n"
  77.     };
  78.     switch (stage) // All cases fall through.
  79.     {
  80.     default:
  81.         cout << "ERROR! IMPOSSIBLE SITUATION. Hangman stage = " << stage
  82.             << endl;
  83.         return;
  84.     case 6: // Add right leg
  85.         hangedMan[7][5] = hangedMan[8][6] = '\\';
  86.     case 5: // Add left leg
  87.         hangedMan[7][3] = hangedMan[8][2] = '/';
  88.     case 4: // Add right arm.
  89.         hangedMan[3][5] = hangedMan[3][6] = '-';
  90.     case 3: // Add left arm
  91.         hangedMan[3][2] = hangedMan[3][3] = '-';
  92.     case 2: // Add the body
  93.         hangedMan[3][4] = stage > 2 ? '+' : '|';
  94.         hangedMan[4][4] = hangedMan[5][4] = '|';
  95.         hangedMan[6][4] = stage > 4 ? '^' : '|';
  96.     case 1: // Add the head
  97.         hangedMan[2][4] = 'O';
  98.     case 0:
  99.         break;
  100.     }
  101.     copy(begin(hangedMan), end(hangedMan), ostream_iterator<string>(cout));
  102.     return;
  103. }
  104.  
  105. char getGuess(vector<char>& previousGuesses)
  106. {
  107.     while (true)
  108.     {
  109.         cout << "Guess: ";
  110.         auto input = string{ "" };
  111.         getline(cin, input);
  112.         if (input.empty())
  113.         {
  114.             continue;
  115.         }
  116.         const char guess = toupper(input[0]);
  117.         if (!isalpha(guess))
  118.         {
  119.             cout << "Your guess (" << guess
  120.                 << ") is not a letter. Please try again.\n";
  121.             continue;
  122.         }
  123.         if (contains(previousGuesses, guess))
  124.         {
  125.             cout << "You already guessed '" << guess
  126.                 << "'. Please try again.\n";
  127.             input.clear();
  128.             continue;
  129.         }
  130.         else
  131.         {
  132.             previousGuesses.push_back(guess);
  133.             return guess;
  134.         }
  135.     }
  136. }
  137.  
  138. vector<char> getSolutionLetters(const string& solution)
  139. {
  140.     auto solutionLetters = vector<char>{};
  141.     copy_if(begin(solution), end(solution), back_inserter(solutionLetters),
  142.         [](char c) {return !isspace(c); });
  143.     sort(begin(solutionLetters), end(solutionLetters));
  144.     solutionLetters.erase(unique(begin(solutionLetters), end(solutionLetters)),
  145.         end(solutionLetters));
  146.     return solutionLetters;
  147. }
  148.  
  149. void playHangman(string solution)
  150. {
  151.     const auto solutionLetters = getSolutionLetters(solution);
  152.     auto guesses = vector<char>{};
  153.     int falseGuesses(0);
  154.     while (true)
  155.     {
  156.         printHangedMan(falseGuesses);
  157.         cout << "Word: ";
  158.         transform(begin(solution), end(solution), ostream_iterator<char>(cout),
  159.             [&](char c){return contains(guesses, c) || isspace(c) ? c : '-'; });
  160.         cout << "\nFalse guesses: ";
  161.         copy_if(begin(guesses), end(guesses), ostream_iterator<char>(cout),
  162.             [&](char c){return !contains(solutionLetters, c); });
  163.         cout << '\n';
  164.         if (falseGuesses >= 6)
  165.         {
  166.             cout << "You have been hanged.\nThe solution was:\n    "
  167.                 << solution << '\n';
  168.             return;
  169.         }
  170.         if (all_of(begin(solutionLetters), end(solutionLetters),
  171.             [&](char c){return contains(guesses, c); }))
  172.         {
  173.             cout << "You win!\n";
  174.             return;
  175.         }
  176.         const auto guess = getGuess(guesses);
  177.         cout << "You guessed '" << guess << "': ";
  178.         if (contains(solutionLetters, guess))
  179.         {
  180.             cout << "Correct!\n";
  181.         }
  182.         else
  183.         {
  184.             cout << "Incorrect.\n";
  185.             ++falseGuesses;
  186.         }
  187.     }
  188. }
  189.  
  190. double getDifficultyCoefficient(string in)
  191. {
  192.     if (in.empty())
  193.         return 0.0;
  194.     static const auto frequencies = vector<pair<char, double>> {
  195.         { 'A', 8.167 },
  196.         { 'B', 1.492 },
  197.         { 'C', 2.782 },
  198.         { 'D', 4.253 },
  199.         { 'E', 12.702 },
  200.         { 'F', 2.228 },
  201.         { 'G', 2.015 },
  202.         { 'H', 6.094 },
  203.         { 'I', 6.966 },
  204.         { 'J', 0.153 },
  205.         { 'K', 0.772 },
  206.         { 'L', 4.025 },
  207.         { 'M', 2.406 },
  208.         { 'N', 6.749 },
  209.         { 'O', 7.507 },
  210.         { 'P', 1.929 },
  211.         { 'Q', 0.095 },
  212.         { 'R', 5.987 },
  213.         { 'S', 6.327 },
  214.         { 'T', 9.056 },
  215.         { 'U', 2.758 },
  216.         { 'V', 0.987 },
  217.         { 'W', 2.360 },
  218.         { 'X', 0.150 },
  219.         { 'Y', 1.974 },
  220.         { 'Z', 0.074 }
  221.     };
  222.     const auto solution = getSolutionLetters(in);
  223.     auto hits = 0.0;
  224.     auto misses = 0.0;
  225.     for (auto c : frequencies)
  226.     {
  227.  
  228.         if (contains(solution, c.first))
  229.         {
  230.             hits += c.second;
  231.         }
  232.         else
  233.         {
  234.             misses += c.second;
  235.         }
  236.     }
  237.     return misses / hits;
  238. }
  239.  
  240. vector<string> getWordList(string filename)
  241. {
  242.     auto input = ifstream{ filename };
  243.     auto words = vector<pair<string, double>>{};
  244.     cout << "Reading word list.\n";
  245.     auto nWords = int{ 0 };
  246.     transform(istream_iterator<string>(input), istream_iterator<string>(),
  247.         back_inserter(words),
  248.         [&](const string& in)
  249.         {
  250.             cout << "\r" << ++nWords << " read";
  251.             auto out = cleanSolution(in);
  252.             return make_pair(out,getDifficultyCoefficient(out));
  253.         });
  254.     auto it = remove_if(begin(words), end(words),
  255.         [](const pair<string, double>& elem){return elem.first.empty(); });
  256.     if (it != end(words))
  257.     {
  258.         words.erase(it, end(words));
  259.     }
  260.     sort(begin(words), end(words),
  261.         [](decltype(*begin(words)) l, decltype(*begin(words)) r)
  262.             {return l.second > r.second; });
  263.     auto result = vector<string>{};
  264.     result.reserve(words.size());
  265.     transform(begin(words), end(words), back_inserter(result),
  266.         [](decltype(*begin(words)) elem) { return elem.first; });
  267.     return result;
  268. }
  269.  
  270. string getWord(int difficulty)
  271. {
  272.     if (difficulty < 0) // EASTER EGG!
  273.     {
  274.         static const auto words = vector<string> {
  275.             "Waltz, bad nymph, for quick jigs vex.",
  276.             "Quick zephyrs blow, vexing daft Jim.",
  277.             "Sphinx of black quartz, judge my vow.",
  278.             "Two driven jocks help fax my big quiz.",
  279.             "Five quacking zephyrs jolt my wax bed.",
  280.             "The five boxing wizards jump quickly.",
  281.             "Pack my box with five dozen liquor jugs.",
  282.             "The quick brown fox jumps over the lazy dog.",
  283.             "Jinxed wizards pluck ivy from the big quilt.",
  284.             "Crazy Fredrick bought many very exquisite opal jewels.",
  285.             "We promptly judged antique ivory buckles for the next prize.",
  286.             "A mad boxer shot a quick, gloved jab to the jaw of his dizzy opponent.",
  287.             "Jaded zombies acted quaintly but kept driving their oxen forward.",
  288.             "The job requires extra pluck and zeal from every young wage earner."
  289.         };
  290.         auto distribution =
  291.             uniform_int_distribution<size_t>{0u, words.size()-1};
  292.         const auto index = distribution(engine);
  293.         cout << "Very easy mode puzzle " << index+1 << '\n';
  294.         return cleanSolution(words[index]);
  295.     }
  296.  
  297.     static auto words = getWordList("word_list.txt");
  298.  
  299.     difficulty = max(100, difficulty);
  300.     auto lowRange = max(0.0, (difficulty - 5) / 100.0 );
  301.     auto highRange = min(1.0, (difficulty + 5) / 100.0);
  302.     auto lowIndex = static_cast<size_t>(words.size() * lowRange);
  303.     auto highIndex = static_cast<size_t>(words.size() * highRange);
  304.     auto distribution = uniform_int_distribution<size_t>(lowIndex, highIndex);
  305.     auto index = distribution(engine);
  306.     cout << "Puzzle " << index + 1 << " of " << words.size() << '\n';
  307.     return words[index];
  308. }
  309.  
  310. int main()
  311. {
  312.     cout <<
  313.         ".------..------..------..------..------..------..------.\n"
  314.         "|H.--. ||A.--. ||N.--. ||G.--. ||M.--. ||A.--. ||N.--. |\n"
  315.         "| :/\\: || (\\/) || :(): || :/\\: || (\\/) || (\\/) || :(): |\n"
  316.         "| (__) || :\\/: || ()() || :\\/: || :\\/: || :\\/: || ()() |\n"
  317.         "| '--'H|| '--'A|| '--'N|| '--'G|| '--'M|| '--'A|| '--'N|\n"
  318.         "`------'`------'`------'`------'`------'`------'`------'\n"
  319.         "    by /r/arkadye\n"
  320.         "        Title generated by http://patorjk.com/software/taag/\n\n";
  321.        
  322.     printHangedMan(6);
  323.     cout << '\n';
  324.     while (true)
  325.     {
  326.         cout << "Choose your difficulty (0-100, or 'quit' to quit)\n"
  327.             "Difficulty: ";
  328.         auto input = string{ "" };
  329.         getline(cin, input);
  330.         if (input == "quit")
  331.         {
  332.             break;
  333.         }
  334.         auto istr = istringstream{ input };
  335.         int difficulty;
  336.         istr >> difficulty;
  337.         if (istr.bad())
  338.         {
  339.             cout << "Sorry, I didn't understand that. Please try again.\n";
  340.             continue;
  341.         }
  342.         auto word = getWord(difficulty);
  343.         playHangman(word);
  344.     }
  345. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement