#define VERSION "1.10" #define N 9 #define USERNAME_LENGTH 10 #include #include #include #include #include FILE *fp; int matrix[N][N] = {0}; // structs struct point{ int x; int y; } ptr; struct res { int moves; int grid; char user[USERNAME_LENGTH]; time_t playtime; } current; typedef struct Node { struct res result; struct Node* next; } Node; typedef Node* ptrNode; ptrNode List; // functions void importdata(); void menu(); void play(); void start(); void move_ptr(int direction); void nolow(); void settings(); void ranking(); void rules(); void printm(); int win(); ptrNode InsertInList(ptrNode List, struct res elem); ptrNode InsertFirst(ptrNode List, struct res elem); int EmptyList(ptrNode List); int main() { initscr(); noecho(); cbreak(); keypad(stdscr, true); if (has_colors() == TRUE) { start_color(); init_pair(1, COLOR_BLACK, COLOR_WHITE); } srand(time(NULL)); fp = fopen("roofus.txt", "a+"); if (fp == NULL) { printw("Error opening file"); refresh(); getch(); endwin(); return 1; } else { importdata(); menu(); fclose(fp); endwin(); return 0; } } void importdata() { int lenght; struct res temp; // import last grid size fseek(fp, -2, SEEK_END); current.grid = fgetc(fp) - '0'; if (current.grid < 3 || current.grid > 9) current.grid = 5; lenght = ftell(fp); rewind(fp); // import results while (ftell(fp) < lenght) { fscanf(fp, "%li %d %s %d", &temp.playtime, &temp.moves, temp.user, &temp.grid); List = InsertInList(List, temp); } } void menu() { while (1) { clear(); printw("~~~ ROOFUS %dx%d ~~~\n\n" "[1] Play\n" "[2] Ranking\n" "[3] Settings\n" "[4] Rules\n" "[q] Quit\n\nv%s\n\n", current.grid, current.grid, VERSION); refresh(); switch (getch()) { case '1': play(); break; case '2': ranking(); break; case '3': settings(); break; case '4': rules(); break; case 'q': return; } } } void play() { int direction, end = 0, replay; char *text = malloc(sizeof(text) * N); do { replay = 0; current.moves = 0; ptr.x = ptr.y = current.grid / 2; start(); while (end == 0) { printw("\n[q] Quit. [r] Restart\nArrow to move "); refresh(); direction = getch(); if (direction == 'q') { printw("\nQuit? [y/n] "); refresh(); if (getch() == 'y') break; else direction = 0; } if (direction == 'r') { printw("\nRestart? [y/n] "); refresh(); if (getch() == 'y') { replay = 1; break; } else direction = 0; } if (direction != 0) { move_ptr(direction); printm(); end = win(); if (end == 1) { current.playtime = time(NULL); printw("Enter your name: "); refresh(); echo(); getnstr(current.user, USERNAME_LENGTH); // read at most noecho(); sprintf(text, "%li %d %s %d\n", current.playtime, current.moves, current.user, current.grid); fputs(text, fp); List = InsertInList(List, current); } } else printm(); } } while (replay == 1); free(text); return; } void start() { for (int i = 0; i < current.grid; i++) { for (int j = 0; j < current.grid; j++) { matrix[i][j] = rand() % 19 + 1; } } nolow(); printm(); } // move pointer void move_ptr(int direction) { int xinit = ptr.x, yinit = ptr.y; int i, j, del = 0; switch (direction) { case KEY_LEFT: if (ptr.x != 0) { ptr.x--; for (j = 0; j < xinit; j++) { if (matrix[ptr.y][j] != 0) { matrix[ptr.y][j] = matrix[ptr.y][j] - matrix[ptr.y][xinit]; if (matrix[ptr.y][j] == 0) del = 1; if (matrix[ptr.y][j] < 0 && matrix[yinit][xinit] != 0) matrix[ptr.y][j] = - matrix[ptr.y][j]; } } } break; case KEY_RIGHT: if (ptr.x < current.grid - 1) { ptr.x++; for (j = ptr.x; j < current.grid; j++) { if (matrix[ptr.y][j] != 0) { matrix[ptr.y][j] = matrix[ptr.y][j] - matrix[yinit][xinit]; if (matrix[ptr.y][j] == 0) del = 1; if (matrix[ptr.y][j] < 0 && matrix[yinit][xinit] != 0) matrix[ptr.y][j] = - matrix[ptr.y][j]; } } } break; case KEY_UP: if (ptr.y > 0) { ptr.y--; for (i = ptr.y; i >= 0; i--) { if (matrix[i][ptr.x] != 0) { matrix[i][ptr.x] = matrix[i][ptr.x] - matrix[yinit][xinit]; if (matrix[i][ptr.x] == 0) del = 1; if (matrix[i][ptr.x] < 0 && matrix[yinit][xinit] != 0) matrix[i][ptr.x] = - matrix[i][ptr.x]; } } } break; case KEY_DOWN: if (ptr.y < current.grid - 1) { ptr.y++; for (i = ptr.y; i < current.grid; i++) { if(matrix[i][ptr.x] != 0) { matrix[i][ptr.x] = matrix[i][ptr.x] - matrix[yinit][xinit]; if (matrix[i][ptr.x] == 0) del = 1; if (matrix[i][ptr.x] < 0 && matrix[yinit][xinit] != 0) matrix[i][ptr.x] = - matrix[i][ptr.x]; } } } break; default: return; } if (del == 1) matrix[yinit][xinit] = 0; nolow(); if (xinit != ptr.x || yinit != ptr.y) current.moves++; } // if 1 or 2 -> random number void nolow() { for (int i = 0; i < current.grid; i++) { for (int j = 0; j < current.grid; j++) { if ( matrix[i][j] < 3 && matrix[i][j] > 0) matrix[i][j] = rand() % 10 - 10; } } } void settings() { while (1) { clear(); printw("> Settings\n\n"); printw("Menu [q]\nGrid size? [3-9] "); refresh(); switch (getch()) { case 'q': return; case '3': current.grid = 3; return; case '4': current.grid = 4; return; case '5': current.grid = 5; return; case '6': current.grid = 6; return; case '7': current.grid = 7; return; case '8': current.grid = 8; return; case '9': current.grid = 9; return; default: break; } } } void ranking() { int grid_rank = current.grid; int printed; ptrNode ptrList; do { printed = 0; clear(); if (grid_rank >= 3 && grid_rank <= 9) printw("Best results (%dx%d matrix):\n\n", grid_rank, grid_rank); else printw("Best results:\n\n"); for (ptrList = List; ptrList != NULL; ptrList = ptrList->next) { if ((ptrList->result.grid == grid_rank || grid_rank == 1) && printed < 9 && ptrList->result.moves != 0) { printw("# %d - %3d moves\t- (%dx%d matrix) - %s\t- %s", printed + 1, ptrList->result.moves, ptrList->result.grid, ptrList->result.grid, ptrList->result.user, ctime(&ptrList->result.playtime)); printed++; } } if (printed == 0) printw("Nothing to show...\n"); printw("\nMenu [q]; To filter by matrix size [3-9]; No filter [1] "); refresh(); do { grid_rank = getch() - '0'; } while ((grid_rank < 3 || grid_rank > 9) && grid_rank != 1 && grid_rank != 'q'-'0'); } while (grid_rank != ('q'-'0')); } void rules() { clear(); printw("> Rules\n\n"); printw("Delete numbers on the table by moving the pointer.\n"); printw("That's all you need to know\n"); refresh(); getch(); } // print matrix void printm() { clear(); printw("\n\n"); for (int i = 0; i < current.grid; i++) { for (int j = 0; j < current.grid; j++) { if (i == ptr.y && j == ptr.x) { if (has_colors() == TRUE) attron(COLOR_PAIR(1)); else printw("> "); } if (matrix[i][j] != 0) printw("%2d", matrix[i][j]); else { if (has_colors() == FALSE) printw(" "); else printw(" ."); } if (has_colors() == TRUE) attroff(COLOR_PAIR(1)); printw("\t"); } printw("\n\n"); } refresh(); } int win() { int count = 0; for (int i = 0; i < current.grid; i++) { for (int j = 0; j < current.grid; j++) { if (matrix[i][j] == 0) count++; } } if (count >= current.grid * (current.grid - 1)) { printw("\nYou win! Moves: %d\n", current.moves); refresh(); getchar(); return 1; } else { printw("\nYou still need to delete %d numbers. Moves: %d", current.grid * (current.grid - 1) - count, current.moves); refresh(); return 0; } } ptrNode InsertInList(ptrNode List, struct res elem) { if (EmptyList(List) || List->result.moves >= elem.moves) return InsertFirst(List, elem); List->next = InsertInList(List->next, elem); return List; } int EmptyList(ptrNode List) { return List == NULL; } ptrNode InsertFirst(ptrNode List, struct res elem) { ptrNode FirstNode; FirstNode = malloc(sizeof(Node)); FirstNode->result = elem; FirstNode->next = List; return FirstNode; }