From 7611d51bc4fab4c57aa2a10d459ffc630a83468c Mon Sep 17 00:00:00 2001 From: Love Billenius Date: Thu, 12 Sep 2024 22:26:57 +0200 Subject: [PATCH] Fix points + computerPlay - computerPlay was iterating over an empty word - Boggle::getPointsForWord was using std::min instead of std::max --- src/Boggle.cpp | 20 +++++--- src/Boggle.h | 1 + src/boggleplay.cpp | 124 ++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 132 insertions(+), 13 deletions(-) diff --git a/src/Boggle.cpp b/src/Boggle.cpp index 9c7aaf0..c347025 100755 --- a/src/Boggle.cpp +++ b/src/Boggle.cpp @@ -42,10 +42,14 @@ std::array rollSides() { } Boggle::Boggle() - : m_showingSides(rollSides()), m_englishWords(Boggle::s_DICTIONARY_FILE) {} + : m_showingSides(rollSides()), m_englishWords(Boggle::s_DICTIONARY_FILE) { + std::cout << "Lexicon size: " << m_englishWords.size() << std::endl; +} -const std::vector &Boggle::playedWords() const{ - return m_playedWords; +const std::vector &Boggle::playedWords() const { return m_playedWords; } + +const std::array Boggle::showingSides() const { + return m_showingSides; } bool Boggle::isWordEnglish(const std::string &word) const { @@ -64,11 +68,12 @@ bool Boggle::isWordPlayed(const std::string &word) const { unsigned int Boggle::getPointsForWord(const std::string &word) { // This is kept as a variable to avoid static_cast const int pointsForValidWord = word.length() - s_MIN_WORD_LENGTH; - return std::min(pointsForValidWord, 0); + return std::max(pointsForValidWord, 0); } -bool Boggle::userInsert(std::string word){ - bool existsAlready = std::find(m_playedWords.begin(), m_playedWords.end(), word) != m_playedWords.end(); +bool Boggle::userInsert(std::string word) { + bool existsAlready = std::find(m_playedWords.begin(), m_playedWords.end(), + word) != m_playedWords.end(); if (existsAlready) return false; @@ -80,10 +85,11 @@ std::vector Boggle::computerPlay() const { std::unordered_set visited; std::vector valiWords; + std::cout << "showing sides: "< &playedWords() const; + const std::array showingSides() const; bool isWordEnglish(const std::string &word) const; bool isWordLongEnough(const std::string &word) const; bool isWordPlayed(const std::string &word) const; diff --git a/src/boggleplay.cpp b/src/boggleplay.cpp index b3ed7ad..34376da 100755 --- a/src/boggleplay.cpp +++ b/src/boggleplay.cpp @@ -2,20 +2,132 @@ // Also remove these comments here and add your own. // TODO: remove this comment header and replace with your own -#include -#include -#include -#include #include "Boggle.h" #include "bogglemain.h" #include "strlib.h" -// TODO: include any other header files you need +#include +#include +#include +#include +#include + +static const size_t LINE_LENGTH = 80; + +void printSlow(const char *const str, unsigned int msBetween) { + for (const char *c = str; *c; c++) { + std::cout << *c; + std::flush(std::cout); + std::this_thread::sleep_for(std::chrono::milliseconds(msBetween)); + } +} + +std::string wordsToStringLimit(const std::vector &words, + const size_t limitMaxLine, + const size_t startLine) { + if (words.empty()) + return "{}"; + + const std::string linePrefix(startLine, ' '); + std::string ret = "{"; + + int lineLength = startLine + 1; // +1 for the '{' + for (size_t i = 0; i < words.size(); i++) { + std::string word = "\"" + words[i] + "\""; + if (i != words.size() - 1) { + word += ","; + } + + if (word.size() + lineLength <= limitMaxLine) { + ret += word + " "; + lineLength += word.size() + 1; // +1 for the space + continue; + } + // Start a new line, with the prefix + ret += "\n" + linePrefix + word + " "; + lineLength = startLine + word.size() + 1; // +1 for the space + } + + ret.back() = '}'; + return ret; +} /* * Plays one game of Boggle using the given boggle game state object. */ -void playOneGame(Boggle& boggle) { +void playOneGame(Boggle &boggle) { + std::string userInput; + size_t userScore = 0; + std::cout << "It's your turn!\n"; + std::cout << "Showing sides:\n"; + for (const std::string &side : boggle.showingSides()) + std::cout << ' ' << side << '\n'; + + while (true) { + const std::vector &words = boggle.playedWords(); + std::string wordsInfo = + "Your words (" + std::to_string(words.size()) + "): "; + // std::endl flushes the line, it's not necessary yet, hence the \n + std::cout << wordsInfo + << wordsToStringLimit(words, LINE_LENGTH, wordsInfo.length()) + << '\n'; + std::cout << "Your score: " << userScore << '\n'; + std::cout << "Type a word (or press Enter to end your turn): "; + std::flush(std::cout); // Finally flush! + + std::string answer; + std::getline(std::cin, answer); + + if (answer.empty()) + break; + if (answer.size() > 16) { + std::cout << "Your word may not be longer than 16 characters!" + << std::endl; + continue; + } + if (!boggle.isWordLongEnough(answer)) { + std::cout << "Your word is not long enough!" << std::endl; + continue; + } + if (boggle.isWordPlayed(answer)) { + std::cout << "You've already played that word!" << std::endl; + continue; + } + if (!boggle.isWordEnglish(answer)) { + std::cout << "Silly human, that's not a real word!" << std::endl; + continue; + } + boggle.userInsert(answer); + userScore += Boggle::getPointsForWord(answer); + } + + std::cout << "It's my turn!" << std::endl; + std::vector words = boggle.computerPlay(); + size_t myScore = 0; + for (const std::string &word : words) + myScore += Boggle::getPointsForWord(word); + + std::string wordsInfo = "My words (" + std::to_string(words.size()) + "): "; + std::cout << wordsInfo + << wordsToStringLimit(words, LINE_LENGTH, wordsInfo.length()) + << '\n'; + + std::cout << "My score: " << myScore << '\n'; + + if (myScore > userScore) { + std::cout << "Ha ha ha, I destroyed you. Better luck next time, puny human!" + << std::endl; + } else { + std::flush(std::cout); + printSlow("¡Que pasa! You", 25); + printSlow("... won 😭", 150); + std::this_thread::sleep_for(std::chrono::milliseconds(200)); + std::cout << '\n'; + printSlow("Well", 70); + printSlow(", uhhhhh", 200); + printSlow(", well played!", 50); + printSlow(", I suppose", 200); + } } /*