forked from snapshot112/minigame-menu
		
	Got the minigame menu up, running and documented. Also split up the game file
This commit is contained in:
		
							
								
								
									
										153
									
								
								grid_game_engine.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								grid_game_engine.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | |||||||
|  | /* | ||||||
|  |  * Created by snapshot112 on 10/15/25. | ||||||
|  |  * | ||||||
|  |  * A game engine that can run and display games in square grids. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #include "grid_game_engine.h" | ||||||
|  |  | ||||||
|  | #include <locale.h> | ||||||
|  | #include <ncurses.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #include "rooster.h" | ||||||
|  |  | ||||||
|  | int modulo(const int number, const int mod) { | ||||||
|  |     int result = number % mod; | ||||||
|  |     if (result < 0) { | ||||||
|  |         result += mod;    //This is not how math is supposed to work C, damnit. | ||||||
|  |     } | ||||||
|  |     return result; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void show_grid_on_offset(const rooster *gp, const int starting_x, const int starting_y) { | ||||||
|  |     const int height = rooster_hoogte(gp); | ||||||
|  |  | ||||||
|  |     for (int y = 0; y < height; y++) { | ||||||
|  |         char *rij = rooster_vraag_rij(gp, y); | ||||||
|  |         mvprintw(starting_y + y, starting_x, "%s", rij); | ||||||
|  |         free(rij); | ||||||
|  |     } | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void show_grid(const rooster *rp) { | ||||||
|  |     show_grid_on_offset(rp, 0, 0); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void update_grid(rooster *rp, char c, int x, int y) { | ||||||
|  |     if (rooster_plaats(rp, x, y, c) == 1) { | ||||||
|  |         mvaddch(y, x, c); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Shows the victory screen. | ||||||
|  |  * | ||||||
|  |  * Side Effect: | ||||||
|  |  * Clears the console and prints the victory message. | ||||||
|  |  */ | ||||||
|  | static void display_victory(void) { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(2,5, "YOU WON!!!!!"); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Shows the GAME OVER screen. | ||||||
|  |  * | ||||||
|  |  * Side Effect: | ||||||
|  |  * Clears the console and prints the GAME OVER message. | ||||||
|  |  */ | ||||||
|  | static void display_loss(void) { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(2,5, "GAME OVER"); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Shows the quit screen | ||||||
|  |  * | ||||||
|  |  * Side Effect: | ||||||
|  |  * Clears the console and prints the quit message. | ||||||
|  |  */ | ||||||
|  | static void display_quit(void) { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(2,5, "You quit the game"); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Shows the hacker man screen | ||||||
|  |  * | ||||||
|  |  * Side Effect: | ||||||
|  |  * Clears the console and prints the hacker man message. | ||||||
|  |  */ | ||||||
|  | static void display_hackerman(void) { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(2,5, "The hacker man strikes again..."); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void graceful_exit(void) { | ||||||
|  |     mvprintw(5, 5, "Press 'q' to exit."); | ||||||
|  |     while (1) { | ||||||
|  |         switch (getch()) { | ||||||
|  |             case 'q': | ||||||
|  |             case 'Q': | ||||||
|  |                 return; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void game_exit_screen(rooster *gp) { | ||||||
|  |     toestand current_state = rooster_vraag_toestand(gp); | ||||||
|  |     switch (current_state) { | ||||||
|  |         case STATE_GEWONNEN: | ||||||
|  |             display_victory(); | ||||||
|  |             break; | ||||||
|  |         case STATE_VERLOREN: | ||||||
|  |             display_loss(); | ||||||
|  |             break; | ||||||
|  |         case STATE_QUIT: | ||||||
|  |             display_quit(); | ||||||
|  |             break; | ||||||
|  |         default: | ||||||
|  |             display_hackerman(); | ||||||
|  |     } | ||||||
|  |     graceful_exit(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void init_ncurses() { | ||||||
|  |     setlocale(LC_ALL, ""); | ||||||
|  |     initscr(); | ||||||
|  |     cbreak();             // So you can cancel the game with ctrl + c. | ||||||
|  |     keypad(stdscr, TRUE); // Enable extra keys like the arrow keys. | ||||||
|  |     noecho();             // Don't write the keyboard input to the console. | ||||||
|  |     curs_set(0);          // Hides the cursor. | ||||||
|  |  | ||||||
|  |     // mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); // Don't mask any mouse events | ||||||
|  |     // printf("\033[?1003h\n"); // Makes the terminal report mouse movement events | ||||||
|  |  | ||||||
|  |     start_color(); | ||||||
|  |     init_pair(BLACK, COLOR_BLACK, COLOR_BLACK); | ||||||
|  |     init_pair(WHITE, COLOR_BLACK, COLOR_WHITE); | ||||||
|  |     init_pair(BLUE, COLOR_BLACK, COLOR_BLUE); | ||||||
|  |     init_pair(GREEN, COLOR_BLACK, COLOR_GREEN); | ||||||
|  |     init_pair(CYAN, COLOR_BLACK, COLOR_CYAN); | ||||||
|  |     init_pair(MAGENTA, COLOR_BLACK, COLOR_MAGENTA); | ||||||
|  |     init_pair(YELLOW, COLOR_BLACK, COLOR_YELLOW); | ||||||
|  |     init_pair(RED, COLOR_BLACK, COLOR_RED); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | static void cleanup_ncurses() { | ||||||
|  |     endwin(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void init_engine(void) { | ||||||
|  |     init_ncurses(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void cleanup_engine(void) { | ||||||
|  |     cleanup_ncurses(); | ||||||
|  | } | ||||||
							
								
								
									
										103
									
								
								grid_game_engine.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								grid_game_engine.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,103 @@ | |||||||
|  | /* | ||||||
|  |  * Created by snapshot112 on 10/15/25. | ||||||
|  |  * | ||||||
|  |  * A game engine that uses the can run and display games in rectangular grids. | ||||||
|  |  * The graphics are made using ncursesw. | ||||||
|  |  * | ||||||
|  |  * Please make sure to initialize the game engine before running any games. | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef MINIGAME_MENU_GRID_GAME_ENGINE_H | ||||||
|  | #define MINIGAME_MENU_GRID_GAME_ENGINE_H | ||||||
|  | #include "rooster.h" | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |     BLACK = 1, | ||||||
|  |     WHITE = 2, | ||||||
|  |     BLUE = 3, | ||||||
|  |     GREEN = 4, | ||||||
|  |     CYAN = 5, | ||||||
|  |     MAGENTA = 6, | ||||||
|  |     YELLOW = 7, | ||||||
|  |     RED = 8 | ||||||
|  | } game_colors; | ||||||
|  |  | ||||||
|  | typedef struct { | ||||||
|  |     char name[100]; | ||||||
|  |     rooster *game_map; | ||||||
|  | } game_maps; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * A proper modulo function. | ||||||
|  |  * The one provided by c: '%' doesn't work according to the mathematical definition. | ||||||
|  |  */ | ||||||
|  | int modulo(int number, int mod); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Displays the given grid with the given offset using ncurses. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * gp: A pointer to the grid. | ||||||
|  |  * | ||||||
|  |  * Side effect: | ||||||
|  |  * The console is cleared and the grid is printed. | ||||||
|  |  */ | ||||||
|  | void show_grid_on_offset(const rooster *gp, int starting_x, int starting_y); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Displays the given grid with ncurses. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * gp: A pointer to the grid. | ||||||
|  |  * | ||||||
|  |  * Side effect: | ||||||
|  |  * The console is cleared and the grid is printed. | ||||||
|  |  */ | ||||||
|  | void show_grid(const rooster *gp); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Updates a single location in the grid. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * gp: A pointer to the grid. | ||||||
|  |  * c: The character to update the location with. | ||||||
|  |  * x: The x-coordinate of the spot you want to update. | ||||||
|  |  * y: The y-coordinate of the spot you want to update. | ||||||
|  |  * | ||||||
|  |  * Side effect: | ||||||
|  |  * The update gets applied both on the grid and on the screen. | ||||||
|  |  */ | ||||||
|  | void update_grid(rooster *gp, char c, int x, int y); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Display the ending screen that matches the end state of the grid. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * gp: A pointer to the grid. | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * The end of game screen gets displayed with a graceful exit. | ||||||
|  |  */ | ||||||
|  | void game_exit_screen(rooster *gp); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Waits for you to press 'q' before exiting the game. | ||||||
|  |  * | ||||||
|  |  * Side effect: Prints "Press 'q' to exit." game to the console. | ||||||
|  |  */ | ||||||
|  | void graceful_exit(void); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Initialize ncurses. | ||||||
|  |  * | ||||||
|  |  * This enables cbreak, noecho, hides the cursor and enables the extra keys. | ||||||
|  |  * This also creates the color pairs needed for game_colors, | ||||||
|  |  */ | ||||||
|  | void init_engine(void); | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Cleanup ncurses. | ||||||
|  |  */ | ||||||
|  | void cleanup_engine(void); | ||||||
|  |  | ||||||
|  | #endif //MINIGAME_MENU_GRID_GAME_ENGINE_H | ||||||
							
								
								
									
										128
									
								
								maze_runner.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										128
									
								
								maze_runner.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,128 @@ | |||||||
|  | // | ||||||
|  | // Created by snapshot112 on 10/15/25. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "maze_runner.h" | ||||||
|  |  | ||||||
|  | #include <ncurses.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #include "grid_game_engine.h" | ||||||
|  | #include "rooster.h" | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Reads in the maze from the assets file. | ||||||
|  |  */ | ||||||
|  | static rooster *get_maze(void) { | ||||||
|  |     // TODO: echt opties aanbieden in plaats van hardcoded 1 maze. | ||||||
|  |     // Alternatief is om random een maze te genereren. dit is miss beter. | ||||||
|  |  | ||||||
|  |     // 2. Open het doolhof bestand en lees het rooster. | ||||||
|  |     FILE *fh = fopen("assets/maze.txt", "r"); | ||||||
|  |     if (fh == NULL) { | ||||||
|  |         perror("loading maze"); | ||||||
|  |         exit(EXIT_FAILURE); | ||||||
|  |     } | ||||||
|  |     rooster *rp = rooster_lees(fh); | ||||||
|  |     fclose(fh); | ||||||
|  |  | ||||||
|  |     // 3. Bepaal of het lezen van het rooster is gelukt. | ||||||
|  |     if (rp == NULL) { | ||||||
|  |         fprintf(stderr, "Kan rooster niet maken.\n"); | ||||||
|  |         exit(EXIT_FAILURE); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     return rp; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* Voert de benodigde veranderingen in het rooster door als de speler in een | ||||||
|  |  * bepaalde richting probeert te bewegen. | ||||||
|  |  * Input: | ||||||
|  |  * rp   : een pointer naar het rooster | ||||||
|  |  * dx,dy: de richting waarin de speler probeert te bewegen. De vier mogelijk- | ||||||
|  |  *        heden voor (dx,dy) zijn (-1,0), (1,0), (0,-1), (0,1) voor resp. | ||||||
|  |  *        links, rechts, omhoog en omlaag. | ||||||
|  |  * | ||||||
|  |  * Side effect: het rooster wordt aangepast op basis van de handeling van | ||||||
|  |  *              de speler. | ||||||
|  |  */ | ||||||
|  | static void maze_runner_beweeg(rooster *rp, int dx, int dy) { | ||||||
|  |     int playerx; | ||||||
|  |     int playery; | ||||||
|  |     rooster_zoek(rp, '*', &playerx, &playery); | ||||||
|  |  | ||||||
|  |     if (playerx == -1 || playery == -1) { | ||||||
|  |         printf("Player not found!"); | ||||||
|  |         exit(1); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     if (rooster_bevat(rp, playerx + dx, playery + dy) == 1) { | ||||||
|  |         char new_location = rooster_kijk(rp, playerx + dx, playery + dy); | ||||||
|  |         switch (new_location) { | ||||||
|  |             case '#': | ||||||
|  |                 break; | ||||||
|  |             case 'X': | ||||||
|  |                 update_grid(rp, ' ', playerx, playery); | ||||||
|  |                 rooster_zet_toestand(rp, STATE_VERLOREN); | ||||||
|  |                 break; | ||||||
|  |             case ' ': | ||||||
|  |                 update_grid(rp, ' ', playerx, playery); | ||||||
|  |                 update_grid(rp, '*', playerx + dx, playery + dy); | ||||||
|  |                 break; | ||||||
|  |             case '$': | ||||||
|  |                 update_grid(rp, ' ', playerx, playery); | ||||||
|  |                 rooster_zet_toestand(rp, STATE_GEWONNEN); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |         refresh(); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Speelt het spel met een gegeven rooster tot de toestand niet langer | ||||||
|  |  * AAN_HET_SPELEN is. | ||||||
|  |  */ | ||||||
|  | static void speel_maze(rooster *rp) { | ||||||
|  |     while (rooster_vraag_toestand(rp) == STATE_AAN_HET_SPELEN) | ||||||
|  |     { | ||||||
|  |         switch (getch()) { | ||||||
|  |             case KEY_UP: // fallthrough | ||||||
|  |             case 'w': | ||||||
|  |             case 'W': | ||||||
|  |                 maze_runner_beweeg(rp, 0, -1); | ||||||
|  |                 break; | ||||||
|  |             case KEY_DOWN: // fallthrough | ||||||
|  |             case 's': | ||||||
|  |             case 'S': | ||||||
|  |                 maze_runner_beweeg(rp, 0, 1); | ||||||
|  |                 break; | ||||||
|  |             case KEY_LEFT: // fallthrough | ||||||
|  |             case 'a': | ||||||
|  |             case 'A': | ||||||
|  |                 maze_runner_beweeg(rp, -1, 0); | ||||||
|  |                 break; | ||||||
|  |             case KEY_RIGHT: // fallthrough | ||||||
|  |             case 'd': | ||||||
|  |             case 'D': | ||||||
|  |                 maze_runner_beweeg(rp, 1, 0); | ||||||
|  |                 break; | ||||||
|  |             case KEY_BACKSPACE: | ||||||
|  |                 rooster_zet_toestand(rp, STATE_QUIT); | ||||||
|  |                 break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void maze_runner(void) { | ||||||
|  |     // Voorbereiding. | ||||||
|  |     rooster *rp = get_maze(); | ||||||
|  |     show_grid(rp); | ||||||
|  |     rooster_zet_toestand(rp, STATE_AAN_HET_SPELEN); | ||||||
|  |  | ||||||
|  |     // Game zelf. | ||||||
|  |     speel_maze(rp); | ||||||
|  |  | ||||||
|  |     // Exit game. | ||||||
|  |     game_exit_screen(rp); | ||||||
|  |     rooster_klaar(rp); | ||||||
|  | } | ||||||
							
								
								
									
										39
									
								
								maze_runner.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								maze_runner.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | |||||||
|  | /* | ||||||
|  |  * Naam: Jeroen Boxhoorn | ||||||
|  |  * UvAnetID: 16333969 | ||||||
|  |  * Studie: BSc Informatica | ||||||
|  |  * | ||||||
|  |  * A game of maze runner configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling maze_runner(); | ||||||
|  |  * | ||||||
|  |  * How to play the game: | ||||||
|  |  * - You are the '*' character. | ||||||
|  |  * - Use either WSAD or the arrow keys to navigate through the maze. | ||||||
|  |  * - The exit of the maze is marked with a '$'. | ||||||
|  |  * - Walls are '#'. | ||||||
|  |  * - Traps are 'X'. These kill you. | ||||||
|  |  * | ||||||
|  |  * You can quit the program at any time by pressing CTRL + C. | ||||||
|  |  * | ||||||
|  |  * Have fun playing! | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef MINIGAME_MENU_MAZE_RUNNER_H | ||||||
|  | #define MINIGAME_MENU_MAZE_RUNNER_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * A game of maze runner configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling maze_runner(); | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * Clears the console and uses it to play a game of maze runner. | ||||||
|  |  * | ||||||
|  |  * Controls: | ||||||
|  |  * use WSAD or arrow keys to move through the maze. | ||||||
|  |  * Use BACKSPACE to exit the game early. | ||||||
|  |  */ | ||||||
|  | void maze_runner(void); | ||||||
|  |  | ||||||
|  | #endif //MINIGAME_MENU_MAZE_RUNNER_H | ||||||
							
								
								
									
										16
									
								
								minesweeper.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								minesweeper.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // | ||||||
|  | // Created by snapshot112 on 10/15/25. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "minesweeper.h" | ||||||
|  |  | ||||||
|  | #include <ncurses.h> | ||||||
|  |  | ||||||
|  | #include "grid_game_engine.h" | ||||||
|  |  | ||||||
|  | void minesweeper() { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(0,0, "Minesweeper has not yet been created"); | ||||||
|  |     graceful_exit(); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
							
								
								
									
										30
									
								
								minesweeper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								minesweeper.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | |||||||
|  | /* | ||||||
|  |  * Created by snapshot112 on 10/15/25. | ||||||
|  |  * | ||||||
|  |  * A game of minesweeper runner configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling snake(); | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef MINIGAME_MENU_MINESWEEPER_H | ||||||
|  | #define MINIGAME_MENU_MINESWEEPER_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * A game of minesweeper configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling snake(); | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * Clears the console and uses it to play a game of minesweeper. | ||||||
|  |  * | ||||||
|  |  * Instructions: | ||||||
|  |  * use WSAD or arrow keys to select a grid square. | ||||||
|  |  * use SPACEBAR to open the current square. | ||||||
|  |  * use 'f' to mark/unmark a square. | ||||||
|  |  * use BACKSPACE to exit the game early. | ||||||
|  |  * | ||||||
|  |  * marked squares can't be opened. | ||||||
|  |  */ | ||||||
|  | void minesweeper(void); | ||||||
|  |  | ||||||
|  | #endif //MINIGAME_MENU_MINESWEEPER_H | ||||||
							
								
								
									
										173
									
								
								minigame_menu.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										173
									
								
								minigame_menu.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,173 @@ | |||||||
|  | // | ||||||
|  | // Created by snapshot112 on 10/15/25. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "minigame_menu.h" | ||||||
|  |  | ||||||
|  | #include <ncurses.h> | ||||||
|  | #include <stdlib.h> | ||||||
|  |  | ||||||
|  | #include "grid_game_engine.h" | ||||||
|  | #include "maze_runner.h" | ||||||
|  | #include "minesweeper.h" | ||||||
|  | #include "rooster.h" | ||||||
|  | #include "snake.h" | ||||||
|  |  | ||||||
|  | #define AMOUNT_OF_MENU_OPTIONS 4 | ||||||
|  |  | ||||||
|  | static game SELECTED_GAME = GAME_MAZE_RUNNER; | ||||||
|  | static int OFFSET_Y = 5; | ||||||
|  | static int OFFSET_X = 5; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Launch a game from the menu. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * menu: A pointer to the menu grid. | ||||||
|  |  * game: The game you want to launch. | ||||||
|  |  */ | ||||||
|  | static void launch_game(rooster *menu, const game game) { | ||||||
|  |     switch (game) { | ||||||
|  |         case GAME_MAZE_RUNNER: | ||||||
|  |             maze_runner(); | ||||||
|  |             break; | ||||||
|  |         case GAME_SNAKE: | ||||||
|  |             snake(); | ||||||
|  |             break; | ||||||
|  |         case GAME_MINESWEEPER: | ||||||
|  |             minesweeper(); | ||||||
|  |             break; | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Highlight a valid menu option. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * menu:        A pointer to the menu grid. | ||||||
|  |  * target:      The menu option to highlight. | ||||||
|  |  * offset_x:    The x offset of the menu. | ||||||
|  |  * offset_y:    The y offset of the menu. | ||||||
|  |  * | ||||||
|  |  * Side effects: | ||||||
|  |  * If a valid menu option is provided:      It will be highlighted in green. | ||||||
|  |  * If an invalid menu option is provided:   Nothing happens | ||||||
|  |  */ | ||||||
|  | static void menu_highlight(const rooster *menu) { | ||||||
|  |     switch (SELECTED_GAME) { | ||||||
|  |         case GAME_MAZE_RUNNER: | ||||||
|  |         case GAME_SNAKE: | ||||||
|  |         case GAME_MINESWEEPER: | ||||||
|  |         case GAME_QUIT: | ||||||
|  |             attron(COLOR_PAIR(GREEN)); | ||||||
|  |  | ||||||
|  |             char* row = rooster_vraag_rij(menu, SELECTED_GAME); | ||||||
|  |             mvprintw(OFFSET_Y + (int)SELECTED_GAME, OFFSET_X,  "%s", row); | ||||||
|  |             free(row); | ||||||
|  |  | ||||||
|  |             attroff(COLOR_PAIR(GREEN)); | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Show the menu screen. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * menu:                A pointer to the menu grid. | ||||||
|  |  * default_selection:   The starting selection in the menu. | ||||||
|  |  * offset_x:            The x offset of the menu. | ||||||
|  |  * offset_y:            The y offset of the menu. | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * Displays the menu | ||||||
|  |  */ | ||||||
|  | static void show_menu(const rooster *menu) { | ||||||
|  |     clear(); | ||||||
|  |     show_grid_on_offset(menu, OFFSET_X, OFFSET_Y); | ||||||
|  |     menu_highlight(menu); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Select the game on a location determined by a given offset. | ||||||
|  |  * Negative values go up and positive values go down. | ||||||
|  |  * Out of bounds selections loop around. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * selected_game:  The currently selected game. | ||||||
|  |  * offset:         The amount offset the current selection by. | ||||||
|  |  * | ||||||
|  |  * Side effect: | ||||||
|  |  * The game on the location of the given offset will be selected. | ||||||
|  |  */ | ||||||
|  | static void menu_move(const int offset) { | ||||||
|  |     SELECTED_GAME = modulo(SELECTED_GAME + offset, AMOUNT_OF_MENU_OPTIONS); | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Navigate through the menu. | ||||||
|  |  * | ||||||
|  |  * Input: | ||||||
|  |  * menu: A pointer to the menu grid. | ||||||
|  |  * | ||||||
|  |  * Output: A code that reflects the current menu state. | ||||||
|  |  * 0: Continue running. | ||||||
|  |  * 1: Exit the menu. | ||||||
|  |  * | ||||||
|  |  * | ||||||
|  |  * Side Effect: | ||||||
|  |  * Changes the SELECTED_GAME as needed and launches selected games on select. | ||||||
|  |  */ | ||||||
|  | static int navigate_menu(rooster *menu) { | ||||||
|  |     switch (getch()) { | ||||||
|  |         case KEY_UP: | ||||||
|  |         case 'w': | ||||||
|  |         case 'W': | ||||||
|  |             menu_move(-1); | ||||||
|  |             break; | ||||||
|  |         case KEY_DOWN: | ||||||
|  |         case 's': | ||||||
|  |         case 'S': | ||||||
|  |             menu_move(1); | ||||||
|  |             break; | ||||||
|  |         case KEY_ENTER: | ||||||
|  |         case 'f': | ||||||
|  |         case 'F': | ||||||
|  |             if (SELECTED_GAME == GAME_QUIT) { | ||||||
|  |                 return 1; | ||||||
|  |             } | ||||||
|  |             launch_game(menu, SELECTED_GAME); | ||||||
|  |             break; | ||||||
|  |         case KEY_BACKSPACE: | ||||||
|  |             return 1; | ||||||
|  |     } | ||||||
|  |     return 0; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * Create the menu grid. | ||||||
|  |  * | ||||||
|  |  * Output: | ||||||
|  |  * A pointer to the menu grid. | ||||||
|  |  */ | ||||||
|  | static rooster *initialize_menu(void) { | ||||||
|  |     char menu[] = "Maze Runner\n" | ||||||
|  |                   "   Snake   \n" | ||||||
|  |                   "Minesweeper\n" | ||||||
|  |                   "   Leave   \n"; | ||||||
|  |     rooster *rp = rooster_maak(menu); | ||||||
|  |     return rp; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | void minigame_menu(void) { | ||||||
|  |     rooster *menu = initialize_menu(); | ||||||
|  |  | ||||||
|  |     while (true) { | ||||||
|  |         show_menu(menu); | ||||||
|  |         if (navigate_menu(menu) == 1) { | ||||||
|  |             break; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     rooster_klaar(menu); | ||||||
|  | } | ||||||
							
								
								
									
										35
									
								
								minigame_menu.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								minigame_menu.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | |||||||
|  | /* | ||||||
|  |  * Created by snapshot112 on 10/15/25. | ||||||
|  |  * | ||||||
|  |  * A minigame menu for games configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling menu(); | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef MINIGAME_MENU_MINIGAME_MENU_H | ||||||
|  | #define MINIGAME_MENU_MINIGAME_MENU_H | ||||||
|  |  | ||||||
|  | typedef enum { | ||||||
|  |     GAME_MAZE_RUNNER = 0, | ||||||
|  |     GAME_SNAKE = 1, | ||||||
|  |     GAME_MINESWEEPER = 2, | ||||||
|  |     GAME_QUIT = 3, | ||||||
|  | } game; | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * A minigame menu for games configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling menu(); | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * Clears the console and uses it to display a minigame menu. | ||||||
|  |  * | ||||||
|  |  * Controls: | ||||||
|  |  * 'w'/'arr_up:     Next menu item. | ||||||
|  |  * 's'/'arr_down':  Previous menu item. | ||||||
|  |  * 'f':             Select current menu item. | ||||||
|  |  * 'BACKSPACE':     Exit the menu. | ||||||
|  |  */ | ||||||
|  | void minigame_menu(void); | ||||||
|  |  | ||||||
|  | #endif //MINIGAME_MENU_MINIGAME_MENU_H | ||||||
							
								
								
									
										33
									
								
								rooster.c
									
									
									
									
									
								
							
							
						
						
									
										33
									
								
								rooster.c
									
									
									
									
									
								
							| @@ -4,9 +4,6 @@ | |||||||
| #include <string.h> | #include <string.h> | ||||||
| #include <stdio.h> | #include <stdio.h> | ||||||
|  |  | ||||||
|  |  | ||||||
| // TODO: End the eternal NULL checks. |  | ||||||
|  |  | ||||||
| /* | /* | ||||||
|  * The rooster type this program is build around. |  * The rooster type this program is build around. | ||||||
|  */ |  */ | ||||||
| @@ -17,14 +14,12 @@ typedef struct rooster_data { | |||||||
|     toestand state; |     toestand state; | ||||||
| } rooster; | } rooster; | ||||||
|  |  | ||||||
|  |  | ||||||
| rooster *rooster_maak(const char* input) { | rooster *rooster_maak(const char* input) { | ||||||
|     int width = 0; |     int width = 0; | ||||||
|     int height = 0; |     int height = 0; | ||||||
|     const size_t len = strlen(input) / sizeof(char); |     const size_t len = strlen(input) / sizeof(char); | ||||||
|     if (input == NULL || len == 0) { |     if (input == NULL || len == 0) { | ||||||
|         perror("rooster_maak"); |         return NULL; | ||||||
|         exit(1); |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     for (int i = 0; input[i] != '\n'; i++) { |     for (int i = 0; input[i] != '\n'; i++) { | ||||||
| @@ -35,14 +30,18 @@ rooster *rooster_maak(const char* input) { | |||||||
|  |  | ||||||
|     for (int i = 0; i < height; i = i + width + 1) { |     for (int i = 0; i < height; i = i + width + 1) { | ||||||
|         if ((int)strcspn(&input[i], "\n") != width) { |         if ((int)strcspn(&input[i], "\n") != width) { | ||||||
|             perror("rooster_maak"); |             return NULL; | ||||||
|             exit(1); |         } | ||||||
|         }; |  | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     const int grid_size = (width + 1) * height + 1; |     const int grid_size = (width + 1) * height + 1; | ||||||
|  |  | ||||||
|     rooster *rp = malloc(sizeof(rooster)); |     rooster *rp = malloc(sizeof(rooster)); | ||||||
|  |  | ||||||
|  |     if (rp == NULL) { | ||||||
|  |         return NULL; | ||||||
|  |     } | ||||||
|  |  | ||||||
|     rp->rost = malloc(grid_size * sizeof(char)); |     rp->rost = malloc(grid_size * sizeof(char)); | ||||||
|     rp->height = height; |     rp->height = height; | ||||||
|     rp->width = width; |     rp->width = width; | ||||||
| @@ -68,10 +67,6 @@ rooster *rooster_maak(const char* input) { | |||||||
|  * 0 otherwise |  * 0 otherwise | ||||||
|  */ |  */ | ||||||
| static int get_grid_sizes(FILE *fh, rooster *rost) { | static int get_grid_sizes(FILE *fh, rooster *rost) { | ||||||
|     if (fh == NULL) { |  | ||||||
|         return 0; |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     while (getc(fh) != '\n') { |     while (getc(fh) != '\n') { | ||||||
|         if (feof(fh)) { |         if (feof(fh)) { | ||||||
|             return 0; |             return 0; | ||||||
| @@ -242,18 +237,6 @@ int rooster_plaats(rooster *rp, int x, int y, char c) { | |||||||
|     return 0; |     return 0; | ||||||
| } | } | ||||||
|  |  | ||||||
| char *rooster_als_string(const rooster *rp) { |  | ||||||
| 	if (rp != NULL && rp->rost != NULL) { |  | ||||||
| 		char *string = malloc(sizeof(rp->rost)); |  | ||||||
|         if (string == NULL) { |  | ||||||
|             return NULL; |  | ||||||
|         } |  | ||||||
|         memcpy(string, rp->rost, sizeof(rp->rost)); |  | ||||||
|         return string; |  | ||||||
| 	} |  | ||||||
|     return NULL; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| char *rooster_vraag_rij(const rooster *rp, int y) { | char *rooster_vraag_rij(const rooster *rp, int y) { | ||||||
| 	if (rp != NULL && rp->rost != NULL && rooster_bevat(rp, 0, y) == 1) { | 	if (rp != NULL && rp->rost != NULL && rooster_bevat(rp, 0, y) == 1) { | ||||||
| 	    // we're going to remove the newline so this is long enough | 	    // we're going to remove the newline so this is long enough | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								rooster.h
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								rooster.h
									
									
									
									
									
								
							| @@ -79,18 +79,6 @@ char *rooster_vraag_rij(const rooster *rp, int y); | |||||||
|  */ |  */ | ||||||
| rooster *rooster_kopieer(const rooster *rp); | rooster *rooster_kopieer(const rooster *rp); | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Haal het hele rooster op in de vorm van een string. |  | ||||||
|  * |  | ||||||
|  * Input: |  | ||||||
|  * rp: Een pointer naar het rooster. |  | ||||||
|  * |  | ||||||
|  * Output: |  | ||||||
|  * Een pointer naar een string met daarin het hele rooster, |  | ||||||
|  * regels zijn gescheiden door '/n' karakters. |  | ||||||
|  */ |  | ||||||
| char *rooster_als_string(const rooster *rp); |  | ||||||
|  |  | ||||||
| /* Vraag de huidige toestand van het spel op. | /* Vraag de huidige toestand van het spel op. | ||||||
|  |  | ||||||
|    Input: |    Input: | ||||||
|   | |||||||
							
								
								
									
										16
									
								
								snake.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								snake.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | |||||||
|  | // | ||||||
|  | // Created by snapshot112 on 10/15/25. | ||||||
|  | // | ||||||
|  |  | ||||||
|  | #include "snake.h" | ||||||
|  |  | ||||||
|  | #include <ncurses.h> | ||||||
|  |  | ||||||
|  | #include "grid_game_engine.h" | ||||||
|  |  | ||||||
|  | void snake(void) { | ||||||
|  |     clear(); | ||||||
|  |     mvprintw(0,0, "Snake has not yet been created"); | ||||||
|  |     graceful_exit(); | ||||||
|  |     refresh(); | ||||||
|  | } | ||||||
							
								
								
									
										26
									
								
								snake.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								snake.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | |||||||
|  | /* | ||||||
|  |  * Created by snapshot112 on 10/15/25. | ||||||
|  |  * | ||||||
|  |  * A game of maze runner configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling snake(); | ||||||
|  |  */ | ||||||
|  |  | ||||||
|  | #ifndef MINIGAME_MENU_SNAKE_H | ||||||
|  | #define MINIGAME_MENU_SNAKE_H | ||||||
|  |  | ||||||
|  | /* | ||||||
|  |  * A game of snake configured to run on the grid game engine. | ||||||
|  |  * | ||||||
|  |  * Please make sure to include and initialize the game engine before calling snake(); | ||||||
|  |  * | ||||||
|  |  * Side Effects: | ||||||
|  |  * Clears the console and uses it to play a game of snake. | ||||||
|  |  * | ||||||
|  |  * Controls: | ||||||
|  |  * Use WSAD or arrow keys to redirect the snake. | ||||||
|  |  * Use BACKSPACE to exit the game early. | ||||||
|  |  */ | ||||||
|  | void snake(void); | ||||||
|  |  | ||||||
|  | #endif //MINIGAME_MENU_SNAKE_H | ||||||
							
								
								
									
										452
									
								
								spel.c
									
									
									
									
									
								
							
							
						
						
									
										452
									
								
								spel.c
									
									
									
									
									
								
							| @@ -3,454 +3,22 @@ | |||||||
|  * UvAnetID: 16333969 |  * UvAnetID: 16333969 | ||||||
|  * Studie: BSc Informatica |  * Studie: BSc Informatica | ||||||
|  * |  * | ||||||
|  * This program loads in a maze from a text file and then lets you play that maze. |  * A minigame menu that lets you play games on the grid game engine. | ||||||
|  * |  * | ||||||
|  * Params when running the program: |  * Currently the following games are included: | ||||||
|  * - The path to the text file containing the maze. |  * - maze runner | ||||||
|  * |  * - snake | ||||||
|  * How to play the game: |  * - minesweeper | ||||||
|  * - You are the '*' character. |  | ||||||
|  * - Use either WSAD or the arrow keys to navigate through the maze. |  | ||||||
|  * - The exit of the maze is marked with a '$'. |  | ||||||
|  * - Walls are '#'. |  | ||||||
|  * - Traps are 'X'. These kill you. |  | ||||||
|  * |  | ||||||
|  * You can quit the program at any time by pressing CTRL + C. |  | ||||||
|  * |  | ||||||
|  * Have fun playing! |  | ||||||
|  */ |  */ | ||||||
|  |  | ||||||
| #include <assert.h> | #include "grid_game_engine.h" | ||||||
| #include <ctype.h> | #include "minigame_menu.h" | ||||||
| #include <stdio.h> |  | ||||||
| #include <stdlib.h> |  | ||||||
|  |  | ||||||
| #include <ncurses.h> |  | ||||||
| #include <wchar.h> |  | ||||||
| #include <locale.h> |  | ||||||
| #include <string.h> |  | ||||||
|  |  | ||||||
| #include "rooster.h" |  | ||||||
|  |  | ||||||
| typedef enum { |  | ||||||
|     GAME_QUIT, |  | ||||||
|     GAME_MAZE_RUNNER, |  | ||||||
|     GAME_SNAKE, |  | ||||||
|     GAME_MINESWEEPER |  | ||||||
| } game; |  | ||||||
|  |  | ||||||
| typedef enum { |  | ||||||
|     BLACK = 1, |  | ||||||
|     WHITE = 2, |  | ||||||
|     BLUE = 3, |  | ||||||
|     GREEN = 4, |  | ||||||
|     CYAN = 5, |  | ||||||
|     MAGENTA = 6, |  | ||||||
|     YELLOW = 7, |  | ||||||
|     RED = 8//, |  | ||||||
|     // LIME = 9 |  | ||||||
| } game_colors; |  | ||||||
|  |  | ||||||
| typedef struct { |  | ||||||
|     char name[100]; |  | ||||||
|     rooster *game_map; |  | ||||||
| } game_maps; |  | ||||||
|  |  | ||||||
| void toon_rooster_op_locatie(rooster *rp, int starting_x, int starting_y) { |  | ||||||
|     int height = rooster_hoogte(rp); |  | ||||||
|  |  | ||||||
|     for (int y = 0; y < height; y++) { |  | ||||||
|         char *rij = rooster_vraag_rij(rp, y); |  | ||||||
|         mvprintw(starting_y + y, starting_x, "%s", rij); |  | ||||||
|         free(rij); |  | ||||||
|     } |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Toont het gegeven rooster met ncurses. |  | ||||||
|  * |  | ||||||
|  * Input: |  | ||||||
|  * rp: een pointer naar het rooster. |  | ||||||
|  * |  | ||||||
|  * Side effect: |  | ||||||
|  * De console wordt geleegd en het rooster wordt erin gezet. |  | ||||||
|  */ |  | ||||||
| void toon_rooster(rooster *rp) { |  | ||||||
|     clear(); |  | ||||||
|  |  | ||||||
|     toon_rooster_op_locatie(rp, 0, 0); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void update_grid(rooster *rp, char c, int x, int y) { |  | ||||||
|     if (rooster_plaats(rp, x, y, c) == 1) { |  | ||||||
|         mvaddch(y, x, c); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void game_error(void) { |  | ||||||
|     endwin(); |  | ||||||
|     exit(EXIT_FAILURE); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void quit_game(rooster *menu) { |  | ||||||
|     if (menu != NULL) { |  | ||||||
|         rooster_klaar(menu); |  | ||||||
|     } |  | ||||||
|     endwin(); |  | ||||||
|     exit(EXIT_SUCCESS); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Toont het victory screen. |  | ||||||
|  * |  | ||||||
|  * Side Effect: |  | ||||||
|  * De victory message wordt op een schone console geprint. |  | ||||||
|  */ |  | ||||||
| void display_victory(void) { |  | ||||||
|     clear(); |  | ||||||
|     mvprintw(2,5, "YOU WON!!!!!"); |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Toont het loss screen. |  | ||||||
|  * |  | ||||||
|  * Side Effect: |  | ||||||
|  * De loss message wordt op een schone console geprint. |  | ||||||
|  */ |  | ||||||
| void display_loss(void) { |  | ||||||
|     clear(); |  | ||||||
|     mvprintw(2,5, "RIP, YOU DIED..."); |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Toont het quit screen. |  | ||||||
|  * |  | ||||||
|  * Side Effect: |  | ||||||
|  * De quit message wordt op een schone console geprint. |  | ||||||
|  */ |  | ||||||
| void display_quit(void) { |  | ||||||
|     clear(); |  | ||||||
|     mvprintw(2,5, "You quit the game"); |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Toont het hackerman screen. |  | ||||||
|  * |  | ||||||
|  * Side Effect: |  | ||||||
|  * De hackerman message wordt op een schone console geprint. |  | ||||||
|  */ |  | ||||||
| void display_hackerman(void) { |  | ||||||
|     clear(); |  | ||||||
|     mvprintw(2,5, "The hacker man strikes again..."); |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Bepaalt afhankelijk van de eindtoestand van het rooster |  | ||||||
|  * welk afsluitscherm er getoond moet worden en toont dan dat rooster. |  | ||||||
|  * |  | ||||||
|  * Input: Het rooster om de toestand uit af te lezen. |  | ||||||
|  * |  | ||||||
|  * Side Effects: |  | ||||||
|  * Het end-of-game scherm wordt op een blanke console geprint. |  | ||||||
|  */ |  | ||||||
| void game_exit_screen(rooster *rp) { |  | ||||||
|     toestand current_state = rooster_vraag_toestand(rp); |  | ||||||
|     switch (current_state) { |  | ||||||
|         case STATE_GEWONNEN: |  | ||||||
|             display_victory(); |  | ||||||
|             return; |  | ||||||
|         case STATE_VERLOREN: |  | ||||||
|             display_loss(); |  | ||||||
|             return; |  | ||||||
|         case GAME_QUIT: |  | ||||||
|             display_quit(); |  | ||||||
|             return; |  | ||||||
|     } |  | ||||||
|     display_hackerman(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Waits for the user to press an exit key 'q' before continuing. |  | ||||||
|  */ |  | ||||||
| void graceful_exit(void) { |  | ||||||
|     mvprintw(5, 0, "Press 'q' to exit the game."); |  | ||||||
|     while (1) { |  | ||||||
|         switch (getch()) { |  | ||||||
|             case 'q': |  | ||||||
|                 return; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void speel_snake(void) { |  | ||||||
|     mvprintw(0,0, "Snake has not yet been created"); |  | ||||||
|     graceful_exit(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void speel_minesweeper() { |  | ||||||
|     mvprintw(0,0, "Minesweeper has not yet been created"); |  | ||||||
|     graceful_exit(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* Voert de benodigde veranderingen in het rooster door als de speler in een |  | ||||||
|  * bepaalde richting probeert te bewegen. |  | ||||||
|  * Input: |  | ||||||
|  * rp   : een pointer naar het rooster |  | ||||||
|  * dx,dy: de richting waarin de speler probeert te bewegen. De vier mogelijk- |  | ||||||
|  *        heden voor (dx,dy) zijn (-1,0), (1,0), (0,-1), (0,1) voor resp. |  | ||||||
|  *        links, rechts, omhoog en omlaag. |  | ||||||
|  * |  | ||||||
|  * Side effect: het rooster wordt aangepast op basis van de handeling van |  | ||||||
|  *              de speler. |  | ||||||
|  */ |  | ||||||
| void maze_runner_beweeg(rooster *rp, int dx, int dy) { |  | ||||||
|     int playerx; |  | ||||||
|     int playery; |  | ||||||
|     rooster_zoek(rp, '*', &playerx, &playery); |  | ||||||
|  |  | ||||||
|     if (playerx == -1 || playery == -1) { |  | ||||||
|         printf("Player not found!"); |  | ||||||
|         exit(1); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     if (rooster_bevat(rp, playerx + dx, playery + dy) == 1) { |  | ||||||
|         char new_location = rooster_kijk(rp, playerx + dx, playery + dy); |  | ||||||
|         switch (new_location) { |  | ||||||
|             case '#': |  | ||||||
|                 break; |  | ||||||
|             case 'X': |  | ||||||
|                 update_grid(rp, ' ', playerx, playery); |  | ||||||
|                 rooster_zet_toestand(rp, STATE_VERLOREN); |  | ||||||
|                 break; |  | ||||||
|             case ' ': |  | ||||||
|                 update_grid(rp, ' ', playerx, playery); |  | ||||||
|                 update_grid(rp, '*', playerx + dx, playery + dy); |  | ||||||
|                 break; |  | ||||||
|             case '$': |  | ||||||
|                 update_grid(rp, ' ', playerx, playery); |  | ||||||
|                 rooster_zet_toestand(rp, STATE_GEWONNEN); |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|         refresh(); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Speel een dolhof spel. |  | ||||||
|  * |  | ||||||
|  * Input: |  | ||||||
|  * rp: Een pointer naar een rooster met een valide doolhof erin. |  | ||||||
|  * |  | ||||||
|  * Side Effects: |  | ||||||
|  * Met WSAD en arrow keys kun je door het doolhof heen bewegen. |  | ||||||
|  * |  | ||||||
|  */ |  | ||||||
| void maze_runner(rooster *rp) { |  | ||||||
|     while (rooster_vraag_toestand(rp) == STATE_AAN_HET_SPELEN) |  | ||||||
|     { |  | ||||||
|         switch (getch()) { |  | ||||||
|             case KEY_UP: // fallthrough |  | ||||||
|             case 'w': |  | ||||||
|                 maze_runner_beweeg(rp, 0, -1); |  | ||||||
|                 break; |  | ||||||
|             case KEY_DOWN: // fallthrough |  | ||||||
|             case 's': |  | ||||||
|                 maze_runner_beweeg(rp, 0, 1); |  | ||||||
|                 break; |  | ||||||
|             case KEY_LEFT: // fallthrough |  | ||||||
|             case 'a': |  | ||||||
|                 maze_runner_beweeg(rp, -1, 0); |  | ||||||
|                 break; |  | ||||||
|             case KEY_RIGHT: // fallthrough |  | ||||||
|             case 'd': |  | ||||||
|                 maze_runner_beweeg(rp, 1, 0); |  | ||||||
|                 break; |  | ||||||
|             case KEY_BACKSPACE: |  | ||||||
|                 rooster_zet_toestand(rp, STATE_QUIT); |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| rooster *choose_maze(void) { |  | ||||||
|     // TODO: echt opties aanbieden in plaats van hardcoded 1 maze. |  | ||||||
|     // Alternatief is om random een maze te genereren. dit is miss beter. |  | ||||||
|  |  | ||||||
|     // 2. Open het doolhof bestand en lees het rooster. |  | ||||||
|     FILE *fh = fopen("assets/voorbeeld_doolhof.txt", "r"); |  | ||||||
|     if (fh == NULL) { |  | ||||||
|         perror("loading maze"); |  | ||||||
|         game_error(); |  | ||||||
|     } |  | ||||||
|     rooster *rp = rooster_lees(fh); |  | ||||||
|     fclose(fh); |  | ||||||
|  |  | ||||||
|     // 3. Bepaal of het lezen van het rooster is gelukt. |  | ||||||
|     if (rp == NULL) { |  | ||||||
|         fprintf(stderr, "Kan rooster niet maken.\n"); |  | ||||||
|         game_error(); |  | ||||||
|     } |  | ||||||
|  |  | ||||||
|     return rp; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| /* |  | ||||||
|  * Speelt het spel met een gegeven rooster tot de toestand niet langer |  | ||||||
|  * AAN_HET_SPELEN is. |  | ||||||
|  */ |  | ||||||
| void speel_maze(void) { |  | ||||||
|     // Voorbereiding. |  | ||||||
|     rooster *rp = choose_maze(); |  | ||||||
|     toon_rooster(rp); |  | ||||||
|     rooster_zet_toestand(rp, STATE_AAN_HET_SPELEN); |  | ||||||
|  |  | ||||||
|     // Game zelf. |  | ||||||
|     maze_runner(rp); |  | ||||||
|  |  | ||||||
|     // Exit game. |  | ||||||
|     game_exit_screen(rp); |  | ||||||
|     rooster_klaar(rp); |  | ||||||
|     graceful_exit(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void launch_game(rooster *menu, const game game) { |  | ||||||
|     switch (game) { |  | ||||||
|         case GAME_MAZE_RUNNER: |  | ||||||
|             speel_maze(); |  | ||||||
|             return; |  | ||||||
|         case GAME_SNAKE: |  | ||||||
|             speel_snake(); |  | ||||||
|             return; |  | ||||||
|         case GAME_MINESWEEPER: |  | ||||||
|             speel_minesweeper(); |  | ||||||
|             return; |  | ||||||
|         case GAME_QUIT: |  | ||||||
|             quit_game(menu); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void menu_highlight(rooster *rp, const game target, const int offset_x, const int offset_y) { |  | ||||||
|     switch (target) { |  | ||||||
|         case GAME_MAZE_RUNNER: // Fallthrough |  | ||||||
|         case GAME_SNAKE:       // Fallthrough |  | ||||||
|         case GAME_MINESWEEPER: // Fallthrough |  | ||||||
|         case GAME_QUIT:        // Fallthrough |  | ||||||
|             // TODO: Properly highlight this shit. |  | ||||||
|             attron(COLOR_PAIR(HIGHLIGHT_COLOR)); |  | ||||||
|             mvaddch(y0 + y, x0 + x * 2, ' '); |  | ||||||
|             addch(' '); |  | ||||||
|             attroff(COLOR_PAIR(kleur)); |  | ||||||
|             char* row = rooster_vraag_rij(rp, target); |  | ||||||
|             mvprintw(offset_y + (int)target, offset_x, row); |  | ||||||
|             free(row); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| game menu_try_move(const game selected_game, const int offset) { |  | ||||||
|     switch (selected_game + offset) { |  | ||||||
|         case GAME_MAZE_RUNNER: |  | ||||||
|             return GAME_MAZE_RUNNER; |  | ||||||
|         case GAME_SNAKE: |  | ||||||
|             return GAME_SNAKE; |  | ||||||
|         case GAME_MINESWEEPER: |  | ||||||
|             return GAME_MINESWEEPER; |  | ||||||
|         case GAME_QUIT: |  | ||||||
|             return GAME_QUIT; |  | ||||||
|     } |  | ||||||
|     return selected_game; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void navigate_menu(rooster *menu, const game default_game, const int offset_x, const int offset_y) { |  | ||||||
|     game selected_game = default_game; |  | ||||||
|     while (true) { |  | ||||||
|         switch (getch()) { |  | ||||||
|             case KEY_UP: // fallthrough |  | ||||||
|             case 'w': |  | ||||||
|                 selected_game = menu_try_move(selected_game, -1); |  | ||||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); |  | ||||||
|                 break; |  | ||||||
|             case KEY_DOWN: // fallthrough |  | ||||||
|             case 's': |  | ||||||
|                 selected_game = menu_try_move(selected_game, 1); |  | ||||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); |  | ||||||
|                 break; |  | ||||||
|             case KEY_ENTER: |  | ||||||
|             case 'p': |  | ||||||
|                 // select current game somehow |  | ||||||
|                 launch_game(menu, GAME_QUIT); |  | ||||||
|                 menu_highlight(menu, selected_game, offset_x, offset_y); |  | ||||||
|                 break; |  | ||||||
|             case KEY_BACKSPACE: |  | ||||||
|                 launch_game(menu, GAME_QUIT); |  | ||||||
|                 break; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| rooster *laad_menu(void) { |  | ||||||
|     char menu[] = "Maze Runner\n" |  | ||||||
|                   "   Snake   \n" |  | ||||||
|                   "Minesweeper\n" |  | ||||||
|                   "   Leave   \n"; |  | ||||||
|     rooster *rp = rooster_maak(menu); |  | ||||||
|     return rp; |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void toon_menu(rooster *menu, const game default_game, const int offset_x, const int offset_y) { |  | ||||||
|     toon_rooster_op_locatie(menu, offset_x, offset_y); |  | ||||||
|     menu_highlight(menu, default_game, offset_x, offset_y); |  | ||||||
|     refresh(); |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void menu(void) { |  | ||||||
|     rooster *menu = laad_menu(); |  | ||||||
|     const game default_game = GAME_MAZE_RUNNER; |  | ||||||
|  |  | ||||||
|     while (true) { |  | ||||||
|         clear(); |  | ||||||
|         const int offset_x = 5; |  | ||||||
|         const int offset_y = 5; |  | ||||||
|         toon_menu(menu, default_game, offset_x, offset_y); |  | ||||||
|         navigate_menu(menu, default_game, offset_x, offset_y); |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| void startup_sequence(void) { |  | ||||||
|     // TODO: Nice entry screen |  | ||||||
| } |  | ||||||
|  |  | ||||||
| int main(void) { | int main(void) { | ||||||
|     // 4. Initialiseer ncurses |     init_engine(); | ||||||
|     setlocale(LC_ALL, ""); |  | ||||||
|     initscr(); |  | ||||||
|     cbreak();             // zodat je kunt onderbreken met Ctrl+C |  | ||||||
|     keypad(stdscr, TRUE); // luister ook naar extra toetsen zoals pijltjes |  | ||||||
|     noecho();             // druk niet de letters af die je intypt |  | ||||||
|     curs_set(0);          // hides the cursor// Don't mask any mouse events |  | ||||||
|  |  | ||||||
|     // mousemask(ALL_MOUSE_EVENTS | REPORT_MOUSE_POSITION, NULL); // Don't mask any mouse events |  | ||||||
|     // printf("\033[?1003h\n"); // Makes the terminal report mouse movement events |  | ||||||
|  |  | ||||||
|     start_color(); |  | ||||||
|     init_pair(BLACK, COLOR_BLACK, COLOR_BLACK); |  | ||||||
|     init_pair(WHITE, COLOR_BLACK, COLOR_WHITE); |  | ||||||
|     init_pair(BLUE, COLOR_BLACK, COLOR_BLUE); |  | ||||||
|     init_pair(GREEN, COLOR_BLACK, COLOR_GREEN); |  | ||||||
|     init_pair(CYAN, COLOR_BLACK, COLOR_CYAN); |  | ||||||
|     init_pair(MAGENTA, COLOR_BLACK, COLOR_MAGENTA); |  | ||||||
|     init_pair(YELLOW, COLOR_BLACK, COLOR_YELLOW); |  | ||||||
|     init_pair(RED, COLOR_BLACK, COLOR_RED); |  | ||||||
|     // init_pair(LIME, COLOR_BLACK, COLOR_LIME); |  | ||||||
|  |  | ||||||
|  |  | ||||||
|     // 5. Speel het spel. |     // 5. Speel het spel. | ||||||
|     startup_sequence(); |     minigame_menu(); | ||||||
|     menu(); |  | ||||||
|  |  | ||||||
|     // 6. Sluit af. |     cleanup_engine(); | ||||||
|     quit_game(NULL); |  | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user