This article is part of C# Advent 2022 event! Thanks Matthew D. Groves for organizing it again this year! Source code available on my GitHub.
Preface
This December I spent considerable time playing with ChatGPT – an AI language model developed by OpenAI that can generate human-like text when given a prompt. It has the ability to write articles, stories, and code, and can engage in conversations with users in a natural and believable way. Impressed by what it can do, I decided to push its limits and ask it to write a Christmas tree generator program in C#, going through several rounds of improvements to arrive at the final result. To go one step further, I asked it to write the accompanying blogpost as well! This post then consists of two parts. The first generated fully by ChatGPT (including the code), the second written by me, explaining the steps I took to arrive at this result. Let’s begin!
Blogpost by ChatGPT
Christmas is just around the corner, and what better way to get into the holiday spirit than by drawing a beautiful Christmas tree using ASCII art? In this article, we’ll go through the steps of creating a C# program that draws a colorful Christmas tree with randomly placed ornaments and a brown trunk.
The Code
Here is the complete source code for the program:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
namespace ChristmasTree; | |
static class Program | |
{ | |
static void Main(string[] args) | |
{ | |
// Get the width of the tree from the first command line argument | |
int width = int.Parse(args[0]); | |
// Make sure the width is odd | |
if (width % 2 == 0) | |
{ | |
Console.WriteLine("Error: The width must be an odd number."); | |
return; | |
} | |
// Calculate the number of rows needed for the top of the tree | |
int numRows = (width + 1) / 2; | |
// Create a random number generator | |
var rand = new Random(); | |
// Draw the top of the tree | |
for (int i = 0; i < numRows; i++) | |
{ | |
// Calculate the number of asterisks for this row | |
int numAsterisks = (i * 2) + 1; | |
// Calculate the number of spaces on either side of the asterisks | |
int numSpaces = (width – numAsterisks) / 2; | |
// Choose a random number of ornaments for this row | |
int numOrnaments = rand.Next(numAsterisks + 1); | |
// Create a list of ornaments for this row | |
var ornaments = Enumerable.Repeat('o', numOrnaments).Concat(Enumerable.Repeat('*', numAsterisks – numOrnaments)).ToList(); | |
// Shuffle the ornaments | |
ornaments = ornaments.OrderBy(x => rand.Next()).ToList(); | |
// Draw the row | |
Console.ForegroundColor = ConsoleColor.Green; | |
Console.Write(new string(' ', numSpaces)); | |
for (int j = 0; j < ornaments.Count; j++) | |
{ | |
if (ornaments[j] == 'o') | |
{ | |
// Choose a random color for the ornament | |
ConsoleColor color = (ConsoleColor)rand.Next(1, 16); | |
Console.ForegroundColor = color; | |
} | |
Console.Write(ornaments[j]); | |
Console.ForegroundColor = ConsoleColor.Green; | |
} | |
Console.WriteLine(new string(' ', numSpaces)); | |
} | |
// Draw the trunk of the tree | |
Console.ForegroundColor = ConsoleColor.DarkRed; | |
Console.WriteLine(new string(' ', width / 2) + "|" + new string(' ', width / 2)); | |
Console.WriteLine(new string(' ', width / 2) + "|" + new string(' ', width / 2)); | |
// Reset the console color | |
Console.ResetColor(); | |
// Print a blank line | |
Console.WriteLine(); | |
// Print the message | |
string message = "Merry Christmas!"; | |
Console.ForegroundColor = ConsoleColor.White; | |
Console.WriteLine(new string(' ', (width – message.Length) / 2) + message + new string(' ', (width – message.Length) / 2)); | |
} | |
} |
How It Works
The program starts by parsing the first command line argument as the width of the tree. It then calculates the number of rows needed for the top of the tree based on the width. Next, it creates a random number generator to use for choosing the colors of the ornaments and shuffling their positions.
The program then enters a loop to draw the top of the tree. For each row, it calculates the number of asterisks and spaces needed, chooses a random number of ornaments, creates a list of ornaments and asterisks, shuffles the ornaments, and finally draws the row. The ornaments are given random colors by setting the System.Console.ForegroundColor
property to a random color before printing each ornament.
After the top of the tree has been drawn, the program draws the trunk using the System.Console.ForegroundColor
of DarkRed
. After the trunk has been drawn, the program resets the console color and prints a message wishing everyone a “Merry Christmas!”.
Running the Program
To run the program, you will need to have the .NET framework installed on your machine. You can then compile the program using the csc
command:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
csc ChristmasTree.cs |
This will create an executable file called ChristmasTree.exe
. You can then run the program by specifying the width of the tree as a command line argument:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
./ChristmasTree.exe 7 |
This will draw a Christmas tree with a width of 7 characters. You can try different widths to see how the tree looks with different sizes.
Example output

Conclusion
I hope you enjoyed this tutorial on how to draw a colorful Christmas tree using ASCII art in C#. Happy holidays and have a merry Christmas!
Explanation by me, the human
Pretty cool, huh? So how did me conversation with ChatGPT look like to arrive at this result?
It all started quite innocently with this prompt:

Nice and easy. But quite a small tree, right? I wanted it bigger.

Well, it is bigger, but just by one column. I tried to get a more general solution:

Very nice, in this form the tree is already looking pretty nice!

However, without the Merry Christmas, it would be hard to guess this is actually a Christmas tree! I decided there should be some ornaments added:

The generated code didn’t go too well though:

As you can see, the new code does add o
characters as ornaments, but suddenly omits the tree itself!

Ok, let’s try again:

And it did work!

Now the tree looks like this:

As we can see though, the tree is now all golden. While nice, let’s try to adjust the code, so that the ornaments have random color, the tree itself is green and the trunk is brown:

With that, the provided code generated this beauty:

Now just a final adjustment – center the text horizontally and separate it from the tree with a blank line:

Et voilà! With this I have received the final source code you could see in the first part of the article. And then I tried to go one more step further:

And what about GitHub README.md?

All neatly prepared by ChatGPT – and it even included itself in the Acknowledgements!
Summary
As you can see having the power of AI under our fingertips has the potential of accelerating not only software-development, but any creative and knowledge-based effort in general. However, as we have also seen, even though the AI can generate a valid C# code, that compiles, it is not always perfect and may not understand all requirements properly. And that’s where we, as humans need to come in. I wholeheartedly recommend you to try out ChatGPT, and imagine scenarios, where it could help you speed up your work.
Thank you for reading this far, have Merry Christmas and Happy New Year! And make sure to spend time with all your loved ones as much as possible!

Before I came across your article, I happened to have ChatGPT generate a different kind of tree… more specifically a Trie data structure in C#, and lo and behold *it did*.
It created a search by prefix as part of the implementation, complete with unit tests. I then asked it to “add method FindBySuffix() to search for words by suffix”, and it did that too. Pretty impressive.