Skip to content

Instantly share code, notes, and snippets.

@gvanem
Created March 16, 2025 16:54
Show Gist options
  • Save gvanem/441ed2dd0d819d52e0acd7073e5dd8dc to your computer and use it in GitHub Desktop.
Save gvanem/441ed2dd0d819d52e0acd7073e5dd8dc to your computer and use it in GitHub Desktop.
Matrix clone in C
/*
* "Bleh" -- a "potato-friendly" cmatrix clone.
*
* Screenshot: https://i.imgur.com/dt6RmU7.png
*
* Adapted to Windows from:
* https://www.reddit.com/r/commandline/comments/1jcnyht/bleh_a_potatofriendly_cmatrix_clone/
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>
#include <conio.h>
#include <windows.h>
#define DELAY_MS 80
#define RAND_RANGE 94
#define MIN_STREAM_LEN 5
typedef struct {
uint16_t x;
uint16_t y;
uint16_t prev_y;
uint8_t length;
uint8_t active;
} Stream;
static int get_terminal_size (uint16_t *rows, uint16_t *cols)
{
CONSOLE_SCREEN_BUFFER_INFO console_info;
HANDLE console_hnd = GetStdHandle (STD_OUTPUT_HANDLE);
int okay = (console_hnd != INVALID_HANDLE_VALUE &&
GetConsoleScreenBufferInfo(console_hnd, &console_info) &&
GetFileType(console_hnd) == FILE_TYPE_CHAR);
if (okay)
{
*rows = console_info.srWindow.Bottom - console_info.srWindow.Top + 1;
*cols = console_info.srWindow.Right - console_info.srWindow.Left + 1;
}
return (okay);
}
int main (void)
{
uint16_t i, j, max_y, max_x;
if (!get_terminal_size(&max_y, &max_x))
{
fprintf (stderr, "Failed to get the screen-size.\n");
return (1);
}
srand ((unsigned int) time(NULL));
Stream *streams = calloc (max_x, sizeof(Stream));
if (!streams)
return (1);
for (i = 0; i < max_x; i++)
{
streams [i].x = i;
streams [i].y = rand() % max_y;
streams [i].prev_y = streams[i].y;
streams [i].length = (rand() % (max_y / 2)) + MIN_STREAM_LEN;
streams [i].active = rand() & 1;
}
printf ("\e[2J\e[?25l");
while (!_kbhit())
{
for (i = 0; i < max_x; i++)
{
if (streams[i].active)
{
uint16_t y = streams [i].y;
uint16_t prev_y = streams [i].prev_y;
uint8_t len = streams [i].length;
if (y != prev_y)
{
for (j = 0; j < len; j++)
{
uint16_t prev_pos = prev_y - j;
if (prev_pos >= 0 && prev_pos < max_y)
printf ("\e[%d;%dH ", prev_pos + 1, i + 1);
}
}
if (y < max_y + len)
{
for (j = 0; j < len; j++)
{
uint16_t pos = y - j;
if (pos >= 0 && pos < max_y)
printf ("\e[%d;%dH%s%c",
pos + 1, i + 1, j == 0 ? "\e[97m" : "\e[32m",
(rand() % RAND_RANGE) + 33);
}
}
streams[i].prev_y = y;
if (++streams[i].y - len >= max_y)
{
streams [i].y = 0;
streams [i].prev_y = 0;
streams [i].length = (rand() % (max_y / 2)) + MIN_STREAM_LEN;
streams [i].active = (rand() % 5) != 0;
}
}
else if ((rand() % 50) == 0)
{
streams [i].active = 1;
streams [i].y = 0;
streams [i].prev_y = 0;
streams [i].length = (rand() % (max_y / 2)) + MIN_STREAM_LEN;
}
}
fflush (stdout);
Sleep (DELAY_MS);
}
printf ("\e[?25h\e[0m");
fflush (stdout);
free (streams);
return (0);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment