/*************************************************************************** * llk_algorithm.c * * Fri Sep 23 08:46:05 2005 * Copyright 2005 Alpher * Email: alpher_zmx@yahoo.com.cn ****************************************************************************/ /* * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include gboolean algorithm_game_init(void) { gint i,j; algorithm_game.difficulty = 0; algorithm_game.level = 0; algorithm_game.life = 0; algorithm_game.hint = 0; algorithm_game.score = 0; algorithm_game.status = ALGORITHM_GAME_STOP; for(i=0;i<8;i++) for(j=0;j<16;j++) algorithm_game.data[i][j]=0; return TRUE; } gboolean algorithm_game_begin(gpointer data) { /*get a random order of the card image list*/ if(algorithm_game.status == ALGORITHM_GAME_STOP) { switch(GPOINTER_TO_INT(data)) { case 1: algorithm_game.row = 6; algorithm_game.col = 12; algorithm_game.difficulty = 0; algorithm_game.level = 0; algorithm_game.life = 2; algorithm_game.hint = 4; algorithm_game.score = 0; break; case 2: algorithm_game.row = 7; algorithm_game.col = 14; algorithm_game.difficulty = 1; algorithm_game.level = 0; algorithm_game.life = 3; algorithm_game.hint = 6; algorithm_game.score = 0; break; case 3: algorithm_game.row = 8; algorithm_game.col = 16; algorithm_game.difficulty = 2; algorithm_game.level = 0; algorithm_game.life = 4; algorithm_game.hint = 8; algorithm_game.score = 0; break; default: algorithm_game.row = 8; algorithm_game.col = 16; algorithm_game.difficulty = 2; algorithm_game.level = 0; algorithm_game.life = 4; algorithm_game.hint = 5; algorithm_game.score = 0; } algorithm_init_data(); algorithm_game.status = ALGORITHM_GAME_RUN; return TRUE; } else { return FALSE; } } void algorithm_init_data(void) { gint picture_type = 36; gint i,j=128; time_t t; GSList *picture_list = NULL, *tmp_node; /*Single list*/ switch(algorithm_game.difficulty) { case 0: picture_type = 21; j = 72; break; case 1: picture_type = 25; j = 98; break; case 2: picture_type = 32; j = 128; break; default:/*assert not reach*/ break; } for(i=0;inext; tmp_node->next = NULL; /*close the node's next node pointer,and so get a 1 node single list,and then free it.*/ g_slist_free(tmp_node); /*free the single list.*/ } else { tmp_node = g_slist_nth(picture_list,i); g_slist_nth(picture_list,i-1)->next = tmp_node->next; tmp_node->next = NULL; /*close the node's next node pointer,and so get a 1 node single list,and then free it.*/ g_slist_free(tmp_node); /*free the single list*/ } j--; } } /* test if p1 and p2 can direct link or not. that is to say,the points between p1 and p2 at the same row or column are all empty. BE CARE:this function do not warrant p1 and p2 have the same type of image. */ gboolean algorithm_can_direct_link(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { /* if(p1.x > 0 && p1.x < algorithm_game.row && p1.y > 0 && p1.y < algorithm_game.col && p2.x > 0 && p2.x < algorithm_game.row && p2.y > 0 && p2.y < algorithm_game.col) g_assert(algorithm_game.data[p1.x][p1.y] == algorithm_game.data[p2.x][p2.y]); */ /*g_print("Direct Link,x1: %d, y1: %d , x2: %d, y2:%d \n",p1.x,p1.y,p2.x,p2.y);*/ if(p1.x == p2.x || p1.y == p2.y) { gint i; if(abs(p1.x - p2.x) + abs(p1.y - p2.y) <= 1) { return TRUE; } else { if(p1.x == p2.x && p1.x > -1 && p1.x < algorithm_game.row) { if(p1.y > p2.y) { for(i=p2.y+1; i 0) return FALSE; } } else { for(i=p1.y+1;i 0) return FALSE; } } } else if(p1.y == p2.y && p1.y > -1 && p1.y < algorithm_game.col) { if(p1.x > p2.x) { for(i=p2.x+1;i 0) return FALSE; } } else { for(i=p1.x+1;i 0) return FALSE; } } } return TRUE; } } else { return FALSE; } } /* test if p1 and p2 can link. first,test if p1 and p2 can direct link,if not,get p1's and p2's adjacent empty points at x and y direction, judge if the p1's adjacent empty point can direct link to p2's */ gboolean algorithm_can_link(struct AlgorithmPoint p1, struct AlgorithmPoint p2, struct AlgorithmPoint *pp3, struct AlgorithmPoint *pp4) { if(algorithm_game.data[p1.x][p1.y] != algorithm_game.data[p2.x][p2.y]) { return FALSE; } if(algorithm_can_direct_link(p1,p2) && pp3 == NULL) /*can direct link,no need to return the turn points.*/ { return TRUE; } else { /*get adjacent empty points at x and y direction,judge point by point*/ GSList *p1_list=NULL,*p2_list=NULL; p1_list = algorithm_get_points(p1); p2_list = algorithm_get_points(p2); /* g_print("length_p1: %d, length_p2: %d \n",g_slist_length(p1_list),g_slist_length(p2_list)); for(i=0;ix,((struct AlgorithmPoint*)g_slist_nth_data(p1_list,i))->y); } g_print("\n"); for(j=0;jx,((struct AlgorithmPoint*)g_slist_nth_data(p2_list,j))->y); } g_print("\n"); */ if(p1_list == NULL || p2_list == NULL) { return FALSE; } else { gint i,j; for(i=0;ix = ((struct AlgorithmPoint*)g_slist_nth_data(p1_list,i))->x; pp3->y = ((struct AlgorithmPoint*)g_slist_nth_data(p1_list,i))->y; pp4->x = ((struct AlgorithmPoint*)g_slist_nth_data(p2_list,j))->x; pp4->y = ((struct AlgorithmPoint*)g_slist_nth_data(p2_list,j))->y; } algorithm_free_with_data(p1_list); algorithm_free_with_data(p2_list); return TRUE; } /*g_print("can link over.\n"); */ } } algorithm_free_with_data(p1_list); algorithm_free_with_data(p2_list); return FALSE; } } } /* free single list and the memory of the data it refer */ void algorithm_free_with_data(GSList *list) { GSList *last; last = list; while (last) { g_free (last->data); last = last->next; } g_slist_free(list); } /* find up,down,left and right of point p,get the adjacent empty points,form a single list,and return it. */ GSList * algorithm_get_points(struct AlgorithmPoint p) { struct AlgorithmPoint *tmp_point=NULL; GSList *p_list=NULL; gint i; /*g_print("Get Points,x1: %d, y1: %d \n",p.x,p.y);*/ for(i=p.y + 1; i<=algorithm_game.col; i++) { /*p_list = algorithm_game.data[p.x][i] == 0 ? g_slist_prepend(p_list,ddd) : p_list;*/ if(i < algorithm_game.col && algorithm_game.data[p.x][i] > 0) { break; } else { tmp_point = (struct AlgorithmPoint *)g_malloc(sizeof(struct AlgorithmPoint)); tmp_point->x = p.x; tmp_point->y = i; p_list = g_slist_prepend(p_list,tmp_point); } } for(i=p.y - 1; i >= -1; i--) { /*p_list = algorithm_game.data[p.x][i] == 0 ? g_slist_prepend(p_list,ddd) : p_list;*/ if(i > -1 && algorithm_game.data[p.x][i] > 0) { break; } else { tmp_point = (struct AlgorithmPoint *)g_malloc(sizeof(struct AlgorithmPoint)); tmp_point->x = p.x; tmp_point->y = i; p_list = g_slist_prepend(p_list,tmp_point); } } for(i=p.x + 1; i<=algorithm_game.row; i++) { /*p_list = algorithm_game.data[p.x][i] == 0 ? g_slist_prepend(p_list,ddd) : p_list;*/ if(i < algorithm_game.row && algorithm_game.data[i][p.y] > 0) { break; } else { tmp_point = (struct AlgorithmPoint *)g_malloc(sizeof(struct AlgorithmPoint)); tmp_point->x = i; tmp_point->y = p.y; p_list = g_slist_prepend(p_list,tmp_point); } } for(i=p.x - 1; i >= -1; i--) { /*p_list = algorithm_game.data[p.x][i] == 0 ? g_slist_prepend(p_list,ddd) : p_list;*/ if(i > -1 && algorithm_game.data[i][p.y] > 0) { break; } else { tmp_point = (struct AlgorithmPoint *)g_malloc(sizeof(struct AlgorithmPoint)); tmp_point->x = i; tmp_point->y = p.y; p_list = g_slist_prepend(p_list,tmp_point); } } /*in order to efficient the operation of insert node to a single list,above algorithm insert node at the front, and then reverse the list,and return.MUST reverse,or will not get the right points of turning. */ return g_slist_reverse(p_list); } /* empty the data of the two points. */ void algorithm_link(struct AlgorithmPoint p1,struct AlgorithmPoint p2) { algorithm_game.data[p1.x][p1.y] = 0; algorithm_game.data[p2.x][p2.y] = 0; /*add score*/ algorithm_game.score += 20; } /* test if the current game situation have solution. return value: 0: yes,have solution. 1: no,need to shuffle the cards. 2: the cards are all deleted,this level is clear. */ gint algorithm_game_no_solution(void) { gint i,j; gint k,l; gint cards_num = 0; /*g_print("================================================================\n");*/ for(i=0; i 0) { cards_num++; for(k=i;k 0) { struct AlgorithmPoint p1,p2; p1.x = i; p1.y = j; p2.x = k; p2.y = l; if(algorithm_can_link(p1,p2,NULL,NULL)) { /*g_print("p1:%d,%d -- p2:%d,%d can link.\n",p1.x,p1.y,p2.x,p2.y);*/ return 0; } /*g_print("p1:%d,%d -- p2:%d,%d can not link.\n",p1.x,p1.y,p2.x,p2.y);*/ } } } } } } if(cards_num > 0) { return 1; } return 2; } /* shuffle cards. read the remain cards in data array,form a single list.then traversal the data array, at every point that have cards,get a random card from the single list and put it there. BE CARE: the life value will be minimised in UI dealing function,because in this function, shuffle one time do not certainly get a game situation that have solution,so this function may be called more than one time. */ void algorithm_game_shuffle(void) { GSList *picture_list = NULL, *tmp_node; gint i,j; time_t t; for(i=0; i < algorithm_game.row; i++) { for(j=0; j < algorithm_game.col; j++) { if(algorithm_game.data[i][j] > 0) { picture_list = g_slist_prepend(picture_list,GINT_TO_POINTER(algorithm_game.data[i][j])); } } } srand( (unsigned)time(&t) ); for(i=0; i < algorithm_game.row; i++) { for(j=0; j < algorithm_game.col; j++) { if(algorithm_game.data[i][j] > 0) { gint m = rand()%g_slist_length(picture_list) ; if(m == 0) m=1; m--; tmp_node = g_slist_nth(picture_list,m); algorithm_game.data[i][j] = GPOINTER_TO_INT(tmp_node->data); if( m == 0 ) { picture_list = picture_list->next; tmp_node->next = NULL; g_slist_free(tmp_node); } else { g_slist_nth(picture_list,m-1)->next = tmp_node->next; tmp_node->next = NULL; g_slist_free(tmp_node); } } } } if(algorithm_game_no_solution() == 1)algorithm_game_shuffle(); /*recursion call of this function,untill get a game situation that have solution.*/ } void algorithm_game_change(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { switch(algorithm_game.level) { case 0:/*No Change*/ algorithm_data_change_0(p1,p2); break; case 1:/*Move Down*/ algorithm_data_change_1(p1,p2); break; case 2:/*Move Left*/ algorithm_data_change_2(p1,p2); break; case 3:/*Up Down Separate*/ algorithm_data_change_3(p1,p2); break; case 4:/*Left and Right Separate*/ algorithm_data_change_4(p1,p2); break; case 5:/*Up and Down Converge*/ algorithm_data_change_5(p1,p2); break; case 6:/*Left and Right Converge*/ algorithm_data_change_6(p1,p2); break; case 7:/*Up leftward,Down rightward*/ algorithm_data_change_7(p1,p2); break; case 8:/*Left downward,Right upward*/ algorithm_data_change_8(p1,p2); break; case 9:/*Disperse from Center*/ algorithm_data_change_9(p1,p2); break; case 10:/*Centralize*/ algorithm_data_change_10(p1,p2); break; default: /*assert not reach*/ break; } } gboolean algorithm_game_net_level(void) { if( algorithm_game.level >= 10 ) /*11 Levels,from 0 to 10*/ { return FALSE; } else { algorithm_game.level ++; algorithm_game.life += 1; algorithm_game.hint += 1; algorithm_game.score += algorithm_game.level > 5 ? 400*algorithm_game.level : 200*algorithm_game.level; algorithm_game.score += algorithm_game.life*100 + algorithm_game.hint*50; algorithm_init_data(); return TRUE; } } /*No Change, do nothing*/ void algorithm_data_change_0(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { /*do nothing*/ } /*Move Down*/ void algorithm_data_change_1(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint i; for(i=p1.x;i>0;i--) { algorithm_game.data[i][p1.y] = algorithm_game.data[i-1][p1.y]; } algorithm_game.data[0][p1.y] = 0; i=p2.x; if(p1.y == p2.y && p1.x > p2.x)i++; for( ;i>0;i--) { algorithm_game.data[i][p2.y] = algorithm_game.data[i-1][p2.y]; } algorithm_game.data[0][p2.y] = 0; } /*Move Left*/ void algorithm_data_change_2(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { /*BE CARE: the last column do not in the for loop.*/ gint j; for(j=p1.y;j < algorithm_game.col-1; j++) { algorithm_game.data[p1.x][j] = algorithm_game.data[p1.x][j+1]; } algorithm_game.data[p1.x][algorithm_game.col-1] = 0; j=p2.y; if(p1.x == p2.x && p1.y < p2.y)j--; for( ;j= algorithm_game.row/2 && p2.x >= algorithm_game.row/2) /*p1 and p2 are all in the down half rows*/ { if(p1.x > p2.x) { tmp_start++; } } } i = tmp_start; if(tmp_start != tmp_end) { while(i != tmp_end) { gint sign = (tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[i][p2.y] = algorithm_game.data[i+sign][p2.y]; algorithm_game.data[i+sign][p2.y] =0; i=i+sign; } } } /*Left and Right Separate*/ void algorithm_data_change_4(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint j; gint tmp_start,tmp_end; tmp_start = p1.y; tmp_end = algorithm_game.col/2; if(p1.y < algorithm_game.col/2) tmp_end--; j = tmp_start; if(tmp_start != tmp_end) { while( j != tmp_end ) { gint sign=(tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[p1.x][j] = algorithm_game.data[p1.x][j+sign]; algorithm_game.data[p1.x][j+sign] = 0; j=j+sign; } } tmp_start = p2.y; tmp_end = algorithm_game.col/2; if(p2.y < algorithm_game.col/2)tmp_end--; if(p1.x == p2.x) { if(p1.y < algorithm_game.col/2 && p2.y < algorithm_game.col/2) { if(p1.y < p2.y) { tmp_start--; } } else if(p1.y >= algorithm_game.col/2 && p2.y >= algorithm_game.col/2) { if(p1.y > p2.y) { tmp_start++; } } } j=tmp_start; if(tmp_start != tmp_end) { while(j != tmp_end) { gint sign = (tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[p2.x][j] = algorithm_game.data[p2.x][j+sign]; algorithm_game.data[p2.x][j+sign] = 0; j = j+sign; } } } /*Up and Down Converge*/ void algorithm_data_change_5(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint i; gint tmp_start,tmp_end; tmp_start = p1.x; if(p1.x < algorithm_game.row/2) /* <= row/2 -1 */ { tmp_end = 0; } else { tmp_end = algorithm_game.row-1; } i=tmp_start; if(tmp_start != tmp_end) { while(i != tmp_end) { gint sign=(tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[i][p1.y] = algorithm_game.data[i+sign][p1.y]; algorithm_game.data[i+sign][p1.y] =0; i=i+sign; } } tmp_start = p2.x; if(p2.x < algorithm_game.row/2) { tmp_end = 0; } else { tmp_end = algorithm_game.row - 1; } if(p1.y == p2.y) /*同p1 and p2 are in the same column*/ { if(p1.x < algorithm_game.row/2 && p2.x < algorithm_game.row/2) /*p1 and p2 are all in the up half rows*/ { if(p1.x > p2.x) /*p1's move will change p2's positon*/ { tmp_start++; /*start positon move down*/ } } else if(p1.x >= algorithm_game.row/2 && p2.x >= algorithm_game.row/2) /*p1 and p2 are all in the down half rows*/ { if(p1.x < p2.x) { tmp_start--; } } } i = tmp_start; if(tmp_start != tmp_end) { while(i != tmp_end) { gint sign = (tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[i][p2.y] = algorithm_game.data[i+sign][p2.y]; algorithm_game.data[i+sign][p2.y] =0; i=i+sign; } } } /*Left and Right Converge*/ void algorithm_data_change_6(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint j; gint tmp_start,tmp_end; tmp_start = p1.y; if(p1.y < algorithm_game.col/2) { tmp_end = 0; } else { tmp_end = algorithm_game.col - 1; } j = tmp_start; if(tmp_start != tmp_end) { while( j != tmp_end ) { gint sign=(tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[p1.x][j] = algorithm_game.data[p1.x][j+sign]; algorithm_game.data[p1.x][j+sign] = 0; j=j+sign; } } tmp_start = p2.y; if(p2.y < algorithm_game.col/2) { tmp_end = 0; } else { tmp_end = algorithm_game.col - 1; } if(p1.x == p2.x) { if(p1.y < algorithm_game.col/2 && p2.y < algorithm_game.col/2) { if(p1.y > p2.y) { tmp_start++; } } else if(p1.y >= algorithm_game.col/2 && p2.y >= algorithm_game.col/2) { if(p1.y < p2.y) { tmp_start--; } } } j=tmp_start; if(tmp_start != tmp_end) { while(j != tmp_end) { gint sign = (tmp_end - tmp_start)/abs(tmp_end - tmp_start); algorithm_game.data[p2.x][j] = algorithm_game.data[p2.x][j+sign]; algorithm_game.data[p2.x][j+sign] = 0; //this sentence can be write outside of while loop in some way. j = j+sign; } } } /*Up leftward,Down rightward*/ void algorithm_data_change_7(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint j; if(p1.x < algorithm_game.row/2) /*leftward*/ { for(j=p1.y;j < algorithm_game.col-1; j++) { algorithm_game.data[p1.x][j] = algorithm_game.data[p1.x][j+1]; } algorithm_game.data[p1.x][algorithm_game.col-1] = 0; } else /*rightward*/ { for(j=p1.y;j>0;j--) { algorithm_game.data[p1.x][j] = algorithm_game.data[p1.x][j-1]; } algorithm_game.data[p1.x][0] = 0; } j=p2.y; if(p2.x < algorithm_game.row/2) /*leftward*/ { if(p1.x == p2.x && p1.y < p2.y)j--; for( ;j p2.y)j++; for(;j>0;j--) { algorithm_game.data[p2.x][j] = algorithm_game.data[p2.x][j-1]; } algorithm_game.data[p2.x][0] = 0; } } /*Left downward,Right upward*/ void algorithm_data_change_8(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { gint i; if(p1.y < algorithm_game.col/2) /*downward*/ { for(i=p1.x;i>0;i--) { algorithm_game.data[i][p1.y] = algorithm_game.data[i-1][p1.y]; } algorithm_game.data[0][p1.y] = 0; } else /*upward*/ { for(i=p1.x;i p2.x)i++; for( ;i>0;i--) { algorithm_game.data[i][p2.y] = algorithm_game.data[i-1][p2.y]; } algorithm_game.data[0][p2.y] = 0; } else /*upward*/ { if(p1.y == p2.y && p1.x < p2.x)i--; for(; i < algorithm_game.row-1; i++) { algorithm_game.data[i][p2.y] = algorithm_game.data[i+1][p2.y]; } algorithm_game.data[algorithm_game.row-1][p2.y]=0; } } /* Disperse from Center first,left and right seperate,and then up and down seperate. */ void algorithm_data_change_9(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { struct AlgorithmPoint p3,p4; gint sign; algorithm_data_change_4( p1, p2 ); /*1.left and right seperate*/ /*find p1,p2 's position after 'left and right seperate',then do 'up and down seperate' on p1,p2 's new position*/ p3.x=p1.x; p3.y = (p1.y < algorithm_game.col/2) ? 0 : (algorithm_game.col-1) ; sign= p3.y ? -1:1; while(algorithm_game.data[p3.x][p3.y] != 0) { p3.y = p3.y + sign; } p4.x = p2.x; p4.y = (p2.y < algorithm_game.col/2) ? 0 : (algorithm_game.col-1); sign = p4.y ? -1:1; while(algorithm_game.data[p4.x][p4.y] != 0) { p4.y = p4.y + sign; } /*modify in case of special situation*/ if(p1.x == p2.x) { if(p1.y < algorithm_game.col/2 && p2.y < algorithm_game.col/2) { p4.y = p3.y + 1; } else if(p1.y >= algorithm_game.col/2 && p2.y >= algorithm_game.col/2) { p4.y = p3.y - 1; } } /*p3,p4 are the new position of p1,p2 after 'left and right seperate', do 'up and down seperate' on them*/ algorithm_data_change_3(p3,p4); } /* Centralize first do 'Left Right Converge' and then 'Up Down Converge' */ void algorithm_data_change_10(struct AlgorithmPoint p1, struct AlgorithmPoint p2) { struct AlgorithmPoint p3,p4; gint sign; algorithm_data_change_6( p1, p2 ); /*first do 'Left Right Converge'*/ /*find the new position of p1,p2 after 'Left Right Converge',then do 'Up Down Converge' on new position*/ p3.x=p1.x; p3.y = (p1.y < algorithm_game.col/2) ? (algorithm_game.col/2 - 1) : (algorithm_game.col/2) ; sign= (p1.y < algorithm_game.col/2) ? -1:1; while(algorithm_game.data[p3.x][p3.y] != 0) { p3.y = p3.y + sign; } p4.x = p2.x; p4.y = (p2.y < algorithm_game.col/2) ? (algorithm_game.col/2 - 1) : (algorithm_game.col/2); sign = (p2.y < algorithm_game.col/2) ? -1:1; while(algorithm_game.data[p4.x][p4.y] != 0) { p4.y = p4.y + sign; } /*modify in case of special situation*/ if(p1.x == p2.x) { if(p1.y < algorithm_game.col/2 && p2.y < algorithm_game.col/2) { p4.y = p3.y - 1; } else if(p1.y >= algorithm_game.col/2 && p2.y >= algorithm_game.col/2) { p4.y = p3.y + 1; } } /*p3,p4 are the new position of p1,p2 after 'Left Right Converge', do 'Up Down Converge' on them*/ algorithm_data_change_5(p3,p4); }