|
@@ -4,20 +4,22 @@
|
|
|
#include <input/input.h>
|
|
#include <input/input.h>
|
|
|
#include <notification/notification.h>
|
|
#include <notification/notification.h>
|
|
|
#include <notification/notification_messages.h>
|
|
#include <notification/notification_messages.h>
|
|
|
-
|
|
|
|
|
-FuriMutex* mutex;
|
|
|
|
|
-int matrix[6][7] = {0};
|
|
|
|
|
-int cursorx = 3;
|
|
|
|
|
-int cursory = 5;
|
|
|
|
|
-int player = 1;
|
|
|
|
|
-int scoreX = 0;
|
|
|
|
|
-int scoreO = 0;
|
|
|
|
|
-
|
|
|
|
|
-void init(){
|
|
|
|
|
- for (size_t i = 0; i < 6; i++)
|
|
|
|
|
- {
|
|
|
|
|
- for (size_t j = 0; j < 7; j++)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+#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;
|
|
matrix[i][j] = 0;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -51,7 +53,7 @@ const NotificationSequence end = {
|
|
|
void intToStr(int num, char* str) {
|
|
void intToStr(int num, char* str) {
|
|
|
int i = 0, sign = 0;
|
|
int i = 0, sign = 0;
|
|
|
|
|
|
|
|
- if (num < 0) {
|
|
|
|
|
|
|
+ if(num < 0) {
|
|
|
num = -num;
|
|
num = -num;
|
|
|
sign = 1;
|
|
sign = 1;
|
|
|
}
|
|
}
|
|
@@ -59,9 +61,9 @@ void intToStr(int num, char* str) {
|
|
|
do {
|
|
do {
|
|
|
str[i++] = num % 10 + '0';
|
|
str[i++] = num % 10 + '0';
|
|
|
num /= 10;
|
|
num /= 10;
|
|
|
- } while (num > 0);
|
|
|
|
|
|
|
+ } while(num > 0);
|
|
|
|
|
|
|
|
- if (sign) {
|
|
|
|
|
|
|
+ if(sign) {
|
|
|
str[i++] = '-';
|
|
str[i++] = '-';
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -70,122 +72,110 @@ void intToStr(int num, char* str) {
|
|
|
// Reverse the string
|
|
// Reverse the string
|
|
|
int j, len = i;
|
|
int j, len = i;
|
|
|
char temp;
|
|
char temp;
|
|
|
- for (j = 0; j < len / 2; j++) {
|
|
|
|
|
|
|
+ for(j = 0; j < len / 2; j++) {
|
|
|
temp = str[j];
|
|
temp = str[j];
|
|
|
str[j] = str[len - j - 1];
|
|
str[j] = str[len - j - 1];
|
|
|
str[len - j - 1] = temp;
|
|
str[len - j - 1] = temp;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-int next_height(int x){
|
|
|
|
|
- if (matrix[0][x] != 0){
|
|
|
|
|
|
|
+int next_height(int x) {
|
|
|
|
|
+ if(matrix[0][x] != 0) {
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
- for (size_t y = 1; y < 6; y++)
|
|
|
|
|
- {
|
|
|
|
|
- if (matrix[y][x] != 0){
|
|
|
|
|
- return y-1;
|
|
|
|
|
|
|
+ for(size_t y = 1; y < 6; y++) {
|
|
|
|
|
+ if(matrix[y][x] != 0) {
|
|
|
|
|
+ return y - 1;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
return 5;
|
|
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]){
|
|
|
|
|
|
|
+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];
|
|
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]){
|
|
|
|
|
|
|
+ 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];
|
|
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]){
|
|
|
|
|
|
|
+ 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];
|
|
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]){
|
|
|
|
|
|
|
+ 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];
|
|
return matrix[y][x];
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
bool tf = true;
|
|
bool tf = true;
|
|
|
- for (size_t y = 0; y < 6; y++)
|
|
|
|
|
- {
|
|
|
|
|
- for (size_t x = 0; x < 7; x++)
|
|
|
|
|
- {
|
|
|
|
|
- if (matrix[y][x] == 0){
|
|
|
|
|
|
|
+ for(size_t y = 0; y < 6; y++) {
|
|
|
|
|
+ for(size_t x = 0; x < 7; x++) {
|
|
|
|
|
+ if(matrix[y][x] == 0) {
|
|
|
tf = false;
|
|
tf = false;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- if(tf){
|
|
|
|
|
|
|
+ if(tf) {
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return -1;
|
|
return -1;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
static void draw_callback(Canvas* canvas, void* ctx) {
|
|
static void draw_callback(Canvas* canvas, void* ctx) {
|
|
|
- UNUSED(ctx);
|
|
|
|
|
|
|
+ furi_assert(ctx);
|
|
|
|
|
+ const FourInRowState* fourinrow_state = ctx;
|
|
|
|
|
|
|
|
- furi_mutex_acquire(mutex, FuriWaitForever);
|
|
|
|
|
|
|
+ furi_mutex_acquire(fourinrow_state->mutex, FuriWaitForever);
|
|
|
canvas_clear(canvas);
|
|
canvas_clear(canvas);
|
|
|
|
|
|
|
|
- if(wincheck()!=-1){
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if(wincheck() != -1) {
|
|
|
canvas_set_font(canvas, FontPrimary);
|
|
canvas_set_font(canvas, FontPrimary);
|
|
|
|
|
|
|
|
- if (wincheck()==0){
|
|
|
|
|
|
|
+ if(wincheck() == 0) {
|
|
|
canvas_draw_str(canvas, 30, 35, "Draw! O_o");
|
|
canvas_draw_str(canvas, 30, 35, "Draw! O_o");
|
|
|
}
|
|
}
|
|
|
- if (wincheck()==1){
|
|
|
|
|
|
|
+ if(wincheck() == 1) {
|
|
|
canvas_draw_str(canvas, 30, 35, "Player X win!");
|
|
canvas_draw_str(canvas, 30, 35, "Player X win!");
|
|
|
- }
|
|
|
|
|
- if (wincheck()==2){
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ if(wincheck() == 2) {
|
|
|
canvas_draw_str(canvas, 30, 35, "Player O win!");
|
|
canvas_draw_str(canvas, 30, 35, "Player O win!");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- furi_mutex_release(mutex);
|
|
|
|
|
|
|
+ furi_mutex_release(fourinrow_state->mutex);
|
|
|
|
|
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- for (size_t i = 0; i < 6; i++)
|
|
|
|
|
- {
|
|
|
|
|
- for (size_t j = 0; j < 7; j++)
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ for(size_t i = 0; i < 6; i++) {
|
|
|
|
|
+ for(size_t j = 0; j < 7; j++) {
|
|
|
char el[2];
|
|
char el[2];
|
|
|
- switch (matrix[i][j])
|
|
|
|
|
- {
|
|
|
|
|
|
|
+ switch(matrix[i][j]) {
|
|
|
case 0:
|
|
case 0:
|
|
|
strcpy(el, "_\0");
|
|
strcpy(el, "_\0");
|
|
|
break;
|
|
break;
|
|
|
-
|
|
|
|
|
|
|
+
|
|
|
case 1:
|
|
case 1:
|
|
|
strcpy(el, "X\0");
|
|
strcpy(el, "X\0");
|
|
|
break;
|
|
break;
|
|
@@ -193,18 +183,16 @@ static void draw_callback(Canvas* canvas, void* ctx) {
|
|
|
case 2:
|
|
case 2:
|
|
|
strcpy(el, "O\0");
|
|
strcpy(el, "O\0");
|
|
|
break;
|
|
break;
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
- canvas_draw_str(canvas, j*10 + 10, i*10 + 10, el);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ canvas_draw_str(canvas, j * 10 + 10, i * 10 + 10, el);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
- canvas_draw_str(canvas, cursorx*10+8, cursory*10+10, "[ ]");
|
|
|
|
|
|
|
+ canvas_draw_str(canvas, cursorx * 10 + 8, cursory * 10 + 10, "[ ]");
|
|
|
|
|
|
|
|
- if (player == 1){
|
|
|
|
|
|
|
+ if(player == 1) {
|
|
|
canvas_draw_str(canvas, 80, 10, "Turn: X");
|
|
canvas_draw_str(canvas, 80, 10, "Turn: X");
|
|
|
}
|
|
}
|
|
|
- if (player == 2){
|
|
|
|
|
|
|
+ if(player == 2) {
|
|
|
canvas_draw_str(canvas, 80, 10, "Turn: O");
|
|
canvas_draw_str(canvas, 80, 10, "Turn: O");
|
|
|
}
|
|
}
|
|
|
char scX[1];
|
|
char scX[1];
|
|
@@ -212,17 +200,15 @@ static void draw_callback(Canvas* canvas, void* ctx) {
|
|
|
char scO[1];
|
|
char scO[1];
|
|
|
intToStr(scoreO, scO);
|
|
intToStr(scoreO, scO);
|
|
|
|
|
|
|
|
-
|
|
|
|
|
canvas_draw_str(canvas, 80, 20, "X:");
|
|
canvas_draw_str(canvas, 80, 20, "X:");
|
|
|
canvas_draw_str(canvas, 90, 20, scX);
|
|
canvas_draw_str(canvas, 90, 20, scX);
|
|
|
|
|
|
|
|
canvas_draw_str(canvas, 80, 30, "O:");
|
|
canvas_draw_str(canvas, 80, 30, "O:");
|
|
|
canvas_draw_str(canvas, 90, 30, scO);
|
|
canvas_draw_str(canvas, 90, 30, scO);
|
|
|
|
|
|
|
|
- furi_mutex_release(mutex);
|
|
|
|
|
|
|
+ furi_mutex_release(fourinrow_state->mutex);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
static void input_callback(InputEvent* input_event, void* ctx) {
|
|
static void input_callback(InputEvent* input_event, void* ctx) {
|
|
|
// Проверяем, что контекст не нулевой
|
|
// Проверяем, что контекст не нулевой
|
|
|
furi_assert(ctx);
|
|
furi_assert(ctx);
|
|
@@ -239,16 +225,26 @@ int32_t four_in_row_app(void* p) {
|
|
|
// Очередь событий на 8 элементов размера InputEvent
|
|
// Очередь событий на 8 элементов размера InputEvent
|
|
|
FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(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
|
|
// Создаем новый view port
|
|
|
ViewPort* view_port = view_port_alloc();
|
|
ViewPort* view_port = view_port_alloc();
|
|
|
// Создаем callback отрисовки, без контекста
|
|
// Создаем callback отрисовки, без контекста
|
|
|
- view_port_draw_callback_set(view_port, draw_callback, NULL);
|
|
|
|
|
|
|
+ view_port_draw_callback_set(view_port, draw_callback, fourinrow_state);
|
|
|
// Создаем callback нажатий на клавиши, в качестве контекста передаем
|
|
// Создаем callback нажатий на клавиши, в качестве контекста передаем
|
|
|
// нашу очередь сообщений, чтоб запихивать в неё эти события
|
|
// нашу очередь сообщений, чтоб запихивать в неё эти события
|
|
|
view_port_input_callback_set(view_port, input_callback, event_queue);
|
|
view_port_input_callback_set(view_port, input_callback, event_queue);
|
|
|
|
|
|
|
|
- mutex = furi_mutex_alloc(FuriMutexTypeNormal);
|
|
|
|
|
-
|
|
|
|
|
// Создаем GUI приложения
|
|
// Создаем GUI приложения
|
|
|
Gui* gui = furi_record_open(RECORD_GUI);
|
|
Gui* gui = furi_record_open(RECORD_GUI);
|
|
|
// Подключаем view port к GUI в полноэкранном режиме
|
|
// Подключаем view port к GUI в полноэкранном режиме
|
|
@@ -258,34 +254,31 @@ int32_t four_in_row_app(void* p) {
|
|
|
|
|
|
|
|
// Бесконечный цикл обработки очереди событий
|
|
// Бесконечный цикл обработки очереди событий
|
|
|
while(1) {
|
|
while(1) {
|
|
|
-
|
|
|
|
|
// Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
|
|
// Выбираем событие из очереди в переменную event (ждем бесконечно долго, если очередь пуста)
|
|
|
// и проверяем, что у нас получилось это сделать
|
|
// и проверяем, что у нас получилось это сделать
|
|
|
furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
|
|
furi_check(furi_message_queue_get(event_queue, &event, FuriWaitForever) == FuriStatusOk);
|
|
|
- furi_mutex_acquire(mutex, FuriWaitForever);
|
|
|
|
|
|
|
+ furi_mutex_acquire(fourinrow_state->mutex, FuriWaitForever);
|
|
|
// Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
|
|
// Если нажата кнопка "назад", то выходим из цикла, а следовательно и из приложения
|
|
|
- if(wincheck()!=-1){
|
|
|
|
|
-
|
|
|
|
|
|
|
+ if(wincheck() != -1) {
|
|
|
notification_message(notification, &end);
|
|
notification_message(notification, &end);
|
|
|
furi_delay_ms(1000);
|
|
furi_delay_ms(1000);
|
|
|
- if (wincheck() == 1){
|
|
|
|
|
|
|
+ if(wincheck() == 1) {
|
|
|
scoreX++;
|
|
scoreX++;
|
|
|
}
|
|
}
|
|
|
- if (wincheck() == 2){
|
|
|
|
|
|
|
+ if(wincheck() == 2) {
|
|
|
scoreO++;
|
|
scoreO++;
|
|
|
}
|
|
}
|
|
|
init();
|
|
init();
|
|
|
-
|
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
if(event.type == InputTypePress) {
|
|
if(event.type == InputTypePress) {
|
|
|
if(event.key == InputKeyOk) {
|
|
if(event.key == InputKeyOk) {
|
|
|
int nh = next_height(cursorx);
|
|
int nh = next_height(cursorx);
|
|
|
- if (nh!=-1){
|
|
|
|
|
|
|
+ if(nh != -1) {
|
|
|
matrix[nh][cursorx] = player;
|
|
matrix[nh][cursorx] = player;
|
|
|
player = 3 - player;
|
|
player = 3 - player;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
if(event.key == InputKeyUp) {
|
|
if(event.key == InputKeyUp) {
|
|
|
//cursory--;
|
|
//cursory--;
|
|
|
}
|
|
}
|
|
@@ -293,36 +286,36 @@ int32_t four_in_row_app(void* p) {
|
|
|
//cursory++;
|
|
//cursory++;
|
|
|
}
|
|
}
|
|
|
if(event.key == InputKeyLeft) {
|
|
if(event.key == InputKeyLeft) {
|
|
|
- if (cursorx > 0){
|
|
|
|
|
|
|
+ if(cursorx > 0) {
|
|
|
cursorx--;
|
|
cursorx--;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
if(event.key == InputKeyRight) {
|
|
if(event.key == InputKeyRight) {
|
|
|
- if (cursorx < 6){
|
|
|
|
|
|
|
+ if(cursorx < 6) {
|
|
|
cursorx++;
|
|
cursorx++;
|
|
|
- } }
|
|
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
if(event.key == InputKeyBack) {
|
|
if(event.key == InputKeyBack) {
|
|
|
break;
|
|
break;
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
view_port_update(view_port);
|
|
view_port_update(view_port);
|
|
|
- furi_mutex_release(mutex);
|
|
|
|
|
-
|
|
|
|
|
|
|
+ furi_mutex_release(fourinrow_state->mutex);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // Специальная очистка памяти, занимаемой очередью
|
|
|
|
|
|
|
+ // Clear notification
|
|
|
notification_message_block(notification, &sequence_display_backlight_enforce_auto);
|
|
notification_message_block(notification, &sequence_display_backlight_enforce_auto);
|
|
|
furi_record_close(RECORD_NOTIFICATION);
|
|
furi_record_close(RECORD_NOTIFICATION);
|
|
|
|
|
+
|
|
|
// Специальная очистка памяти, занимаемой очередью
|
|
// Специальная очистка памяти, занимаемой очередью
|
|
|
furi_message_queue_free(event_queue);
|
|
furi_message_queue_free(event_queue);
|
|
|
|
|
|
|
|
// Чистим созданные объекты, связанные с интерфейсом
|
|
// Чистим созданные объекты, связанные с интерфейсом
|
|
|
gui_remove_view_port(gui, view_port);
|
|
gui_remove_view_port(gui, view_port);
|
|
|
view_port_free(view_port);
|
|
view_port_free(view_port);
|
|
|
-
|
|
|
|
|
- furi_mutex_free(bomber_state->mutex);
|
|
|
|
|
|
|
+ furi_mutex_free(fourinrow_state->mutex);
|
|
|
furi_record_close(RECORD_GUI);
|
|
furi_record_close(RECORD_GUI);
|
|
|
- free(bomber_state);
|
|
|
|
|
|
|
+ free(fourinrow_state);
|
|
|
|
|
|
|
|
return 0;
|
|
return 0;
|
|
|
}
|
|
}
|