This project demonstrates a concept called quine, or "self-reproducing program".
The main problem I faced, which I guess anyone is facing when making such a program is that every print you do has to be printed by itself so at first glance you'd think the code size has to be infinite.
The main trick that allows it to work abuses the fact that when strings are passed into a formatting function they are formatted only if they are passed as the first argument but not when passed through %s, so formatting "...%s" with string input of "..." will give you both a formatted version and an unformatted version of the string.
So if you want a string containing "a" you can do char *f="a"; and then sprintf(buffer, f), which is obvious but then, extend the logic we described and you can get "char *f=\"achar *f=\\\"a%s\\\"\"" into the buffer by defining char *f="a%s"; and using sprintf(buffer, f, f), and you can use any formatting function not just sprintf.
Another problem I faced was when I wanted to make it possible to run the program from windows, so I had to make the main formatted string way longer which I didn't want, so the trick I used was to make the first program to run unidentical to the rest as a sort of "generetor".
Another small trick that I thought of for this purpose is defining #define X(...) #__VA_ARGS__, #define S(x) X(x), which together with platform specific macros I defined help make the main formatted string suitable for the platform it was preprocessed on.
As a result of using a generator anything that can be generated at runtime we do not need to define for the compiler to do at compile time e.g. we can make the game's rows and cols calculated at runtime of the generator to make the C code more elegant and more importantly easier to refactor and change.
The rest is a couple basic I/O tricks you can read in the code yourself as it's easier to understand that way IMO then reading without the code.