4inrow.c 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. #include <stdio.h>
  2. #include <furi.h>
  3. #include <gui/gui.h>
  4. #include <input/input.h>
  5. #include <notification/notification.h>
  6. #include <notification/notification_messages.h>
  7. FuriMutex* mutex;
  8. int matrix[6][7] = {0};
  9. int cursorx = 3;
  10. int cursory = 5;
  11. int player = 1;
  12. int scoreX = 0;
  13. int scoreO = 0;
  14. void init(){
  15. for (size_t i = 0; i < 6; i++)
  16. {
  17. for (size_t j = 0; j < 7; j++)
  18. {
  19. matrix[i][j] = 0;
  20. }
  21. }
  22. cursorx = 3;
  23. cursory = 5;
  24. player = 1;
  25. }
  26. const NotificationSequence end = {
  27. &message_vibro_on,
  28. &message_note_ds4,
  29. &message_delay_10,
  30. &message_sound_off,
  31. &message_delay_10,
  32. &message_note_ds4,
  33. &message_delay_10,
  34. &message_sound_off,
  35. &message_delay_10,
  36. &message_note_ds4,
  37. &message_delay_10,
  38. &message_sound_off,
  39. &message_delay_10,
  40. &message_vibro_off,
  41. NULL,
  42. };
  43. void intToStr(int num, char* str) {
  44. int i = 0, sign = 0;
  45. if (num < 0) {
  46. num = -num;
  47. sign = 1;
  48. }
  49. do {
  50. str[i++] = num % 10 + '0';
  51. num /= 10;
  52. } while (num > 0);
  53. if (sign) {
  54. str[i++] = '-';
  55. }
  56. str[i] = '\0';
  57. // Reverse the string
  58. int j, len = i;
  59. char temp;
  60. for (j = 0; j < len / 2; j++) {
  61. temp = str[j];
  62. str[j] = str[len - j - 1];
  63. str[len - j - 1] = temp;
  64. }
  65. }
  66. int next_height(int x){
  67. if (matrix[0][x] != 0){
  68. return -1;
  69. }
  70. for (size_t y = 1; y < 6; y++)
  71. {
  72. if (matrix[y][x] != 0){
  73. return y-1;
  74. }
  75. }
  76. return 5;
  77. }
  78. int wincheck(){
  79. for (size_t y = 0; y <= 2; y++)
  80. {
  81. for (size_t x = 0; x <= 6; x++)
  82. {
  83. 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]){
  84. return matrix[y][x];
  85. }
  86. }
  87. }
  88. for (size_t y = 0; y <= 5; y++)
  89. {
  90. for (size_t x = 0; x <= 3; x++)
  91. {
  92. 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]){
  93. return matrix[y][x];
  94. }
  95. }
  96. }
  97. for (size_t y = 0; y <= 2; y++)
  98. {
  99. for (size_t x = 0; x <= 3; x++)
  100. {
  101. 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]){
  102. return matrix[y][x];
  103. }
  104. }
  105. }
  106. for (size_t y = 3; y <= 5; y++)
  107. {
  108. for (size_t x = 0; x <= 3; x++)
  109. {
  110. 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]){
  111. return matrix[y][x];
  112. }
  113. }
  114. }
  115. bool tf = true;
  116. for (size_t y = 0; y < 6; y++)
  117. {
  118. for (size_t x = 0; x < 7; x++)
  119. {
  120. if (matrix[y][x] == 0){
  121. tf = false;
  122. }
  123. }
  124. }
  125. if(tf){
  126. return 0;
  127. }
  128. return -1;
  129. }
  130. static void draw_callback(Canvas* canvas, void* ctx) {
  131. UNUSED(ctx);
  132. furi_mutex_acquire(mutex, FuriWaitForever);
  133. canvas_clear(canvas);
  134. if(wincheck()!=-1){
  135. canvas_set_font(canvas, FontPrimary);
  136. if (wincheck()==0){
  137. canvas_draw_str(canvas, 37, 41, "Draw! O_o");
  138. }
  139. if (wincheck()==1){
  140. canvas_draw_str(canvas, 37, 41, "Player X win!");
  141. }
  142. if (wincheck()==2){
  143. canvas_draw_str(canvas, 37, 41, "Player O win!");
  144. }
  145. furi_mutex_release(mutex);
  146. return;
  147. }
  148. for (size_t i = 0; i < 6; i++)
  149. {
  150. for (size_t j = 0; j < 7; j++)
  151. {
  152. char el[2];
  153. switch (matrix[i][j])
  154. {
  155. case 0:
  156. strcpy(el, "_\0");
  157. break;
  158. case 1:
  159. strcpy(el, "X\0");
  160. break;
  161. case 2:
  162. strcpy(el, "O\0");
  163. break;
  164. }
  165. canvas_draw_str(canvas, j*10 + 10, i*10 + 10, el);
  166. }
  167. }
  168. canvas_draw_str(canvas, cursorx*10+8, cursory*10+10, "[ ]");
  169. if (player == 1){
  170. canvas_draw_str(canvas, 80, 10, "Turn: X");
  171. }
  172. if (player == 2){
  173. canvas_draw_str(canvas, 80, 10, "Turn: O");
  174. }
  175. char scX[1];
  176. intToStr(scoreX, scX);
  177. char scO[1];
  178. intToStr(scoreO, scO);
  179. canvas_draw_str(canvas, 80, 20, "X:");
  180. canvas_draw_str(canvas, 90, 20, scX);
  181. canvas_draw_str(canvas, 80, 30, "O:");
  182. canvas_draw_str(canvas, 90, 30, scO);
  183. furi_mutex_release(mutex);
  184. }
  185. static void input_callback(InputEvent* input_event, void* ctx) {
  186. // Проверяем, что контекст не нулевой
  187. furi_assert(ctx);
  188. FuriMessageQueue* event_queue = ctx;
  189. furi_message_queue_put(event_queue, input_event, FuriWaitForever);
  190. }
  191. int32_t four_in_row_app(void* p) {
  192. UNUSED(p);
  193. // Текущее событие типа InputEvent
  194. InputEvent event;
  195. // Очередь событий на 8 элементов размера InputEvent
  196. FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(InputEvent));
  197. // Создаем новый view port
  198. ViewPort* view_port = view_port_alloc();
  199. // Создаем callback отрисовки, без контекста
  200. view_port_draw_callback_set(view_port, draw_callback, NULL);
  201. // Создаем callback нажатий на клавиши, в качестве контекста передаем
  202. // нашу очередь сообщений, чтоб запихивать в неё эти события
  203. view_port_input_callback_set(view_port, input_callback, event_queue);
  204. mutex = furi_mutex_alloc(FuriMutexTypeNormal);
  205. // Создаем GUI приложения
  206. Gui* gui = furi_record_open(RECORD_GUI);
  207. // Подключаем view port к GUI в полноэкранном режиме
  208. gui_add_view_port(gui, view_port, GuiLayerFullscreen);
  209. NotificationApp* notification = furi_record_open(RECORD_NOTIFICATION);
  210. notification_message_block(notification, &sequence_display_backlight_enforce_on);
  211. // Бесконечный цикл обработки очереди событий
  212. while(1) {
  213. // Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
  214. // и проверяем, что у нас получилось это сделать
  215. furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
  216. furi_mutex_acquire(mutex, FuriWaitForever);
  217. // Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
  218. if(wincheck()!=-1){
  219. notification_message(notification, &end);
  220. furi_delay_ms(1000);
  221. if (wincheck() == 1){
  222. scoreX++;
  223. }
  224. if (wincheck() == 2){
  225. scoreO++;
  226. }
  227. init();
  228. }
  229. if(event.type == InputTypePress) {
  230. if(event.key == InputKeyOk) {
  231. int nh = next_height(cursorx);
  232. if (nh!=-1){
  233. matrix[nh][cursorx] = player;
  234. player = 3 - player;
  235. }
  236. }
  237. if(event.key == InputKeyUp) {
  238. //cursory--;
  239. }
  240. if(event.key == InputKeyDown) {
  241. //cursory++;
  242. }
  243. if(event.key == InputKeyLeft) {
  244. if (cursorx > 0){
  245. cursorx--;
  246. }
  247. }
  248. if(event.key == InputKeyRight) {
  249. if (cursorx < 6){
  250. cursorx++;
  251. } }
  252. if(event.key == InputKeyBack) {
  253. break;
  254. }
  255. }
  256. view_port_update(view_port);
  257. furi_mutex_release(mutex);
  258. }
  259. // Специальная очистка памяти, занимаемой очередью
  260. furi_message_queue_free(event_queue);
  261. // Чистим созданные объекты, связанные с интерфейсом
  262. gui_remove_view_port(gui, view_port);
  263. view_port_free(view_port);
  264. furi_mutex_free(mutex);
  265. furi_record_close(RECORD_GUI);
  266. return 0;
  267. }