Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <algorithm>
- #include <string>
- #include <vector>
- #include <sstream>
- #include <fstream>
- #include <random>
- #include <cstdlib>
- using namespace std; // Toy projects only.
- random_device rd;
- default_random_engine engine(rd());
- template<class Container, class Value>
- bool contains(const Container& c , const Value& v)
- {
- return find(begin(c), end(c), v) != end(c);
- }
- string cleanSolution(const string& dsolution)
- {
- auto solution = string{ "" };
- for (auto ch : dsolution)
- {
- if (ch >= 'a' &&
- ch <= 'z')
- {
- ch = toupper(ch);
- }
- if ((ch >= 'A' &&
- ch <= 'Z') ||
- ch == ' ')
- {
- solution.push_back(static_cast<char>(ch));
- }
- else if (ch == '\'')
- {
- continue;
- }
- else
- {
- cout << "\nError handling word: " << dsolution
- << " (unrecognised symbol: '" << ch << "')\n";
- return "";
- }
- }
- // Handle whitespace.
- auto input = istringstream{ solution };
- auto output = ostringstream{};
- while (!input.eof())
- {
- auto temp = string{ "" };
- input >> temp;
- output << ' ' << temp;
- }
- auto result = output.str();
- return string(begin(result) + 1, end(result));
- }
- void printHangedMan(int stage)
- {
- auto hangedMan = vector<string>{
- " +---+ \n",
- " | | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- " | \n",
- "--------+--\n"
- };
- switch (stage) // All cases fall through.
- {
- default:
- cout << "ERROR! IMPOSSIBLE SITUATION. Hangman stage = " << stage
- << endl;
- return;
- case 6: // Add right leg
- hangedMan[7][5] = hangedMan[8][6] = '\\';
- case 5: // Add left leg
- hangedMan[7][3] = hangedMan[8][2] = '/';
- case 4: // Add right arm.
- hangedMan[3][5] = hangedMan[3][6] = '-';
- case 3: // Add left arm
- hangedMan[3][2] = hangedMan[3][3] = '-';
- case 2: // Add the body
- hangedMan[3][4] = stage > 2 ? '+' : '|';
- hangedMan[4][4] = hangedMan[5][4] = '|';
- hangedMan[6][4] = stage > 4 ? '^' : '|';
- case 1: // Add the head
- hangedMan[2][4] = 'O';
- case 0:
- break;
- }
- copy(begin(hangedMan), end(hangedMan), ostream_iterator<string>(cout));
- return;
- }
- char getGuess(vector<char>& previousGuesses)
- {
- while (true)
- {
- cout << "Guess: ";
- auto input = string{ "" };
- getline(cin, input);
- if (input.empty())
- {
- continue;
- }
- const char guess = toupper(input[0]);
- if (!isalpha(guess))
- {
- cout << "Your guess (" << guess
- << ") is not a letter. Please try again.\n";
- continue;
- }
- if (contains(previousGuesses, guess))
- {
- cout << "You already guessed '" << guess
- << "'. Please try again.\n";
- input.clear();
- continue;
- }
- else
- {
- previousGuesses.push_back(guess);
- return guess;
- }
- }
- }
- vector<char> getSolutionLetters(const string& solution)
- {
- auto solutionLetters = vector<char>{};
- copy_if(begin(solution), end(solution), back_inserter(solutionLetters),
- [](char c) {return !isspace(c); });
- sort(begin(solutionLetters), end(solutionLetters));
- solutionLetters.erase(unique(begin(solutionLetters), end(solutionLetters)),
- end(solutionLetters));
- return solutionLetters;
- }
- void playHangman(string solution)
- {
- const auto solutionLetters = getSolutionLetters(solution);
- auto guesses = vector<char>{};
- int falseGuesses(0);
- while (true)
- {
- printHangedMan(falseGuesses);
- cout << "Word: ";
- transform(begin(solution), end(solution), ostream_iterator<char>(cout),
- [&](char c){return contains(guesses, c) || isspace(c) ? c : '-'; });
- cout << "\nFalse guesses: ";
- copy_if(begin(guesses), end(guesses), ostream_iterator<char>(cout),
- [&](char c){return !contains(solutionLetters, c); });
- cout << '\n';
- if (falseGuesses >= 6)
- {
- cout << "You have been hanged.\nThe solution was:\n "
- << solution << '\n';
- return;
- }
- if (all_of(begin(solutionLetters), end(solutionLetters),
- [&](char c){return contains(guesses, c); }))
- {
- cout << "You win!\n";
- return;
- }
- const auto guess = getGuess(guesses);
- cout << "You guessed '" << guess << "': ";
- if (contains(solutionLetters, guess))
- {
- cout << "Correct!\n";
- }
- else
- {
- cout << "Incorrect.\n";
- ++falseGuesses;
- }
- }
- }
- double getDifficultyCoefficient(string in)
- {
- if (in.empty())
- return 0.0;
- static const auto frequencies = vector<pair<char, double>> {
- { 'A', 8.167 },
- { 'B', 1.492 },
- { 'C', 2.782 },
- { 'D', 4.253 },
- { 'E', 12.702 },
- { 'F', 2.228 },
- { 'G', 2.015 },
- { 'H', 6.094 },
- { 'I', 6.966 },
- { 'J', 0.153 },
- { 'K', 0.772 },
- { 'L', 4.025 },
- { 'M', 2.406 },
- { 'N', 6.749 },
- { 'O', 7.507 },
- { 'P', 1.929 },
- { 'Q', 0.095 },
- { 'R', 5.987 },
- { 'S', 6.327 },
- { 'T', 9.056 },
- { 'U', 2.758 },
- { 'V', 0.987 },
- { 'W', 2.360 },
- { 'X', 0.150 },
- { 'Y', 1.974 },
- { 'Z', 0.074 }
- };
- const auto solution = getSolutionLetters(in);
- auto hits = 0.0;
- auto misses = 0.0;
- for (auto c : frequencies)
- {
- if (contains(solution, c.first))
- {
- hits += c.second;
- }
- else
- {
- misses += c.second;
- }
- }
- return misses / hits;
- }
- vector<string> getWordList(string filename)
- {
- auto input = ifstream{ filename };
- auto words = vector<pair<string, double>>{};
- cout << "Reading word list.\n";
- auto nWords = int{ 0 };
- transform(istream_iterator<string>(input), istream_iterator<string>(),
- back_inserter(words),
- [&](const string& in)
- {
- cout << "\r" << ++nWords << " read";
- auto out = cleanSolution(in);
- return make_pair(out,getDifficultyCoefficient(out));
- });
- auto it = remove_if(begin(words), end(words),
- [](const pair<string, double>& elem){return elem.first.empty(); });
- if (it != end(words))
- {
- words.erase(it, end(words));
- }
- sort(begin(words), end(words),
- [](decltype(*begin(words)) l, decltype(*begin(words)) r)
- {return l.second > r.second; });
- auto result = vector<string>{};
- result.reserve(words.size());
- transform(begin(words), end(words), back_inserter(result),
- [](decltype(*begin(words)) elem) { return elem.first; });
- return result;
- }
- string getWord(int difficulty)
- {
- if (difficulty < 0) // EASTER EGG!
- {
- static const auto words = vector<string> {
- "Waltz, bad nymph, for quick jigs vex.",
- "Quick zephyrs blow, vexing daft Jim.",
- "Sphinx of black quartz, judge my vow.",
- "Two driven jocks help fax my big quiz.",
- "Five quacking zephyrs jolt my wax bed.",
- "The five boxing wizards jump quickly.",
- "Pack my box with five dozen liquor jugs.",
- "The quick brown fox jumps over the lazy dog.",
- "Jinxed wizards pluck ivy from the big quilt.",
- "Crazy Fredrick bought many very exquisite opal jewels.",
- "We promptly judged antique ivory buckles for the next prize.",
- "A mad boxer shot a quick, gloved jab to the jaw of his dizzy opponent.",
- "Jaded zombies acted quaintly but kept driving their oxen forward.",
- "The job requires extra pluck and zeal from every young wage earner."
- };
- auto distribution =
- uniform_int_distribution<size_t>{0u, words.size()-1};
- const auto index = distribution(engine);
- cout << "Very easy mode puzzle " << index+1 << '\n';
- return cleanSolution(words[index]);
- }
- static auto words = getWordList("word_list.txt");
- difficulty = max(100, difficulty);
- auto lowRange = max(0.0, (difficulty - 5) / 100.0 );
- auto highRange = min(1.0, (difficulty + 5) / 100.0);
- auto lowIndex = static_cast<size_t>(words.size() * lowRange);
- auto highIndex = static_cast<size_t>(words.size() * highRange);
- auto distribution = uniform_int_distribution<size_t>(lowIndex, highIndex);
- auto index = distribution(engine);
- cout << "Puzzle " << index + 1 << " of " << words.size() << '\n';
- return words[index];
- }
- int main()
- {
- cout <<
- ".------..------..------..------..------..------..------.\n"
- "|H.--. ||A.--. ||N.--. ||G.--. ||M.--. ||A.--. ||N.--. |\n"
- "| :/\\: || (\\/) || :(): || :/\\: || (\\/) || (\\/) || :(): |\n"
- "| (__) || :\\/: || ()() || :\\/: || :\\/: || :\\/: || ()() |\n"
- "| '--'H|| '--'A|| '--'N|| '--'G|| '--'M|| '--'A|| '--'N|\n"
- "`------'`------'`------'`------'`------'`------'`------'\n"
- " by /r/arkadye\n"
- " Title generated by http://patorjk.com/software/taag/\n\n";
- printHangedMan(6);
- cout << '\n';
- while (true)
- {
- cout << "Choose your difficulty (0-100, or 'quit' to quit)\n"
- "Difficulty: ";
- auto input = string{ "" };
- getline(cin, input);
- if (input == "quit")
- {
- break;
- }
- auto istr = istringstream{ input };
- int difficulty;
- istr >> difficulty;
- if (istr.bad())
- {
- cout << "Sorry, I didn't understand that. Please try again.\n";
- continue;
- }
- auto word = getWord(difficulty);
- playHangman(word);
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement