diff --git a/src/brick_game/tetris/figures.c b/src/brick_game/tetris/figures.c index 823cbbe..8ee16a1 100644 --- a/src/brick_game/tetris/figures.c +++ b/src/brick_game/tetris/figures.c @@ -1,4 +1,64 @@ -#include "tetris.h" +#include "game_logic.h" +#include + +const int (*get_figure_shape(FigureType type, int rotation))[4] { + const int (*result)[4] = NULL; + switch (type) { + case I: + switch (rotation % 4) { + case 0: result = i_fig_up(); break; + case 1: result = i_fig_right(); break; + case 2: result = i_fig_down(); break; + case 3: result = i_fig_left(); break; + } + break; + case O: + result = o_fig(); + break; + case T: + switch (rotation % 4) { + case 0: result = t_fig_up(); break; + case 1: result = t_fig_right(); break; + case 2: result = t_fig_down(); break; + case 3: result = t_fig_left(); break; + } + break; + case L: + switch (rotation % 4) { + case 0: result = l_fig_up(); break; + case 1: result = l_fig_right(); break; + case 2: result = l_fig_down(); break; + case 3: result = l_fig_left(); break; + } + break; + case J: + switch (rotation % 4) { + case 0: result = j_fig_up(); break; + case 1: result = j_fig_right(); break; + case 2: result = j_fig_down(); break; + case 3: result = j_fig_left(); break; + } + break; + case S: + switch (rotation % 4) { + case 0: result = s_fig_up(); break; + case 1: result = s_fig_right(); break; + case 2: result = s_fig_down(); break; + case 3: result = s_fig_left(); break; + } + break; + case Z: + switch (rotation % 4) { + case 0: result = z_fig_up(); break; + case 1: result = z_fig_right(); break; + case 2: result = z_fig_down(); break; + case 3: result = z_fig_left(); break; + } + break; + default: result = NULL; + } + return result; +} // I const int (*i_fig_up())[4] { @@ -255,4 +315,14 @@ const int (*z_fig_left())[4] { {0, 0, 0, 0} }; return (const int (*)[4])shape; +} + +const int (*empty_fig())[4] { + static const int shape[4][4] = { + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + {0, 0, 0, 0} + }; + return (const int (*)[4])shape; } \ No newline at end of file diff --git a/src/brick_game/tetris/game_logic.c b/src/brick_game/tetris/game_logic.c new file mode 100644 index 0000000..6ff4473 --- /dev/null +++ b/src/brick_game/tetris/game_logic.c @@ -0,0 +1,216 @@ +#include "tetris.h" +#include "game_logic.h" +#include +#include +#include +#include + +// static bool initialized = false; + +static GameStateData* get_instance() { + static GameStateData instance = {0}; + static bool initialized_local = false; + + if (!initialized_local) { + // Инициализация экземпляра + for (int i = 0; i < FIELD_HEIGHT; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + instance.game_field[i][j] = 0; + } + } + instance.score = 0; + instance.high_score = 0; + instance.level = 1; + instance.speed = 1000; + instance.figure_active = false; + instance.game_over = false; + instance.paused = false; + initialized_local = true; + } + + return &instance; +} + +void init_game() { + GameStateData* state = get_instance(); + + // Инициализация игрового поля + for (int i = 0; i < FIELD_HEIGHT; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + state->game_field[i][j] = 0; + } + } + + srand((unsigned int)time(NULL)); + + state->current_figure.type = get_random_figure(); + state->current_figure.x = FIELD_WIDTH / 2 - 2; + state->current_figure.y = 0; + state->current_figure.rotation = 0; + + state->next_figure.type = get_random_figure(); + state->next_figure.x = 0; + state->next_figure.y = 0; + state->next_figure.rotation = 0; + + state->figure_active = true; + state->score = 0; + state->high_score = 0; // Позже можно загружать из файла + state->level = 1; + state->speed = 1000; + state->drop_time = time(NULL) * 1000; + state->game_over = false; + state->paused = false; +} + +static void clear_completed_lines() { + GameStateData* state = get_instance(); + int lines_cleared = 0; + int write_row = FIELD_HEIGHT - 1; + + // Проходим снизу вверх + for (int read_row = FIELD_HEIGHT - 1; read_row >= 0; read_row--) { + bool line_complete = true; + for (int j = 0; j < FIELD_WIDTH; j++) { + if (state->game_field[read_row][j] == 0) { + line_complete = false; + break; + } + } + + if (line_complete) { + lines_cleared++; + } else { + // Копируем неполные строки вниз + if (write_row != read_row) { + for (int j = 0; j < FIELD_WIDTH; j++) { + state->game_field[write_row][j] = state->game_field[read_row][j]; + } + } + write_row--; + } + } + + // Заполняем пустые строки наверху + for (int i = 0; i <= write_row; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + state->game_field[i][j] = 0; + } + } + + if (lines_cleared > 0) { + // Обновляем счет в соответствии с количеством очищенных линий + int points[] = {0, 100, 300, 700, 1500}; // 0, 1, 2, 3, 4 линии + int score_points = 0; + if (lines_cleared <= 4) { + score_points = points[lines_cleared]; + } else { + score_points = points[4]; // для > 4 линий + } + state->score += score_points * state->level; + + if (state->score > state->high_score) { + state->high_score = state->score; + } + + // Увеличиваем уровень каждые 600 очков, максимум 10 + int new_level = state->score / 600 + 1; + if (new_level > 10) new_level = 10; + if (new_level != state->level) { + state->level = new_level; + // Увеличиваем скорость (уменьшаем время падения) + state->speed = 1000 - (state->level - 1) * 50; + if (state->speed < 100) state->speed = 100; + } + } +} + +int get_random_figure() { + return rand() % FIGURE_COUNT; +} + +bool check_collision() { + GameStateData* state = get_instance(); + Figure* f = &state->current_figure; + const int (*shape)[4] = get_figure_shape(f->type, f->rotation); + bool collision = false; + + for (int i = 0; !collision && i < 4; i++) { + for (int j = 0; !collision && j < 4; j++) { + if (shape[i][j]) { + int x = f->x + j; + int y = f->y + i; + + if (x < 0 || x >= FIELD_WIDTH || y >= FIELD_HEIGHT + || (y >= 0 && state->game_field[y][x] != 0)) { + collision = true; + } + } + } + } + return collision; +} + +void place_figure() { + GameStateData* state = get_instance(); + Figure* f = &state->current_figure; + const int (*shape)[4] = get_figure_shape(f->type, f->rotation); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (shape[i][j]) { + int x = f->x + j; + int y = f->y + i; + if (y >= 0 && y < FIELD_HEIGHT && x >= 0 && x < FIELD_WIDTH) { + state->game_field[y][x] = 1; + } + } + } + } + + // Проверяем и удаляем заполненные строки + clear_completed_lines(); + + // Сгенерировать новую текущую фигуру из следующей + state->current_figure = state->next_figure; + state->current_figure.x = FIELD_WIDTH / 2 - 2; + state->current_figure.y = 0; + state->current_figure.rotation = 0; + + // Сгенерировать новую следующую фигуру + state->next_figure.type = get_random_figure(); + state->next_figure.rotation = 0; + + // Проверить, возможно ли размещение новой фигуры + if (check_collision()) { + state->game_over = true; + } +} + +void update_game_state() { + GameStateData* state = get_instance(); + + if (state->game_over) { + return; + } + + // Проверка времени для автоматического падения + long long current_time = time(NULL) * 1000; // в миллисекундах + if (current_time - state->drop_time >= state->speed) { + // Попробовать сдвинуть фигуру вниз + int old_y = state->current_figure.y; + state->current_figure.y++; + + if (check_collision()) { + // Если столкновение, вернуть позицию и зафиксировать фигуру + state->current_figure.y = old_y; + place_figure(); + } else { + state->drop_time = current_time; + } + } +} + +GameStateData* get_game_state() { + return get_instance(); +} \ No newline at end of file diff --git a/src/brick_game/tetris/game_logic.h b/src/brick_game/tetris/game_logic.h new file mode 100644 index 0000000..3096a44 --- /dev/null +++ b/src/brick_game/tetris/game_logic.h @@ -0,0 +1,77 @@ +#ifndef GAME_LOGIC_H +#define GAME_LOGIC_H + +#include +#include "tetris.h" // для использования GameInfo_t + +// Типы фигур +typedef enum { + I = 0, + J, + L, + O, + S, + T, + Z, + FIGURE_COUNT +} FigureType; + +// Структура фигуры +typedef struct { + int x, y; // Позиция фигуры на поле + FigureType type; // Тип фигуры + int rotation; // Поворот (0–3) +} Figure; + +typedef struct { + int game_field[FIELD_HEIGHT][FIELD_WIDTH]; + Figure current_figure; + Figure next_figure; + bool figure_active; + int score; + int high_score; + int level; + int speed; + long long drop_time; + bool game_over; + bool paused; +} GameStateData; + +// Внутренние функции +bool check_collision(void); +void init_game(void); +void update_game_state(void); +int get_random_figure(void); +const int (*get_figure_shape(FigureType type, int rotation))[4]; +GameStateData* get_game_state(void); +void place_figure(void); + +// Фигуры +const int (*i_fig_up())[4]; +const int (*i_fig_right())[4]; +const int (*i_fig_down())[4]; +const int (*i_fig_left())[4]; +const int (*o_fig())[4]; +const int (*t_fig_up())[4]; +const int (*t_fig_right())[4]; +const int (*t_fig_down())[4]; +const int (*t_fig_left())[4]; +const int (*l_fig_up())[4]; +const int (*l_fig_right())[4]; +const int (*l_fig_down())[4]; +const int (*l_fig_left())[4]; +const int (*j_fig_up())[4]; +const int (*j_fig_right())[4]; +const int (*j_fig_down())[4]; +const int (*j_fig_left())[4]; +const int (*s_fig_up())[4]; +const int (*s_fig_right())[4]; +const int (*s_fig_down())[4]; +const int (*s_fig_left())[4]; +const int (*z_fig_up())[4]; +const int (*z_fig_right())[4]; +const int (*z_fig_down())[4]; +const int (*z_fig_left())[4]; +const int (*empty_fig())[4]; + +#endif \ No newline at end of file diff --git a/src/brick_game/tetris/tetris.c b/src/brick_game/tetris/tetris.c index 8666d39..e947291 100644 --- a/src/brick_game/tetris/tetris.c +++ b/src/brick_game/tetris/tetris.c @@ -1,126 +1,191 @@ // src/brick_game/tetris/tetris.c #include "tetris.h" +#include "game_logic.h" #include #include #include +#include -static GameStateData game_state = {0}; -static bool initialized = false; +static GameInfo_t game_info = {0}; +static bool initialized = false; // Добавляем эту переменную -const int (*get_figure_shape(FigureType type, int rotation))[4] { - const int (*result)[4] = NULL; - switch (type) { - case I: - switch (rotation % 4) { - case 0: result = i_fig_up(); break; - case 1: result = i_fig_right(); break; - case 2: result = i_fig_down(); break; - case 3: result = i_fig_left(); break; - } - break; - case O: - result = o_fig(); - break; - case T: - switch (rotation % 4) { - case 0: result = t_fig_up(); break; - case 1: result = t_fig_right(); break; - case 2: result = t_fig_down(); break; - case 3: result = t_fig_left(); break; - } - break; - case L: - switch (rotation % 4) { - case 0: result = l_fig_up(); break; - case 1: result = l_fig_right(); break; - case 2: result = l_fig_down(); break; - case 3: result = l_fig_left(); break; - } - break; - case J: - switch (rotation % 4) { - case 0: result = j_fig_up(); break; - case 1: result = j_fig_right(); break; - case 2: result = j_fig_down(); break; - case 3: result = j_fig_left(); break; - } - break; - case S: - switch (rotation % 4) { - case 0: result = s_fig_up(); break; - case 1: result = s_fig_right(); break; - case 2: result = s_fig_down(); break; - case 3: result = s_fig_left(); break; - } - break; - case Z: - switch (rotation % 4) { - case 0: result = z_fig_up(); break; - case 1: result = z_fig_right(); break; - case 2: result = z_fig_down(); break; - case 3: result = z_fig_left(); break; - } - break; - default: result = NULL; +void init_game_info() { + if (game_info.field == NULL) { + game_info.field = malloc(FIELD_HEIGHT * sizeof(int*)); + for (int i = 0; i < FIELD_HEIGHT; i++) { + game_info.field[i] = malloc(FIELD_WIDTH * sizeof(int)); + } + } + + if (game_info.next == NULL) { + game_info.next = malloc(4 * sizeof(int*)); + for (int i = 0; i < 4; i++) { + game_info.next[i] = malloc(4 * sizeof(int)); + } + } + + // Инициализация полей + for (int i = 0; i < FIELD_HEIGHT; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + game_info.field[i][j] = 0; + } + } + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + game_info.next[i][j] = 0; + } } - return result; } -void user_input(UserAction_t action) { +void userInput(UserAction_t action, bool hold) { if (!initialized) { - memset(&game_state, 0, sizeof(game_state)); + init_game_info(); + init_game(); initialized = true; } + + GameStateData* state = get_game_state(); - if (Figure1 <= action && action <= Figure7) { - FigureType type = (FigureType)(action - Figure1); - game_state.current_figure.type = type; - game_state.current_figure.x = FIELD_WIDTH / 2 - 2; - game_state.current_figure.y = 0; - game_state.current_figure.rotation = 0; - game_state.figure_active = true; + if (action == Start) { + if (state->game_over) { + init_game(); // Перезапуск игры + } else if (!state->paused) { + state->paused = true; + } else { + state->paused = false; + } + return; + } + + if (action == Pause) { + state->paused = !state->paused; + return; + } + + if (action == Terminate) { + return; } - if (game_state.figure_active) { - int old_x = game_state.current_figure.x; - int old_y = game_state.current_figure.y; - int old_rot = game_state.current_figure.rotation; + if (state->game_over || state->paused) { + return; + } - if (action == Left) game_state.current_figure.x--; - if (action == Right) game_state.current_figure.x++; - if (action == Down) game_state.current_figure.y++; - if (action == Up) game_state.current_figure.y--; - if (action == Rotate) { - game_state.current_figure.rotation = (game_state.current_figure.rotation + 1) % 4; + if (state->figure_active && !state->game_over) { + int old_x = state->current_figure.x; + int old_y = state->current_figure.y; + int old_rot = state->current_figure.rotation; + + switch (action) { + case Left: + state->current_figure.x--; + break; + case Right: + state->current_figure.x++; + break; + case Down: + state->current_figure.y++; + break; + case Up: + state->current_figure.rotation = (state->current_figure.rotation + 1) % 4; + break; + case Action: // Это может быть вращение или сброс + if (hold) { + // Быстрый сброс вниз + while (!check_collision()) { + state->current_figure.y++; + } + state->current_figure.y--; // Вернуть на место перед столкновением + place_figure(); + } else { + state->current_figure.rotation = (state->current_figure.rotation + 1) % 4; + } + break; + default: + break; } if (check_collision()) { // Возвращаем старые значения - game_state.current_figure.x = old_x; - game_state.current_figure.y = old_y; - game_state.current_figure.rotation = old_rot; + state->current_figure.x = old_x; + state->current_figure.y = old_y; + state->current_figure.rotation = old_rot; + } else if (action == Down) { + // Если перемещение вниз успешно, обновляем время падения + state->drop_time = time(NULL) * 1000; } } } -GameStateData* get_game_state() { - return &game_state; -} - -bool check_collision() { - Figure* f = &game_state.current_figure; - const int (*shape)[4] = get_figure_shape(f->type, f->rotation); - - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - if (shape[i][j]) { - int x = f->x + j; - int y = f->y + i; - if (x < 0 || x >= FIELD_WIDTH || y >= FIELD_HEIGHT) { - return true; // Коллизия +GameInfo_t updateCurrentState() { + if (!initialized) { + init_game_info(); + init_game(); + initialized = true; + } + + GameStateData* state = get_game_state(); + + if (!state->game_over && !state->paused) { + long long current_time = time(NULL) * 1000; + if (current_time - state->drop_time >= state->speed) { + int old_y = state->current_figure.y; + state->current_figure.y++; + + if (check_collision()) { + state->current_figure.y = old_y; + place_figure(); + } else { + state->drop_time = current_time; + } + } + } + + // Обновляем game_info.field из state->game_field + for (int i = 0; i < FIELD_HEIGHT; i++) { + for (int j = 0; j < FIELD_WIDTH; j++) { + game_info.field[i][j] = state->game_field[i][j]; + } + } + + // Добавляем активную фигуру на поле для отображения (если не game_over) + if (state->figure_active && !state->game_over) { + Figure* f = &state->current_figure; + const int (*shape)[4] = get_figure_shape(f->type, f->rotation); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (shape[i][j]) { + int x = f->x + j; + int y = f->y + i; + if (x >= 0 && x < FIELD_WIDTH && y >= 0 && y < FIELD_HEIGHT) { + game_info.field[y][x] = 1; + } } } } } - return false; // Нет коллизии + + // Обновляем next + const int (*next_shape)[4]; + if (state->game_over) { + // При game_over показываем пустую фигуру + next_shape = empty_fig(); + } else { + next_shape = get_figure_shape(state->next_figure.type, state->next_figure.rotation); + } + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + game_info.next[i][j] = next_shape[i][j]; + } + } + + // Обновляем остальные поля + game_info.score = state->score; + game_info.high_score = state->high_score; + game_info.level = state->level; + game_info.speed = state->speed; + game_info.pause = state->paused ? 1 : 0; + + return game_info; } \ No newline at end of file diff --git a/src/brick_game/tetris/tetris.h b/src/brick_game/tetris/tetris.h index 59d611c..7a66e2f 100644 --- a/src/brick_game/tetris/tetris.h +++ b/src/brick_game/tetris/tetris.h @@ -1,41 +1,12 @@ -// src/brick_game/tetris/tetris.h #ifndef TETRIS_H #define TETRIS_H #include -#include -// Константы #define FIELD_WIDTH 10 #define FIELD_HEIGHT 20 -// Типы фигур typedef enum { - I = 0, - J, - L, - O, - S, - T, - Z, - FIGURE_COUNT -} FigureType; - -// Структура фигуры -typedef struct { - int x, y; // Позиция фигуры на поле - FigureType type; // Тип фигуры - int rotation; // Поворот (0–3) -} Figure; - -typedef struct { - int field[FIELD_HEIGHT][FIELD_WIDTH]; // Игровое поле - Figure current_figure; // Текущая фигура - bool figure_active; // Есть активная фигура? -} GameStateData; - -typedef enum { - Undefined = -1, Start, Pause, Terminate, @@ -43,53 +14,20 @@ typedef enum { Right, Up, Down, - Rotate, - Action, - Figure1, - Figure2, - Figure3, - Figure4, - Figure5, - Figure6, - Figure7 + Action } UserAction_t; -void user_input(UserAction_t action); -static bool check_collision(); -GameStateData* get_game_state(void); +typedef struct { + int **field; + int **next; + int score; + int high_score; + int level; + int speed; + int pause; +} GameInfo_t; -const int (*get_figure_shape(FigureType type, int rotation))[4]; - -const int (*i_fig_up())[4]; -const int (*i_fig_right())[4]; -const int (*i_fig_down())[4]; -const int (*i_fig_left())[4]; - -const int (*o_fig())[4]; - -const int (*t_fig_up())[4]; -const int (*t_fig_right())[4]; -const int (*t_fig_down())[4]; -const int (*t_fig_left())[4]; - -const int (*l_fig_up())[4]; -const int (*l_fig_right())[4]; -const int (*l_fig_down())[4]; -const int (*l_fig_left())[4]; - -const int (*j_fig_up())[4]; -const int (*j_fig_right())[4]; -const int (*j_fig_down())[4]; -const int (*j_fig_left())[4]; - -const int (*s_fig_up())[4]; -const int (*s_fig_right())[4]; -const int (*s_fig_down())[4]; -const int (*s_fig_left())[4]; - -const int (*z_fig_up())[4]; -const int (*z_fig_right())[4]; -const int (*z_fig_down())[4]; -const int (*z_fig_left())[4]; +void userInput(UserAction_t action, bool hold); +GameInfo_t updateCurrentState(); #endif \ No newline at end of file diff --git a/src/gui/cli/display.c b/src/gui/cli/display.c index 66ac5dd..bfc4005 100644 --- a/src/gui/cli/display.c +++ b/src/gui/cli/display.c @@ -5,31 +5,40 @@ void display_game() { clear(); - GameStateData* state = get_game_state(); + GameInfo_t game_state = updateCurrentState(); - // Очистка поля + // Отображение игрового поля for (int i = 0; i < FIELD_HEIGHT; i++) { for (int j = 0; j < FIELD_WIDTH; j++) { - mvaddch(i + 1, j * 2 + 1, '.'); - } - } - - // Если фигура активна — отображаем её - if (state->figure_active) { - Figure* f = &state->current_figure; - const int (*shape)[4] = get_figure_shape(f->type, f->rotation); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - if (shape[i][j]) { - int x = f->x + j; - int y = f->y + i; - if (x >= 0 && x < FIELD_WIDTH && y >= 0 && y < FIELD_HEIGHT) { - mvaddch(y + 1, x * 2 + 1, '$'); - } - } + if (game_state.field[i][j] != 0) { + mvaddch(i + 1, j * 2 + 1, '#'); // Заполненные блоки + } else { + mvaddch(i + 1, j * 2 + 1, '.'); // Пустые ячейки } } } + // Отображение следующей фигуры + mvaddstr(1, FIELD_WIDTH * 2 + 5, "Next figure:"); + + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + if (game_state.next[i][j]) { + mvaddch(i + 3, (FIELD_WIDTH * 2 + 5) + j * 2, '@'); + } else { + mvaddch(i + 3, (FIELD_WIDTH * 2 + 5) + j * 2, ' '); + } + } + } + + mvprintw(FIELD_HEIGHT + 2, 1, "Score: %d", game_state.score); + mvprintw(FIELD_HEIGHT + 3, 1, "High Score: %d", game_state.high_score); + mvprintw(FIELD_HEIGHT + 4, 1, "Level: %d", game_state.level); + mvprintw(FIELD_HEIGHT + 5, 1, "Speed: %d", game_state.speed); + + if (game_state.pause) { + mvprintw(FIELD_HEIGHT / 2, FIELD_WIDTH - 4, "PAUSED"); + } + refresh(); } \ No newline at end of file diff --git a/src/gui/cli/main.c b/src/gui/cli/main.c index 0a1a35c..0e315ba 100644 --- a/src/gui/cli/main.c +++ b/src/gui/cli/main.c @@ -14,35 +14,57 @@ int main() { nodelay(stdscr, TRUE); curs_set(0); - timeout(100); // Таймаут для getch() + timeout(100); int ch; - UserAction_t action = Undefined; - while (Terminate != action) { + UserAction_t current_action; + bool action_valid = false; + bool running = true; + + while (running) { ch = getch(); + action_valid = false; switch (ch) { - case 'q': action = Terminate; break; - case '1': action = Figure1; break; - case '2': action = Figure2; break; - case '3': action = Figure3; break; - case '4': action = Figure4; break; - case '5': action = Figure5; break; - case '6': action = Figure6; break; - case '7': action = Figure7; break; - case 'r': action = Rotate; break; - case ' ': action = Rotate; break; - case KEY_LEFT: action = Left; break; - case KEY_RIGHT: action = Right; break; - case KEY_DOWN: action = Down; break; - case KEY_UP: action = Up; break; - default: action = Undefined; - } - - if (action != Undefined) { - user_input(action); + case 'q': + userInput(Terminate, false); + running = false; + break; + case 'r': case ' ': + current_action = Action; + action_valid = true; + break; + case KEY_LEFT: + current_action = Left; + action_valid = true; + break; + case KEY_RIGHT: + current_action = Right; + action_valid = true; + break; + case KEY_DOWN: + current_action = Down; + action_valid = true; + break; + case KEY_UP: + current_action = Up; + action_valid = true; + break; + case 's': case 'S': + current_action = Start; + action_valid = true; + break; + case 'p': case 'P': + current_action = Pause; + action_valid = true; + break; + } + + if (action_valid) { + userInput(current_action, false); } + updateCurrentState(); display_game(); }