Last active
October 14, 2022 08:33
-
-
Save RobThree/3f8f768514d04e7d306c7e43fe2522ce to your computer and use it in GitHub Desktop.
Random animated string (see https://www.reddit.com/r/programming/y13q8x )
This file contains hidden or 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
// Use chars from input value with custom iterations | |
WriteAnimatedString("Hello world", 50); | |
Console.WriteLine(); | |
// Use printable ASCII chars with left-to-right effect | |
var chars = Enumerable.Range(32, 127).Select(c => (char)c); | |
WriteAnimatedString("I learned something new today!", animationStyle: AnimationStyle.LeftToRight, chars: chars); | |
Console.WriteLine(); | |
static void WriteAnimatedString( | |
string value, | |
int maxiterations = 200, | |
TimeSpan? sleep = null, | |
AnimationStyle animationStyle = AnimationStyle.Random, | |
IEnumerable<char>? chars = null) | |
{ | |
// Input validation | |
ArgumentNullException.ThrowIfNull(value, nameof(value)); | |
if (maxiterations <= 0) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(maxiterations)); | |
} | |
if (sleep < TimeSpan.Zero) | |
{ | |
throw new ArgumentOutOfRangeException(nameof(sleep)); | |
} | |
// Initialization and setup | |
var rng = new Random(42); // Random number generator with fixed seed so animations are deterministic | |
var currentchars = value.Select(c => ' ').ToArray(); // Initialize a char array of same length as input with spaces | |
var counters = Enumerable.Range(0, value.Length) // Initialize letter counters | |
.Select(i => animationStyle switch | |
{ | |
AnimationStyle.SingleShot => maxiterations, // All counters same value | |
AnimationStyle.LeftToRight => (int)Math.Ceiling((i + 1) * (maxiterations / (double)value.Length)), // Ascending counters | |
AnimationStyle.RightToLeft => (int)Math.Ceiling(maxiterations - (i * (maxiterations / (double)value.Length))), // Descending counters | |
AnimationStyle.Random or _ => rng.Next(maxiterations) // Random counters | |
}).ToArray(); | |
var rndchars = (chars ?? value.Select(c => c)) | |
.Distinct().ToArray(); // Initialize available chars (when none specified, use inputstring as source) | |
sleep ??= TimeSpan.FromMilliseconds(10); // Default sleep to 10 ms is not specified | |
var (cp_left, cp_top) = Console.GetCursorPosition(); // Get cursor position before we do anything | |
// Go time! | |
Console.CursorVisible = false; // Hide cursor | |
while (!currentchars.SequenceEqual(value)) // Keep going until currentchars equals input value | |
{ | |
Console.SetCursorPosition(cp_left, cp_top); // Return cursor to position where we first found it at | |
Thread.Sleep(sleep.Value); // Slow down 'animation' | |
for (var i = 0; i < value.Length; i++) // Randomize string by iterating each letter | |
{ | |
currentchars[i] = --counters[i] <= 0 // Decrease counter, then when at 0 or less... | |
? value[i] // ...pick actual letter from string | |
: rndchars[rng.Next(rndchars.Length)]; // ...else pick random letter | |
} | |
Console.Write(currentchars, 0, currentchars.Length); // Output string | |
} | |
Console.CursorVisible = true; // Show cursor | |
} | |
public enum AnimationStyle | |
{ | |
Random = 0, | |
SingleShot = 1, | |
LeftToRight = 2, | |
RightToLeft = 3 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment