| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325 |
- #include <stdio.h>
- #include <furi.h>
- #include <gui/gui.h>
- #include <input/input.h>
- #include <notification/notification.h>
- #include <notification/notification_messages.h>
- #include <dolphin/dolphin.h>
- static int matrix[6][7] = {0};
- static int cursorx = 3;
- static int cursory = 5;
- static int player = 1;
- static int scoreX = 0;
- static int scoreO = 0;
- typedef struct {
- FuriMutex* mutex;
- } FourInRowState;
- void init() {
- for(size_t i = 0; i < 6; i++) {
- for(size_t j = 0; j < 7; j++) {
- matrix[i][j] = 0;
- }
- }
- cursorx = 3;
- cursory = 5;
- player = 1;
- }
- const NotificationSequence end = {
- &message_vibro_on,
- &message_note_ds4,
- &message_delay_10,
- &message_sound_off,
- &message_delay_10,
- &message_note_ds4,
- &message_delay_10,
- &message_sound_off,
- &message_delay_10,
- &message_note_ds4,
- &message_delay_10,
- &message_sound_off,
- &message_delay_10,
- &message_vibro_off,
- NULL,
- };
- void intToStr(int num, char* str) {
- int i = 0, sign = 0;
- if(num < 0) {
- num = -num;
- sign = 1;
- }
- do {
- str[i++] = num % 10 + '0';
- num /= 10;
- } while(num > 0);
- if(sign) {
- str[i++] = '-';
- }
- str[i] = '\0';
- // Reverse the string
- int j, len = i;
- char temp;
- for(j = 0; j < len / 2; j++) {
- temp = str[j];
- str[j] = str[len - j - 1];
- str[len - j - 1] = temp;
- }
- }
- int next_height(int x) {
- if(matrix[0][x] != 0) {
- return -1;
- }
- for(size_t y = 1; y < 6; y++) {
- if(matrix[y][x] != 0) {
- return y - 1;
- }
- }
- return 5;
- }
- int wincheck() {
- for(size_t y = 0; y <= 2; y++) {
- for(size_t x = 0; x <= 6; x++) {
- if(matrix[y][x] != 0 && matrix[y][x] == matrix[y + 1][x] &&
- matrix[y][x] == matrix[y + 2][x] && matrix[y][x] == matrix[y + 3][x]) {
- return matrix[y][x];
- }
- }
- }
- for(size_t y = 0; y <= 5; y++) {
- for(size_t x = 0; x <= 3; x++) {
- if(matrix[y][x] != 0 && matrix[y][x] == matrix[y][x + 1] &&
- matrix[y][x] == matrix[y][x + 2] && matrix[y][x] == matrix[y][x + 3]) {
- return matrix[y][x];
- }
- }
- }
- for(size_t y = 0; y <= 2; y++) {
- for(size_t x = 0; x <= 3; x++) {
- if(matrix[y][x] != 0 && matrix[y][x] == matrix[y + 1][x + 1] &&
- matrix[y][x] == matrix[y + 2][x + 2] && matrix[y][x] == matrix[y + 3][x + 3]) {
- return matrix[y][x];
- }
- }
- }
- for(size_t y = 3; y <= 5; y++) {
- for(size_t x = 0; x <= 3; x++) {
- if(matrix[y][x] != 0 && matrix[y][x] == matrix[y - 1][x + 1] &&
- matrix[y][x] == matrix[y - 2][x + 2] && matrix[y][x] == matrix[y - 3][x + 3]) {
- return matrix[y][x];
- }
- }
- }
- bool tf = true;
- for(size_t y = 0; y < 6; y++) {
- for(size_t x = 0; x < 7; x++) {
- if(matrix[y][x] == 0) {
- tf = false;
- }
- }
- }
- if(tf) {
- return 0;
- }
- return -1;
- }
- static void draw_callback(Canvas* canvas, void* ctx) {
- furi_assert(ctx);
- const FourInRowState* fourinrow_state = ctx;
- furi_mutex_acquire(fourinrow_state->mutex, FuriWaitForever);
- canvas_clear(canvas);
- if(wincheck() != -1) {
- canvas_set_font(canvas, FontPrimary);
- if(wincheck() == 0) {
- canvas_draw_str(canvas, 30, 35, "Draw! O_o");
- }
- if(wincheck() == 1) {
- canvas_draw_str(canvas, 30, 35, "Player X win!");
- }
- if(wincheck() == 2) {
- canvas_draw_str(canvas, 30, 35, "Player O win!");
- }
- furi_mutex_release(fourinrow_state->mutex);
- return;
- }
- for(size_t i = 0; i < 6; i++) {
- for(size_t j = 0; j < 7; j++) {
- char el[2];
- switch(matrix[i][j]) {
- case 0:
- strcpy(el, "_\0");
- break;
- case 1:
- strcpy(el, "X\0");
- break;
- case 2:
- strcpy(el, "O\0");
- break;
- }
- canvas_draw_str(canvas, j * 10 + 10, i * 10 + 10, el);
- }
- }
- canvas_draw_str(canvas, cursorx * 10 + 8, cursory * 10 + 10, "[ ]");
- if(player == 1) {
- canvas_draw_str(canvas, 80, 10, "Turn: X");
- }
- if(player == 2) {
- canvas_draw_str(canvas, 80, 10, "Turn: O");
- }
- char scX[1];
- intToStr(scoreX, scX);
- char scO[1];
- intToStr(scoreO, scO);
- canvas_draw_str(canvas, 80, 20, "X:");
- canvas_draw_str(canvas, 90, 20, scX);
- canvas_draw_str(canvas, 80, 30, "O:");
- canvas_draw_str(canvas, 90, 30, scO);
- furi_mutex_release(fourinrow_state->mutex);
- }
- static void input_callback(InputEvent* input_event, void* ctx) {
- // Проверяем, что контекст не нулевой
- furi_assert(ctx);
- FuriMessageQueue* event_queue = ctx;
- furi_message_queue_put(event_queue, input_event, FuriWaitForever);
- }
- int32_t four_in_row_app(void* p) {
- UNUSED(p);
- // Текущее событие типа InputEvent
- InputEvent event;
- // Очередь событий на 8 элементов размера InputEvent
- FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
- FourInRowState* fourinrow_state = malloc(sizeof(FourInRowState));
- fourinrow_state->mutex = furi_mutex_alloc(FuriMutexTypeNormal); // Alloc Mutex
- if(!fourinrow_state->mutex) {
- FURI_LOG_E("4inRow", "cannot create mutex\r\n");
- furi_message_queue_free(event_queue);
- free(fourinrow_state);
- return 255;
- }
- dolphin_deed(DolphinDeedPluginGameStart);
- // Создаем новый view port
- ViewPort* view_port = view_port_alloc();
- // Создаем callback отрисовки, без контекста
- view_port_draw_callback_set(view_port, draw_callback, fourinrow_state);
- // Создаем callback нажатий на клавиши, в качестве контекста передаем
- // нашу очередь сообщений, чтоб запихивать в неё эти события
- view_port_input_callback_set(view_port, input_callback, event_queue);
- // Создаем GUI приложения
- Gui* gui = furi_record_open(RECORD_GUI);
- // Подключаем view port к GUI в полноэкранном режиме
- gui_add_view_port(gui, view_port, GuiLayerFullscreen);
- NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
- notification_message_block(notification, &sequence_display_backlight_enforce_on);
- // Бесконечный цикл обработки очереди событий
- while(1) {
- // Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
- // и проверяем, что у нас получилось это сделать
- if(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk) {
- if((event.type == InputTypePress) && (event.key == InputKeyBack)) {
- break;
- }
- furi_mutex_acquire(fourinrow_state->mutex, FuriWaitForever);
- if(wincheck() != -1) {
- notification_message(notification, &end);
- furi_delay_ms(1000);
- if(wincheck() == 1) {
- scoreX++;
- }
- if(wincheck() == 2) {
- scoreO++;
- }
- init();
- furi_mutex_release(fourinrow_state->mutex);
- continue;
- }
- if(event.type == InputTypePress) {
- if(event.key == InputKeyOk) {
- int nh = next_height(cursorx);
- if(nh != -1) {
- matrix[nh][cursorx] = player;
- player = 3 - player;
- }
- }
- if(event.key == InputKeyUp) {
- //cursory--;
- }
- if(event.key == InputKeyDown) {
- //cursory++;
- }
- if(event.key == InputKeyLeft) {
- if(cursorx > 0) {
- cursorx--;
- }
- }
- if(event.key == InputKeyRight) {
- if(cursorx < 6) {
- cursorx++;
- }
- }
- }
- furi_mutex_release(fourinrow_state->mutex);
- }
- view_port_update(view_port);
- }
- // Чистим созданные объекты, связанные с интерфейсом
- view_port_enabled_set(view_port, false);
- gui_remove_view_port(gui, view_port);
- view_port_free(view_port);
- furi_message_queue_free(event_queue);
- furi_record_close(RECORD_GUI);
- // Clear notification
- notification_message_block(notification, &sequence_display_backlight_enforce_auto);
- furi_record_close(RECORD_NOTIFICATION);
- furi_mutex_free(fourinrow_state->mutex);
- free(fourinrow_state);
- return 0;
- }
|