2
#include "stdafx.h"
#include <iostream>
#include <string>
#include <windows.h>
#include <time.h>

unsigned long n = 1;

int main()
{
    int i = 0;
    std::string text = "I whip my hair back and forth";
    std::string wipIt = " ";
    size_t sz;
    sz = wipIt.size();
    srand(time(0));

    do{
        for(i = 0; i < 10; i++)
        {
            int randomNumber = rand() % 15 + 1;
            Sleep(50);
            wipIt.resize (sz++,' ');
            std::cout << wipIt;
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), randomNumber);
            std::cout << text << "\n";
        }
        for(i = 10; i > 0; i--)
        {
            int randomNumber = rand() % 15 + 1;
            Sleep(50);
            wipIt.resize (sz--,' ');
            std::cout << wipIt;
            SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), randomNumber);
            std::cout << text << "\n";
        }
    }
    while (n != 0);
    return 0;
}

If I messed this post up I apologize this is only like my second post.

What would be the easiest way to make every character in the string a different color, instead of the entire string the same color.

Tidying up tips would be appreciated as well :P

EDIT: tidy'd up a little, and the random is working well, thank you all ^_^ now for the color by character?

  • 1
    std::srand(std::time(0)) (from ) before your first call to std::rand(). This sets a seed for the pseudo-random number generator that's reasonably random (rand() essentially just iterates over a long sequence of numbers that are expected to be distributed in a random seeming pattern. srand(seed) set's a seed for rand, time(0) is the current time in seconds since epoch (usually anyways, either way it's the current time in some metric). – Cubic Aug 01 '12 at 15:33
  • tidy up tip: you're using a lot of extra braces. I sometime use extra braces to limit the lifetime of a particular variable, but here there are braces that don't do anything except mess with the indentation. I would remove those. – bames53 Aug 01 '12 at 15:35
  • Using the C++11 `` library, if available to you, is preferable to using `rand()`. – bames53 Aug 01 '12 at 15:36
  • 1
    tidy up tip: You are mixing different styles regarding capitalization of variables. Pick a style, and stick with it ;) – W. Goeman Aug 01 '12 at 15:38
  • 1
    `endl` both adds a new line and flushes the buffer. This can cause output performance to suffer greatly. Almost always you'll just want to write a newline: `cout << Test << '\n';`. Also `using namespace std;` is used a lot in beginning programming examples, but IMO it's better not to use it, and instead to either just qualify names: `std::cout << Test << '\n';` or to use more specific using declarations: `using std::cout; ... cout << Test;` – bames53 Aug 01 '12 at 15:43
  • @bames53 I disagree here about `std::endl`. Flushing is probably desirable here, where it looks as if the output is specifically supposed to appear at intervals, with the `Sleep(50)` in between. Otherwise if the buffer is large, you could end up with several lines appearing all at once, after a longer delay than intended. On the other hand, if you mean flush, it may be clearer to do it explicitly. – BoBTFish Aug 01 '12 at 15:48
  • 1
    @BoBTFish Since this is the Windows console using `endl` isn't actually necessary to get the output to appear immediately and IMO it's good to get into the habit of not using `endl`. But you're right that on other platforms this application might require flushing and therefore be one of the few cases where `endl` is desirable (or `flush` as you point out, since I think you're probably right about that being clearer). – bames53 Aug 01 '12 at 16:04
  • tidy up tip: you have repeated code where the only difference is whether you're incrementing or decrementing the initial spacing. I would pull the duplicated code into a function that takes the initial spacing as a parameter in order to eliminate the duplication. – bames53 Aug 01 '12 at 16:08
  • Instead of doing an infinite loop by using `do { } while(n!=0);` on a variable that is always 1 it's more readable to simply use `while(true) {}` – bames53 Aug 01 '12 at 16:21

3 Answers3

1

Why does it not seem random? Well, because it isn't. Computers use pseudorandom number generators to produce seemingly random numbers which are actually well-known and determinate.

The initial state of the pseudorandom generator is called a 'seed'; you have to set it to something different every time to produce more-close-to-random results. In C, you can do it like this:

srand(time(NULL));

This sets the seed to the actual time in seconds upon every call.

1

In order to colorize by character you have to manually iterate through the characters of the string and set the color attribute before outputting each character.

(The below code iterates by char. This doesn't work for character sets that actually use multi-byte encodings. To support those you'll have to use an API to iterate over the string by actual, user perceived characters instead of by char.)

This code has several other changes as well.

#include <iostream>
#include <string>
#include <random>

#include <Windows.h>

void colorize(size_t spacing, std::string const &s, std::mt19937 &eng) {
    std::cout << std::string(spacing, ' ');
    std::uniform_int_distribution<> dist(1,15);
    for (size_t i=0; i<s.size(); ++i) {
        SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), dist(eng));
        std::cout << s[i];
    }
    std::cout << '\n';
}

int main() {
    std::string text = "I whip my hair back and forth";
    int sz = 0;

    std::random_device r;
    std::seed_seq seed{r(), r(), r(), r(), r(), r(), r(), r()};
    std::mt19937 eng(seed);

    while (true) {
        int spacing = 11 - abs(10 - sz);
        sz = (sz+1) % 20;
        Sleep(50);
        colorize(spacing, text, eng);
    }
}

I'm using the C++11 <random> library for random numbers because it's better than rand(). It provides many ready-made distributions and is harder to get wrong (rand() % 15 + 1 has a slight bias even if rand() is high quality, which it probably is not).

I extracted the repeated code into a function to eliminate the duplication. Then I replaced the two for loops with a function that has the zigzag output that exactly matches what the two for loops were doing with sz.

I replaced the do {} while() infinite loop with a more readable and idiomatic while(true){}.

I eliminated the string variable that was being resized for the spacing in favor of constructing a temporary each iteration. This does mean there could be an allocation each iteratation instead of a simple resize (although the small string optimization will probably avoid it) but the performance is irrelevant in this case.

bames53
  • 86,085
  • 15
  • 179
  • 244
0

You need to provide a seed for your random number generator prior to first use.

An example of using srand to initialize the random number generator is:

/* srand example */
#include <stdio.h>
#include <stdlib.h>
#include <time.h>

int main ()
{
  printf ("First number: %d\n", rand() % 100);
  srand ( time(NULL) );
  printf ("Random number: %d\n", rand() % 100);
  srand ( 1 );
  printf ("Again the first number: %d\n", rand() %100);

  return 0;
}
  • 1
    Please don't make references to cplusplus dot com. It is a terrible website with a lot of bad information. – Shahbaz Aug 01 '12 at 15:34
  • Worth taking a look: [Recommended way to initialize srand?](http://stackoverflow.com/q/322938/478288) – chrisaycock Aug 01 '12 at 15:34
  • Shahbaz Care to elaborate? I alternate between the reference at cplusplus.com and cppreference, usually I don't find that much of a difference. – Cubic Aug 01 '12 at 15:37
  • 1
    @Cubic: Several years ago, some of the information there was a bit sketchy and it got a bit of a bad reputation. It looks fine these days, although I'm sure you could the odd mistake if you looked hard enough, and I expect the knee-jerk reactions every time it's referenced here will never end. – Mike Seymour Aug 01 '12 at 15:43
  • @Shahbaz is there anything wrong with this particular example, or do you just generally not like the site? – Dan Is Fiddling By Firelight Aug 01 '12 at 15:54