#include #include #include #include #ifdef _WIN32 #include #include #define CLEAR "cls" #else #include #include #include #define CLEAR "clear" int getch(void) { struct termios o, n; tcgetattr(STDIN_FILENO, &o); n = o; n.c_lflag &= ~(ICANON | ECHO); tcsetattr(STDIN_FILENO, TCSANOW, &n); int ch = getchar(); tcsetattr(STDIN_FILENO, TCSANOW, &o); return ch; } #endif #define SIZE 16 #define MAX_SNAKE 256 #define MAX_VARS 10 #define MAX_CODE 8192 typedef struct { int x, y; } Point; typedef enum { NONE, VARIABLE, ARRAY, FUNCTION, MAIN_FUNC, STATEMENT } EntityType; typedef enum { STATE_NORMAL, STATE_CREATE, STATE_SELECT_ENTITY, STATE_SET_VALUE, STATE_SET_DIM, STATE_SET_ARRAY_SIZE, STATE_SELECT_VAR, STATE_SELECT_STATEMENT, STATE_BUILD_EXPR, STATE_BUILD_IF_COND, STATE_BUILD_WHILE_COND, STATE_BUILD_DO_COND, STATE_SET_LOOP_INIT, STATE_SET_LOOP_COND, STATE_SET_LOOP_INC } GameState; typedef enum { STMT_NONE, STMT_IF, STMT_WHILE, STMT_FOR, STMT_DO_WHILE, STMT_ASSIGN, STMT_CALL, STMT_BREAK, STMT_RETURN, STMT_BLOCK_END } StatementType; typedef enum { BT_NONE, BT_IF, BT_WHILE, BT_FOR, BT_DO_WHILE, BT_FUNC, BT_MAIN } BlockType; typedef struct { char name[32]; char value[64]; int used; } Variable; typedef struct { char name[32]; int dimensions; int sizes[3]; int used; } Array; typedef struct { char name[32]; char params[128]; char body[512]; int used; } Function; Point snake[MAX_SNAKE]; int slen = 3; int dx = 1, dy = 0; char grid[SIZE][SIZE]; char code[MAX_CODE] = ""; GameState state = STATE_NORMAL; EntityType creating = NONE; StatementType current_stmt = STMT_NONE; int selected_entity = 0; Variable vars[MAX_VARS]; Array arrs[MAX_VARS]; Function funcs[MAX_VARS]; int has_main = 0; char current_value[128] = ""; char current_value2[128] = ""; char current_operation[8] = ""; int setting_second_value = 0; int current_dim_count = 0; int indent_level = 0; // For building complex statements char expr_buffer[256] = ""; char condition_buffer[256] = ""; char loop_init[128] = ""; char loop_cond[128] = ""; char loop_inc[128] = ""; BlockType block_stack[32]; int block_level = 0; #ifndef _WIN32 int old_flags; #endif void add_indent() { for (int i = 0; i < indent_level; i++) { strcat(code, " "); } } void init_game() { snake[0].x = 3; snake[0].y = 8; snake[1].x = 2; snake[1].y = 8; snake[2].x = 1; snake[2].y = 8; for (int i = 0; i < MAX_VARS; i++) { vars[i].used = 0; arrs[i].used = 0; funcs[i].used = 0; } memset(block_stack, 0, sizeof(block_stack)); block_level = 0; #ifndef _WIN32 old_flags = fcntl(STDIN_FILENO, F_GETFL, 0); fcntl(STDIN_FILENO, F_SETFL, old_flags | O_NONBLOCK); #endif } void check_collision() { int hx = snake[0].x; int hy = snake[0].y; // Wrap through walls if (hx < 0) hx = SIZE - 1; if (hx >= SIZE) hx = 0; if (hy < 0) hy = SIZE - 1; if (hy >= SIZE) hy = 0; snake[0].x = hx; snake[0].y = hy; // Check special tiles if (state == STATE_NORMAL) { // Creation tiles if (hx == 1 && hy == 2) { state = STATE_CREATE; creating = VARIABLE; } else if (hx == 1 && hy == 4) { state = STATE_CREATE; creating = ARRAY; } else if (hx == 1 && hy == 6) { state = STATE_CREATE; creating = FUNCTION; } else if (hx == 1 && hy == 8) { state = STATE_CREATE; creating = MAIN_FUNC; } else if (hx == 1 && hy == 10) { state = STATE_SELECT_STATEMENT; creating = STATEMENT; } // Print code else if (hx == 15 && hy == 14) { printf("\n=== GENERATED CODE ===\n%s\n=====================\n", code); printf("Press any key to continue..."); while (getch() != 10); } // Close block } else if (hx == 15 && hy == 13) { if (block_level > 0) { BlockType bt = block_stack[--block_level]; indent_level--; add_indent(); if (bt == BT_DO_WHILE) { state = STATE_BUILD_DO_COND; strcpy(condition_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else { strcat(code, "}\n"); } } } } else if (state == STATE_CREATE) { // Select entity (variables/arrays/functions 0-9) if (hx == 3 && hy >= 2 && hy <= 11) { selected_entity = hy - 2; if (creating == VARIABLE) { if (!vars[selected_entity].used) { sprintf(vars[selected_entity].name, "var%d", selected_entity); vars[selected_entity].used = 1; strcpy(vars[selected_entity].value, ""); state = STATE_SET_VALUE; strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } } else if (creating == ARRAY) { if (!arrs[selected_entity].used) { sprintf(arrs[selected_entity].name, "arr%d", selected_entity); arrs[selected_entity].used = 1; arrs[selected_entity].dimensions = 0; for (int i = 0; i < 3; i++) arrs[selected_entity].sizes[i] = 0; state = STATE_SET_DIM; strcpy(current_value, ""); current_dim_count = 0; } } else if (creating == FUNCTION) { if (!funcs[selected_entity].used) { sprintf(funcs[selected_entity].name, "func%d", selected_entity); funcs[selected_entity].used = 1; strcpy(funcs[selected_entity].params, ""); strcpy(funcs[selected_entity].body, ""); add_indent(); char line[256]; sprintf(line, "void %s() {\n", funcs[selected_entity].name); strcat(code, line); indent_level++; block_stack[block_level++] = BT_FUNC; state = STATE_NORMAL; } } else if (creating == MAIN_FUNC) { if (!has_main) { has_main = 1; add_indent(); strcat(code, "int main() {\n"); indent_level++; block_stack[block_level++] = BT_MAIN; state = STATE_NORMAL; } } } } else if (state == STATE_SELECT_STATEMENT) { // Use selectors at col 3 if (hx == 3 && hy >= 2 && hy <= 11) { int stmt_idx = hy - 2; StatementType stmts[] = {STMT_IF, STMT_WHILE, STMT_FOR, STMT_DO_WHILE, STMT_ASSIGN, STMT_CALL, STMT_BREAK, STMT_RETURN, STMT_BLOCK_END}; if (stmt_idx < 9) { current_stmt = stmts[stmt_idx]; if (current_stmt == STMT_BREAK) { add_indent(); strcat(code, "break;\n"); state = STATE_NORMAL; } else if (current_stmt == STMT_RETURN) { add_indent(); strcat(code, "return "); state = STATE_BUILD_EXPR; strcpy(expr_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else if (current_stmt == STMT_BLOCK_END) { if (block_level > 0) { BlockType bt = block_stack[--block_level]; indent_level--; add_indent(); if (bt == BT_DO_WHILE) { state = STATE_BUILD_DO_COND; strcpy(condition_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else { strcat(code, "}\n"); } } state = STATE_NORMAL; } else if (current_stmt == STMT_IF) { state = STATE_BUILD_IF_COND; strcpy(condition_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else if (current_stmt == STMT_WHILE) { state = STATE_BUILD_WHILE_COND; strcpy(condition_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else if (current_stmt == STMT_FOR) { state = STATE_SET_LOOP_INIT; strcpy(loop_init, ""); strcpy(loop_cond, ""); strcpy(loop_inc, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } else if (current_stmt == STMT_DO_WHILE) { add_indent(); strcat(code, "do {\n"); indent_level++; block_stack[block_level++] = BT_DO_WHILE; state = STATE_NORMAL; } else if (current_stmt == STMT_ASSIGN || current_stmt == STMT_CALL) { state = STATE_BUILD_EXPR; strcpy(expr_buffer, ""); strcpy(current_value, ""); strcpy(current_value2, ""); strcpy(current_operation, ""); setting_second_value = 0; } } } } else if (state == STATE_SET_DIM) { // Set dimension count for array if (hx >= 2 && hx <= 11 && hy == 14) { int digit = hx - 2; if (digit >= 1 && digit <= 3) { arrs[selected_entity].dimensions = digit; state = STATE_SET_ARRAY_SIZE; strcpy(current_value, ""); current_dim_count = 0; } } } else if (state == STATE_SET_ARRAY_SIZE) { // Set size for each dimension if (hx >= 2 && hx <= 11 && hy == 14) { int digit = hx - 2; char d[2] = {digit + '0', '\0'}; strcat(current_value, d); } // Confirm dimension size with S else if (hx == 15 && hy == 10) { if (strlen(current_value) > 0) { arrs[selected_entity].sizes[current_dim_count] = atoi(current_value); current_dim_count++; strcpy(current_value, ""); // If all dimensions set, generate code if (current_dim_count >= arrs[selected_entity].dimensions) { add_indent(); char line[128]; sprintf(line, "int %s", arrs[selected_entity].name); for (int i = 0; i < arrs[selected_entity].dimensions; i++) { char dim[16]; sprintf(dim, "[%d]", arrs[selected_entity].sizes[i]); strcat(line, dim); } strcat(line, ";\n"); strcat(code, line); state = STATE_NORMAL; } } } } else if (state == STATE_SET_VALUE || state == STATE_BUILD_IF_COND || state == STATE_BUILD_WHILE_COND || state == STATE_BUILD_DO_COND || state == STATE_BUILD_EXPR || state == STATE_SET_LOOP_INIT || state == STATE_SET_LOOP_COND || state == STATE_SET_LOOP_INC) { // Number tiles (0-9) if (hx >= 2 && hx <= 11 && hy == 14) { int digit = hx - 2; char d[2] = {digit + '0', '\0'}; if (setting_second_value) { strcat(current_value2, d); } else { strcat(current_value, d); } } // Variable selection area (col 4) else if (hx == 4 && hy >= 2 && hy <= 11) { int var_idx = hy - 2; if (vars[var_idx].used) { if (setting_second_value) { strcat(current_value2, vars[var_idx].name); } else { strcat(current_value, vars[var_idx].name); } } } // Array selection with index (col 6) else if (hx == 6 && hy >= 2 && hy <= 11) { int arr_idx = hy - 2; if (arrs[arr_idx].used) { char arr_access[64]; sprintf(arr_access, "%s[", arrs[arr_idx].name); if (setting_second_value) { strcat(current_value2, arr_access); } else { strcat(current_value, arr_access); } } } // Function call (col 11) else if (hx == 11 && hy >= 2 && hy <= 11) { int func_idx = hy - 2; if (funcs[func_idx].used) { char func_call[64]; sprintf(func_call, "%s(", funcs[func_idx].name); if (setting_second_value) { strcat(current_value2, func_call); } else { strcat(current_value, func_call); } } } // Operations else if (hx == 13 && hy >= 2 && hy <= 13) { int idx = hy - 2; if (idx < 12) { const char *ops[] = {"+", "-", "*", "/", ">", "<", "==", "&&", ">=", "<=", "!=", "||"}; if (setting_second_value && strlen(current_operation) > 0) { char temp[256]; sprintf(temp, " %s %s", current_operation, current_value2); strcat(current_value, temp); strcpy(current_value2, ""); strcpy(current_operation, ""); } strcpy(current_operation, ops[idx]); setting_second_value = 1; } } // Special chars else if (hx == 12 && hy >= 2 && hy <= 13) { int idx = hy - 2; if (idx < 12) { const char *chars[] = {"[", "]", "(", ")", ",", "=", ";", ".", "!", "~", "&", "*"}; char s[2] = {chars[idx][0], '\0'}; if (setting_second_value) { strcat(current_value2, s); } else { strcat(current_value, s); } } } // Confirm with set button else if (hx == 15 && hy == 10) { char line[256]; char buffer[256] = ""; if (strlen(current_operation) > 0 && strlen(current_value2) > 0) { sprintf(buffer, "%s %s %s", current_value, current_operation, current_value2); } else { strcpy(buffer, current_value); } if (state == STATE_SET_VALUE) { if (strlen(buffer) > 0) { add_indent(); sprintf(line, "int %s = %s;\n", vars[selected_entity].name, buffer); strcat(code, line); } else { add_indent(); sprintf(line, "int %s;\n", vars[selected_entity].name); strcat(code, line); } state = STATE_NORMAL; } else if (state == STATE_BUILD_IF_COND || state == STATE_BUILD_WHILE_COND || state == STATE_BUILD_DO_COND) { strcpy(condition_buffer, buffer); add_indent(); if (state == STATE_BUILD_DO_COND) { strcat(code, "} while ("); strcat(code, condition_buffer); strcat(code, ");\n"); } else { strcat(code, state == STATE_BUILD_IF_COND ? "if (" : "while ("); strcat(code, condition_buffer); strcat(code, ") {\n"); indent_level++; block_stack[block_level++] = state == STATE_BUILD_IF_COND ? BT_IF : BT_WHILE; } state = STATE_NORMAL; } else if (state == STATE_SET_LOOP_INIT) { strcpy(loop_init, buffer); state = STATE_SET_LOOP_COND; } else if (state == STATE_SET_LOOP_COND) { strcpy(loop_cond, buffer); state = STATE_SET_LOOP_INC; } else if (state == STATE_SET_LOOP_INC) { strcpy(loop_inc, buffer); add_indent(); sprintf(line, "for (%s; %s; %s) {\n", loop_init, loop_cond, loop_inc); strcat(code, line); indent_level++; block_stack[block_level++] = BT_FOR; state = STATE_NORMAL; } else if (state == STATE_BUILD_EXPR) { strcpy(expr_buffer, buffer); add_indent(); if (current_stmt == STMT_RETURN) { sprintf(line, "return %s;\n", expr_buffer); } else { sprintf(line, "%s;\n", expr_buffer); } strcat(code, line); state = STATE_NORMAL; } } } // Undo button if (hx == 15 && hy == 12) { if (state == STATE_SET_VALUE || state == STATE_BUILD_IF_COND || state == STATE_BUILD_WHILE_COND || state == STATE_BUILD_DO_COND || state == STATE_BUILD_EXPR || state == STATE_SET_LOOP_INIT || state == STATE_SET_LOOP_COND || state == STATE_SET_LOOP_INC) { if (setting_second_value && strlen(current_value2) > 0) { strcpy(current_value2, ""); } else if (strlen(current_value) > 0) { strcpy(current_value, ""); } else { strcpy(current_operation, ""); setting_second_value = 0; } } else if (state == STATE_SET_ARRAY_SIZE) { strcpy(current_value, ""); } } } void move_snake() { for (int i = slen - 1; i > 0; i--) { snake[i] = snake[i - 1]; } snake[0].x += dx; snake[0].y += dy; check_collision(); } void draw() { system(CLEAR); // Clear grid for (int i = 0; i < SIZE; i++) { for (int j = 0; j < SIZE; j++) { grid[i][j] = '.'; } } // Mark creation tiles grid[2][1] = 'V'; grid[4][1] = 'A'; grid[6][1] = 'F'; grid[8][1] = 'M'; grid[10][1] = 'S'; // Selection rows for (int i = 2; i <= 11; i++) { grid[i][3] = '0' + (i - 2); // Entity selection if (vars[i - 2].used) grid[i][4] = 'V'; // Vars at col 4 if (arrs[i - 2].used) grid[i][6] = 'A'; // Arrays at col 6 if (funcs[i - 2].used) grid[i][11] = 'F'; // Functions at col 11 } // Number tiles for (int i = 2; i <= 11; i++) { grid[14][i] = '0' + (i - 2); } // Operation tiles char display_ops[12] = {'+', '-', '*', '/', '>', '<', '=', '&', 'g', 'l', 'n', 'o'}; for (int i = 0; i < 12; i++) { if (2 + i < SIZE) grid[2 + i][13] = display_ops[i]; } // Special character tiles char display_chars[12] = {'[', ']', '(', ')', ',', '=', ';', '.', '!', '~', '&', '*'}; for (int i = 0; i < 12; i++) { if (2 + i < SIZE) grid[2 + i][12] = display_chars[i]; } // Action tiles grid[10][15] = 'S'; // Set grid[12][15] = 'U'; // Undo grid[13][15] = '}'; // Close block grid[14][15] = 'P'; // Print // Draw snake for (int i = 0; i < slen; i++) { int x = snake[i].x; int y = snake[i].y; if (x >= 0 && x < SIZE && y >= 0 && y < SIZE) { grid[y][x] = (i == 0) ? '@' : '#'; } } // Print grid printf("╔"); for (int i = 0; i < SIZE * 2; i++) printf("═"); printf("╗\n"); for (int i = 0; i < SIZE; i++) { printf("║"); for (int j = 0; j < SIZE; j++) { printf("%c ", grid[i][j]); } printf("║\n"); } printf("╚"); for (int i = 0; i < SIZE * 2; i++) printf("═"); printf("╝\n"); printf("\nWASD=Move Q=Quit | Indent: %d\n", indent_level); printf("State: "); switch (state) { case STATE_NORMAL: printf("NORMAL"); break; case STATE_CREATE: printf("CREATING"); break; case STATE_SELECT_STATEMENT: printf("SELECT STATEMENT"); break; case STATE_SET_VALUE: printf("SET VALUE"); break; case STATE_BUILD_IF_COND: case STATE_BUILD_WHILE_COND: case STATE_BUILD_DO_COND: printf("BUILD CONDITION"); break; case STATE_BUILD_EXPR: printf("BUILD EXPRESSION"); break; case STATE_SET_DIM: printf("SET DIMENSION"); break; case STATE_SET_ARRAY_SIZE: printf("SET SIZE [%d/%d]", current_dim_count + 1, arrs[selected_entity].dimensions); break; case STATE_SET_LOOP_INIT: printf("FOR INIT"); break; case STATE_SET_LOOP_COND: printf("FOR CONDITION"); break; case STATE_SET_LOOP_INC: printf("FOR INCREMENT"); break; default: printf("UNKNOWN"); break; } printf("\n"); if (state == STATE_SET_VALUE || state == STATE_BUILD_IF_COND || state == STATE_BUILD_WHILE_COND || state == STATE_BUILD_DO_COND || state == STATE_BUILD_EXPR || state == STATE_SET_LOOP_INIT || state == STATE_SET_LOOP_COND || state == STATE_SET_LOOP_INC) { printf("Val1: %s | Op: %s | Val2: %s\n", current_value, current_operation, current_value2); printf("%s\n", setting_second_value ? "(2nd value)" : "(1st value)"); } else if (state == STATE_SET_DIM) { printf("Dimensions (1-3): %s\n", current_value); } else if (state == STATE_SELECT_STATEMENT) { printf("Selectors 0-9: 0=if 1=while 2=for 3=do-while 4=assign 5=call 6=break 7=return 8=}\n"); } printf("\nLegend:\n"); printf("V=Var A=Array F=Func M=Main S=Stmt | Col3=Select Col4=Vars Col6=Arrays\n"); printf("Col11=Funcs | Bottom=0-9 | Right:[]()*+/><=&\n"); printf("S=Set U=Undo }=Close P=Print\n"); } int main() { init_game(); char input; printf("Programming Snake - Write C code!\n"); printf("Create variables, arrays, functions, and control structures.\n"); printf("Press any key to start...\n"); getch(); while (1) { draw(); int ch; #ifdef _WIN32 if (_kbhit()) { ch = getch(); } else { ch = -1; } #else ch = getch(); #endif if (ch != -1) { input = (char)ch; if (input == 'q' || input == 'Q') break; else if (input == 'w' || input == 'W') { dx = 0; dy = -1; } else if (input == 's' || input == 'S') { dx = 0; dy = 1; } else if (input == 'a' || input == 'A') { dx = -1; dy = 0; } else if (input == 'd' || input == 'D') { dx = 1; dy = 0; } move_snake(); } #ifdef _WIN32 Sleep(150); #else usleep(150000); #endif } #ifndef _WIN32 fcntl(STDIN_FILENO, F_SETFL, old_flags); #endif printf("\n=== FINAL CODE ===\n%s\n==================\n", code); return 0; }