Program: Xmas tree with flashing lights

Ta-da! Here's a present for you...

This program displays a Christmas tree with randomly allocated baubles and flashing lights, which blink once every second.




Rather than the traditional pine needles, this tree uses various ASCII characters, stored in a one-dimensional array of string values.

The tree and trunk are generated using simple for loops. Extra characters are then added over the top of the original # pine needle characters for the baubles and lights.

The second part of program uses a for loop to redraw the rows in the tree. To colour in the different parts, the code then examines each character in the array. It uses a switch statement to decide which colour to use for a particular kind of character (needles, bauble, lights, trunk etc.) and whether to use normal or bold font weights when displaying that character.

To find out more about for loops, random numbers and switch statements, take a look in the book - available directly on Amazon in the USA, UK, France, Germany, Spain, Italy and Canada.



To try out the program, select and copy the C++ source-code at the bottom of this post.


Paste into a text editor, such as Nano or Geany.

Then save the new file, ending in .cpp

I used  tree.cpp



To compile from the command-line:



    g++ -o tree tree.cpp



To run from the command-line:



    ./tree



Here's the code:



#include <iostream>  // Screen
#include <unistd.h>  // Time functions
#include <cstdlib>   // Random number functions



using namespace std;


// - - - - - - - - - -


const char NEEDLES = '#';
const char BAUBLE = 'O';
const char LIGHT1 = '*';
const char LIGHT2 = '+';
const char TOP = '&';
const char TRUNK = '%';



const string BOLD = "\e[1m";
const string NORMAL = "\e[21m";



const string RED = "\e[31m";
const string GREEN = "\e[32m";
const string AMBER = "\e[33m";
const string WHITE = "\e[37m";
const string BRIGHT_YELLOW = "\e[38;5;226m";



const string TOP_LEFT_COORDS = "\e[1;1H";


// - - - - - - - - - -


int main()
{
    // Seed the random number process to ensure new tree each time

    srandom( time( 0 ) );


    const int HEIGHT = 20;


    string tree[HEIGHT];


    int row, col, len;

    // Set up the branches

    for ( row = 0; row < HEIGHT-3; row++ )
    {

        string padding( 1 + HEIGHT - row, ' ' );
        string branch( 1 + row*2, NEEDLES );
        tree[row] = padding + branch;
    }  // End of for loop to set up branches


    // - - - - - - - - - -


    // Randomly add baubles
    for ( row = 0; row < HEIGHT; row++ )
    {
        len = tree[row].length();

        for ( col = 1 + HEIGHT - row; col < len; col++ )
            if ( random() % 6 == 0 )
                tree[row].at(col) = BAUBLE;

    }  // End of for loop to add baubles on each row of tree


    // - - - - - - - - - -


    // Randomly add on lights
    for ( row = 0; row < HEIGHT; row++ )
    {
        len = tree[row].length();

        for ( col = 1 + HEIGHT - row; col < len; col++ )
            if ( random() % 8 == 0 )
                tree[row].at(col) = LIGHT1;
       
    }  // End of for loop to add lights on each row of tree



    // - - - - - - - - - -


    // Randomly add other kind of lights
    for ( row = 0; row < HEIGHT; row++ )
    {
        len = tree[row].length();

        for ( col = 1 + HEIGHT - row; col < len; col++ )
            if ( random() % 8 == 0 )
                tree[row].at(col) = LIGHT2;

    }  // End of for loop to add lights on each row of tree
   
    // - - - - - - - - - -



    // Set up the trunk
    for ( row = HEIGHT-3; row < HEIGHT; row++ )
    {
        string padding( HEIGHT-1, ' ' );

        string trunk( 5, TRUNK );
        tree[row] = padding + trunk;
    }  // End of for loop to set up the trunk



    // - - - - - - - - - -


    // Put someone on the top!
    tree[0][HEIGHT+1] = TOP;


    // - - - - - - - - - -


    // Display the tree
    bool flashOn = false;  // Controls which set of lights is on


    // Examines one character at a time in the tree,
    // choosing the appropriate colour and bold/normal weight font
    // depending on what kind of character is about to be displayed
   
    char current;



    // Infinite loop to make lights flash continuously
    while ( true )
    {
        // Start drawing from top-left corner of terminal window

        cout << TOP_LEFT_COORDS;


        // Examine and draw one row of tree at a time
        for ( row = 0; row < HEIGHT; row++ )
        {
            len = tree[row].length();



            // Examine and draw each individual character from the row
            for ( col = 0; col < len; col++ )
            {
                current = tree[row].at(col);



                // Decide which colour and font weight to use
                switch ( current )
                {
                    // Decoration on top of the tree
                    case TOP:
                        cout << BRIGHT_YELLOW << NORMAL;
                    break;



                    // Branch colour green
                    case NEEDLES:
                        cout << GREEN << NORMAL;
                    break;



                    // Trunk colour amber
                    case TRUNK:
                        cout << AMBER << NORMAL;
                    break;



                    // Main twinkly lights
                    case LIGHT1:
                        cout << BRIGHT_YELLOW;



                        if ( flashOn )
                            cout << BOLD;
                        else
                            cout << NORMAL;
                    break;



                    // Other type of twinkly lights
                    case LIGHT2:
                        cout << AMBER;



                        if ( not flashOn )
                            cout << BOLD;
                        else
                            cout << NORMAL;
                    break;



                    // Baubles
                    case BAUBLE:
                        cout << RED << NORMAL;
                    break;



                }  // End of switch decision that decides colour for each part of tree


                // Display tiny part of the tree
                cout << current;



            }  // End of for loop that works on a single row


            cout << endl;


        }  // End of for loop that controls which row is being displayed


        // Wait one second in between flashes
        sleep( 1 );
       
        // Change which set of lights will be on or off
        flashOn = not flashOn;



    }  // End of infinite while loop block


// End of program 


Find out more - buy the book on Amazon...