0

I am making a hangman game. I have a vector<string> words that consists of 2455 words and a function called valid_word() that verifies that the randomly selected word matches the level of difficulty that the player has selected. Like for easy level the word is <=6, for a hard level the word is <= 8 and so on.

Sometimes this takes a long time. First a random_number is generated, then a words.at(random_number) is picked, and then it is verified for the words.at(random_number).length(). Depending upon the level and if it doesn't qualify to be a valid word then this process is repeated.

This process most of the time takes at least 15-20 seconds. So I created a function that displays a loading animation at the console as below:

void print_loading() {
    std::cout << '-' << std::flush;
    for (;;) {
        sleep(1);
        std::cout << "\b\\" << std::flush;
        sleep(1);
        std::cout << "\b|" << std::flush;
        sleep(1);
        std::cout << "\b/" << std::flush;
        sleep(1);
        std::cout << "\b-" << std::flush;
    }
}

Got this code from here

How can I make this function to run only until my valid_word has been generated?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • 5
    Why not instead change your sampling algorithm? One idea that comes to mind is to use [`std::partition`](https://en.cppreference.com/w/cpp/algorithm/partition) to split up your vector into easy vs hard, then just sample from between the boundaries of each category. Then instead of loop & discard, you can sample in O(1) every time. – Cory Kramer Jun 10 '21 at 11:41
  • 2
    don't pick a random word among all words and then verify it it qualifies, instead first select words that qualify and then pick one at random. – 463035818_is_not_an_ai Jun 10 '21 at 11:41
  • All loop constructs support a way of terminating when some condition is met (or continuing for as long as the opposite of that condition is true). – Peter Jun 10 '21 at 11:49
  • 1
    *"This process most of the time takes at least 15-20 seconds."* I would say it should be instant (less than 1 sec). – Jarod42 Jun 10 '21 at 12:09
  • Look into [`std::asnyc`](https://en.cppreference.com/w/cpp/thread/async). But note that multithreading is very hard to get right, and if you don't do it just right your application is likely to start crashing or misbehaving seemingly randomly. If you are new to C++ and still learning the basics, I would suggest simply not trying to implement this yet. – François Andrieux Jun 10 '21 at 12:53

2 Answers2

2

As people have mentioned in the comments you should really address the issue that it takes so long time to find a word in such a small dataset.

That said, being able to wait on lengthy executions might be good to know anyway. I would suggest using a std::future object to detect when your task has completed. Have a look at: http://www.cplusplus.com/reference/future/future/

A short example of what you tried to accomplish would be:

#include <future>
#include <iostream>
#include <ostream>

void some_slow_method(){
  std::cout << "Performing some lengthy task here" << std::endl;
  std::this_thread::sleep_for(std::chrono::seconds(5));
}

int main()
{
  char animation[] = {'\\','|','/','-'};
  int i = 0;
  std::chrono::milliseconds span(100);

  //Create the future based on your slow method
  std::future<void> f = std::async(some_slow_method);
  
  //Wait for 100ms to see if it has finished, if not perform 1 step of the animation
  while(f.wait_for(span) == std::future_status::timeout)
  {
    std::cout << '\b' << animation[i++] << std::flush;
    if(i>3) i=0; //start over when we reach last animation
  }

  std::cout << std::endl << "Task complete" << std::endl;

}
rmfeldt
  • 101
  • 1
  • 4
-1

I see two options here.

First, the simplest, use a global boolean variable. Your for loop becomes a while(flag), and your validating process will be something like:

boolean flag = true;

void validating() {
    flag = true;
    .. do your staff ..
    flag = false;
}

Second option, use again a boolean flag read from logging routine and written from validating routine, but this time pass it as an argument of such routines (of course you have to pass a reference to the flag). In this case your logging function becomes:

void print_loading(boolean * flag) {
    ..
    while(*flag) {
    ..
}
Jack
  • 1,488
  • 11
  • 21