Created
March 16, 2025 16:54
-
-
Save gvanem/441ed2dd0d819d52e0acd7073e5dd8dc to your computer and use it in GitHub Desktop.
Matrix clone in C
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
/* | |
* "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