C語言寫的榫卯拼圖遊戲
阿新 • • 發佈:2021-07-18
C語言寫的小遊戲,沒什麼實際意義,玩具程式碼,僅供娛樂與參考學習。
作者的話:
簡單命令的有趣應用。不會拿別的寫遊戲,但又想寫,就有了此程式。
本玩具程式碼沒有刪除關卡的功能。您一個人玩(all_level.dat中沒有其他玩家的資料)如果想刪除關卡的話就直接刪all_level.dat,然後重新執行好了。
作者把主要功能寫完後,為了提高趣味性設定了得分系統。只有第一次嘗試的得分是有效的。這恰好掩蓋了不能取消放置方塊這一不足之處。
嘗試多次都通不了關就開掛吧。
#include <conio.h> //用於getch() #include <math.h> #include <stdio.h> #include<stdlib.h> //用於rand #include <string.h> #include <time.h> #include <windows.h> int game_area[32][37] = {0}; int color_map[16][16] = {0}; char current_player_ID[10] = "TBE"; char player_trace[14]; char current_level_name[30]; char title[5][20] = { {"[Mortise ]"}, {"[ &Tenon]"}, {"[榫卯 ]"}, {"[ 拼拼看]"}}; char logo[16][5] = { {"111"}, {"110"}, {"111"}, {"010"}, {"1010"}, {"1111"}, {"1110"}, {"010"}, {"111"}, {"011"}, {"111"}, {"0111"}, {"1111"}, {"0101"}, }; struct Doc{ char docLine[7][15]; }doc[4] = { {{{"[ ]"}, {"[榫,剡木]"}, {"[入竅也。]"}, {"[ --]"}, {"[《集韻》]"}, {"[ ]"}}}, {{{"[ ]"}, {"[榫卯萬年]"}, {"[牢。 ]"}, {"[ --]"}, {"[ 俗語]"}, {"[ ]"}}}, {{{"[一著不慎]"}, {"[,滿盤皆]"}, {"[輸。 ]"}, {"[ --]"}, {"[ 俗語]"}, {"[ ]"}}}, {{{"[謀定而後]"}, {"[動。 ]"}, {"[ --]"}, {"[《孫子兵]"}, {"[法》 ]"}, {"[ ]"}}}}; struct _Block{ int block[10][10]; }Block[16]; struct _Buldge_concave_info{ int concave_len[4][2];//4條邊,每邊2個凹陷度 int buldge_concave_info[4][2];//4條邊,每邊2個凹凸資訊域, }Buldge_concave_info[16]; struct _Block_buffer{ int block_buffer[2][2];//左和上兩個方向各兩個 }Block_buffer[16];//需設定緩衝區的方塊共9個,其他的塊也一併設定,以使序號對的上 struct _Player_win{ char player_win_ID[10]; int time_cost; int cnt_browse; double score; char grade; }; struct _Level{ char level_name[30]; struct _Block level_block[16]; struct _Player_win level_player_win[5];//為了儘早實現整體結構,先不使用malloc動態分配記憶體,設定通關的人數最多為5 char creator[30]; int player_win_total; }; struct _Block_node{ int node_block[10][10]; int init_num; int list_num; int color; int direction_index; struct _Block_node *prev; struct _Block_node *next; }; int height = 30, width = 35; int info_tag0, info_tag1;//替代域0,替代域1 int if_first = 1, if_full = 0;//是否第一次,是否人滿,用來判斷記錄是否有效 char choose; void gotoxy(); void hideCursor(); void showCursor(); int getRand(int min, int max); void menu(); int login(); int levelEntry(int mode); void myGame(); void initGameArea(); void createBuldgeConcaveInfo(struct _Buldge_concave_info *p, int i, int j); void createAllBuldgeConcaveInfo(); void applyInfoToBlock(struct _Buldge_concave_info *p, int i, int j); void solveForConcaveLength(struct _Buldge_concave_info *p, int i, int j); void processBlockBuffer(struct _Block_buffer *b, struct _Buldge_concave_info *p, int i); void rotateForInit(); void initBlock(); int createLevel(); char *getLocalTime(); void cpyBlockFromLevel(struct _Level *lp); int runLevel(); int ifQuit(struct _Block_node *head); struct _Block_node *createBlockList(int rand_sequence[]); struct _Block_node *createBlockNode(); void getRandSequence(int rand_sequence[]); int getRandColor(); void randRotate(struct _Block_node *np); void showNodeBlock(struct _Block_node *np); struct _Block_node *deleteBlockNode(struct _Block_node *np, struct _Block_node *head); void showListNum(struct _Block_node *np, int total); void getBuldgeInfo(int buldge_info[], struct _Block_node *np); void showReference(int direct, int top, int bottom, int leftmost, int rightmost, int buldge_info[]); void showMovedBlock(int **min_block, int direct, int top, int bottom, int leftmost, int rightmost, int row, int col); int getRandLength(int max_len); int ifTwoSides(); int ifPlain(); void preventDouble3(); void printLogo(); void printMenuPage(); void printHelpPage(); void printAboutPage(); void printMyGamePage(); void gotoxy(int x, int y) //座標函式 { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(handle, pos); } void hideCursor() //游標隱藏 { CONSOLE_CURSOR_INFO cursor_info = {1, 0}; //後邊的0代表游標不可見 SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } void showCursor() { CONSOLE_CURSOR_INFO cursor_info = {1, 1}; SetConsoleCursorInfo(GetStdHandle(STD_OUTPUT_HANDLE), &cursor_info); } void menu() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); system("mode con cols=46 lines=16"); system("cls"); printMenuPage(); choose = getch(); while(choose != 'm' && choose != 'l' && choose != 'h' && choose != 'a' && choose != 'q') choose = getch(); switch(choose) { case 'm': if((strcmp(current_player_ID, "TBE")) == 0) { if(login() == -1) { sleep(2); menu(); break; } } myGame(); break; case 'l': if((strcmp(current_player_ID, "TBE")) == 0) { if(login() == -1) { sleep(2); menu(); break; } } if(levelEntry(0) == 1) { if(runLevel() == -1) { sleep(2); menu(); } else menu(); } else { sleep(2); menu(); } break; case 'h': system("mode con cols=84 lines=15"); system("cls"); printHelpPage(); choose=getch(); while(choose!='b') choose=getch(); menu(); break; case 'a': system("cls"); printAboutPage(); choose=getch(); while(choose!='b') choose=getch(); menu(); break; case 'q': exit(0); } } int login() { char *p; FILE *fp; int i = 0; system("cls"); gotoxy(0, 6); printf(" 請輸入您的遊戲ID "); gotoxy(20, 7); showCursor(); fgets(current_player_ID, 10, stdin); fflush(stdin); hideCursor(); p = current_player_ID; while(p[i] != '\n') { i++; p[i] = current_player_ID[i]; } current_player_ID[i] = '\0'; strcpy(player_trace, current_player_ID); strcat(player_trace, ".dat"); if((fp = fopen(player_trace, "ab+")) == NULL) { system("cls"); printf(" 拉取玩家資料失敗,即將返回上一級... \n"); return -1; } fclose(fp); return 1; } int levelEntry(int mode) { FILE *fp1, *fp2; struct _Level* lp; struct _Level tmp_level; struct _Player_win *pwp[5]; struct _Player_win *tmp_pwp; char tmp_level_name[30]; int length = 3;//初始關卡數 int cnt = 0, if_end = 0; int i, j, k, tmp_p_w_t, chs_p_w_t; int judge, chosen; system("cls"); system("mode con cols=46 lines=20"); if((fp1 = fopen("all_level.dat", "rb")) == NULL) { printf(" 拉取關卡庫失敗,即將返回上一級... \n"); return -1; } lp = (struct _Level*)malloc(sizeof(struct _Level) * length); switch(mode) { case 0: if((fp2 = fopen(player_trace, "rb")) == NULL) { printf(" 拉取玩家資料失敗,即將返回上一級... \n"); return -1; } printf("*******************全部關卡*******************\n"); while(1) { fread(&tmp_level, sizeof(struct _Level), 1, fp1); if(feof(fp1)) break; cnt++; gotoxy(0, cnt); printf("******"); gotoxy(10, cnt); printf("(%d) %s", cnt - 1, tmp_level.level_name); gotoxy(40, cnt); printf("******\n"); if(cnt >= length) lp = (struct _Level*)realloc(lp, sizeof(struct _Level) * (++length)); strcpy((lp + cnt - 1)->level_name, tmp_level.level_name); for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) (lp + cnt - 1)->level_block[i].block[j][k] = tmp_level.level_block[i].block[j][k]; } } tmp_p_w_t = tmp_level.player_win_total; (lp + cnt - 1)->player_win_total = tmp_p_w_t; for(i = 0; i < tmp_p_w_t; i++) { strcpy((lp + cnt - 1)->level_player_win[i].player_win_ID, tmp_level.level_player_win[i].player_win_ID); (lp + cnt - 1)->level_player_win[i].score = tmp_level.level_player_win[i].score; (lp + cnt - 1)->level_player_win[i].grade = tmp_level.level_player_win[i].grade; (lp + cnt - 1)->level_player_win[i].cnt_browse = tmp_level.level_player_win[i].cnt_browse; (lp + cnt - 1)->level_player_win[i].time_cost = tmp_level.level_player_win[i].time_cost; } } fclose(fp1); if(cnt == 0) { free(lp); printf(" 還沒有任何遊戲記錄,即將返回上一級... \n"); return -1; } break; case 1: if_first = 0; printf("*******************我的關卡*******************\n"); while(1) { fread(&tmp_level, sizeof(struct _Level), 1, fp1); if(feof(fp1)) break; if(strcmp(tmp_level.creator, current_player_ID) == 0) { cnt++; gotoxy(0, cnt); printf("******"); gotoxy(10, cnt); printf("(%d) %s", cnt - 1, tmp_level.level_name); gotoxy(40, cnt); printf("******\n"); if(cnt >= length) lp = (struct _Level*)realloc(lp, sizeof(struct _Level) * (++length)); strcpy((lp + cnt - 1)->level_name, tmp_level.level_name); for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) (lp + cnt - 1)->level_block[i].block[j][k] = tmp_level.level_block[i].block[j][k]; } } tmp_p_w_t = tmp_level.player_win_total; (lp + cnt - 1)->player_win_total = tmp_p_w_t; for(i = 0; i < tmp_p_w_t; i++) { strcpy((lp + cnt - 1)->level_player_win[i].player_win_ID, tmp_level.level_player_win[i].player_win_ID); (lp + cnt - 1)->level_player_win[i].score = tmp_level.level_player_win[i].score; (lp + cnt - 1)->level_player_win[i].grade = tmp_level.level_player_win[i].grade; (lp + cnt - 1)->level_player_win[i].cnt_browse = tmp_level.level_player_win[i].cnt_browse; (lp + cnt - 1)->level_player_win[i].time_cost = tmp_level.level_player_win[i].time_cost; } } } fclose(fp1); if(cnt == 0) { free(lp); printf(" 您的歷史記錄為空,即將返回上一級... \n"); return -1; } break; } printf("**********************************************\n"); printf(" 請輸入關卡序號:"); showCursor(); judge = scanf("%d", &chosen); fflush(stdin); while(judge != 1 || chosen < 0 || chosen >= cnt) { printf(" 輸入無效,請重新輸入關卡序號:"); judge = scanf("%d", &chosen); fflush(stdin); } hideCursor(); if((lp + chosen)->player_win_total > 0) { printf("*****************本關卡排名*******************\n"); printf("玩家ID 得分 等級 瀏覽次數 用時\n"); for(i = 0; i < 5; i++) pwp[i] = NULL; chs_p_w_t = (lp + chosen)->player_win_total; for(i = 0; i < chs_p_w_t; i++) pwp[i] = &((lp + chosen)->level_player_win[i]); for(i = 0; i < chs_p_w_t - 1; i++) { k = i; for(j = i + 1; j < chs_p_w_t; j++) { if(pwp[j]->score > pwp[k]->score) k = j; } if(k != i) { tmp_pwp = pwp[i]; pwp[i] = pwp[k]; pwp[k] = tmp_pwp; } } for(i = 0; i < chs_p_w_t; i++) printf("%s\t%.2lf\t %c %d\t %2d分%2d秒\n", pwp[i]->player_win_ID, pwp[i]->score, pwp[i]->grade, pwp[i]->cnt_browse, (pwp[i]->time_cost) / 60, (pwp[i]->time_cost) % 60); printf("**********************************************\n"); printf(" 按任意鍵繼續。 \n"); getch(); } if(mode == 0) { if((lp + chosen)->player_win_total == 5) if_full = 1;//這兩句防止刪掉自己的trace後點進了滿員的關卡 while(1) { fread(tmp_level_name, sizeof(char), 30, fp2); if(feof(fp2)) { if_end = 1; break; } if(strcmp((lp + chosen)->level_name, tmp_level_name) == 0) break; } fclose(fp2); if(if_end == 0) { if_first = 0; printf(" 這不是您的第一次挑戰,不得錄入有效記錄。 \n"); printf(" 按任意鍵繼續。 \n"); getch(); } else if((lp + chosen)->player_win_total == 5) { if_full = 1; printf(" 很抱歉,該關卡有成功挑戰記錄的人數已達上限! \n"); printf(" 您的有效記錄將不會被錄入。按任意鍵繼續。 \n"); getch(); } } strcpy(current_level_name, (lp + chosen)->level_name); cpyBlockFromLevel(lp + chosen); free(lp); return 1; } void myGame() { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); system("mode con cols=46 lines=16"); system("cls"); gotoxy(0, 3); printMyGamePage(); choose = getch(); while(choose != 'n' && choose != 'h' && choose != 'b') choose = getch(); switch(choose) { case 'n': system("cls"); system("mode con cols=46 lines=21"); printf(" 生成榫卯塊中... \n"); if(createLevel() == 1) { if(runLevel() == -1) { sleep(2); myGame(); } else myGame(); } else { sleep(2); myGame(); } break; case 'h': if(levelEntry(1) == 1) { if(runLevel() == -1) { sleep(2); myGame(); } else myGame(); } else { sleep(2); myGame(); } break; case 'b': menu(); break; } } void initGameArea() { int i, j; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); system("mode con cols=38 lines=33"); system("cls"); for (i = 0; i <= height + 1; i++) { for (j = 0; j <= width + 1; j = j + 2) { if (i == 0 || i == 1 || j == 0 || i == height || i == height + 1 || j == width - 1 || j == width + 1 || i == 13 || i == 12) game_area[i][j] = 2; else game_area[i][j] = 0; } } gotoxy(0, 0); //基本邊框 for (i = 0; i <= height + 1; i++) { for (j = 0; j <= width + 2; j = j + 2) { if (game_area[i][j] == 2) printf("[]"); else printf(" "); } printf("\n"); } //豎分劃 for (i = 2; i <= 11; i++) { gotoxy(22,i); printf("[]\n"); } //遊戲名 for (i = 1; i <= 4; i++) { gotoxy(24,i); printf("%s", title[i-1]); } gotoxy(24,5); printf("[][][][][]\n"); } //已知某邊兩個域的凹陷度,按一定規則給這兩個域的凹凸資訊隨機賦值 void createBuldgeConcaveInfo(struct _Buldge_concave_info *p, int i, int j)//i, j分別為第幾個塊,哪條邊 { struct _Block_buffer *b; b = Block_buffer; int len_tag0, len_tag1; len_tag0 = (p + i)->concave_len[j][0]; len_tag1 = (p + i)->concave_len[j][1]; if(!ifPlain())//凹凸資訊不置有平 { //凹凸資訊置一凹一凸的條件 :至少有一個域凹陷塊數不為0 if(len_tag0 > 0 || len_tag1 > 0) { if(ifTwoSides()) { //一個可凹一個不可凹 if(len_tag0 == 0) { info_tag0 = getRandLength(3); info_tag1 = - getRandLength(len_tag1); } else if(len_tag1 == 0) { info_tag1 = getRandLength(3); info_tag0 = - getRandLength(len_tag0); } //兩個都可凹 else { //選擇一個域,規定其凹凸資訊為負值,另一個域為正值 if(getRand(0, 1) == 0) { info_tag0 = - getRandLength(len_tag0); info_tag1 = getRandLength(3); } else { info_tag1 = - getRandLength(len_tag1); info_tag0 = getRandLength(3); } } } //若凹凸資訊不置有平,也不置一凹一凸,則凹凸資訊置單向。對於一個可凹一個不可凹的,只能為凸。 else if(len_tag0 == 0 || len_tag1 == 0) { info_tag0 = getRandLength(3); info_tag1 = getRandLength(3); preventDouble3(); } //凹凸資訊置單向,對於兩個均可凹的 else { if(getRand(0, 7) > 2)//凹 { info_tag0 = - getRandLength(len_tag0); info_tag1 = - getRandLength(len_tag1); preventDouble3(); } else//凸 { info_tag0 = getRandLength(3); info_tag1 = getRandLength(3); preventDouble3(); } } } else//凹凸資訊置單向,兩個均不可凹 { info_tag0 = getRandLength(3); info_tag1 = getRandLength(3); preventDouble3(); } } else//凹凸資訊置有平 { if(len_tag0 > 0 || len_tag1 > 0) { //兩個域均可凹 if(len_tag0 > 0 && len_tag1 > 0) { if(getRand(0, 1) == 0) { info_tag0 = 0; if(getRand(0, 4) < 3) info_tag1 = - getRandLength(len_tag1); else info_tag1 = getRandLength(3); } else { info_tag1 = 0; if(getRand(0, 4) < 3) info_tag0 = - getRandLength(len_tag0); else info_tag0 = getRandLength(3); } } //只有一個域可凹 else if(len_tag0 == 0) { //選擇一個域,置其凹凸資訊為平,另一個域再隨機 if(getRand(0, 4) < 3)//xzs:if(getRand(0, 1) == 0) { info_tag0 = 0; if(getRand(0, 4) < 3)//xzs:if(getRand(0, 1) == 0) info_tag1 = - getRandLength(len_tag1); else info_tag1 = getRandLength(3); } else { info_tag1 = 0; info_tag0 = getRandLength(3); } } else if(len_tag1 == 0) { if(getRand(0, 4) < 3)//xzs:ts { info_tag1 = 0; if(getRand(0, 4) < 3)//xzs:ts info_tag0 = - getRandLength(len_tag0); else info_tag0 = getRandLength(3); } else { info_tag0 = 0; info_tag1 = getRandLength(3); } } } else//兩個域均不可凹 { if(getRand(0, 1) == 0) { info_tag0 = 0; info_tag1 = getRandLength(3); } else { info_tag1 = 0; info_tag0 = getRandLength(3); } } } if(j == 0) { if((i >= 1 && i<= 3) || (i >= 5 && i <= 7) || (i >= 9 && i <= 11)) { //緩衝 (b + i + 4)->block_buffer[j][0] = - info_tag0; (b + i + 4)->block_buffer[j][1] = - info_tag1; printf("buffer%d area0:%d %d\n", i + 4, (b + i + 4)->block_buffer[j][0], (b + i + 4)->block_buffer[j][1]); sleep(2); //給緩衝區對應方塊的方陣及下緩塊的方陣賦值由緩衝區處理函式來完成 processBlockBuffer(b, p, i + 4);//由於drrd的順序,先1後0,故j == 0, j == 1兩個分支不具有對稱性,在j == 0時處理緩衝區 } else { (p + i)->buldge_concave_info[j][0] = info_tag0; (p + i)->buldge_concave_info[j][1] = info_tag1; applyInfoToBlock(p, i, j); (p + i + 4)->buldge_concave_info[2][0] = - info_tag0; (p + i + 4)->buldge_concave_info[2][1] = - info_tag1; applyInfoToBlock(p, i + 4, 2); } } else//j == 1 { if((i >= 4 && i<= 6) || (i >= 8 && i <= 10) || (i >= 12 && i <= 14)) { //將方塊右邊兩個域的凹凸資訊傳給緩衝區 (b + i + 1)->block_buffer[j][0] = - info_tag0; (b + i + 1)->block_buffer[j][1] = - info_tag1; printf("buffer%d area1:%d %d\n", i + 1, (b + i + 1)->block_buffer[j][0], (b + i + 1)->block_buffer[j][1]); sleep(2); } //由於處理緩衝區是以左邊為基的,隨即生成凹凸資訊是啥就加到方陣上啥 (p + i)->buldge_concave_info[j][0] = info_tag0; (p + i)->buldge_concave_info[j][1] = info_tag1; applyInfoToBlock(p, i, j); (p + i + 1)->buldge_concave_info[3][0] = - info_tag0; (p + i + 1)->buldge_concave_info[3][1] = - info_tag1; applyInfoToBlock(p, i + 1, 3); } } void applyInfoToBlock(struct _Buldge_concave_info *p, int i, int j) { int k; switch(j) { case 0: if(((p + i)->buldge_concave_info[j][0]) > 0) { for(k = 7; k <= 7 + ((p + i)->buldge_concave_info[j][0]) - 1; k++) { Block[i].block[k][4] = 1; } } else if(((p + i)->buldge_concave_info[j][0]) < 0) { for(k = 6; k >= 6 + ((p + i)->buldge_concave_info[j][0]) + 1; k--) { Block[i].block[k][4] = 0; } } if(((p + i)->buldge_concave_info[j][1]) > 0) { for(k = 7; k <= 7 + ((p + i)->buldge_concave_info[j][1]) - 1; k++) { Block[i].block[k][5] = 1; } } else if(((p + i)->buldge_concave_info[j][1]) < 0) { for(k = 6; k >= 6 + ((p + i)->buldge_concave_info[j][1]) + 1; k--) { Block[i].block[k][5] = 0; } } break; case 1: if(((p + i)->buldge_concave_info[j][0]) > 0) { for(k = 7; k <= 7 + ((p + i)->buldge_concave_info[j][0]) - 1; k++) { Block[i].block[4][k] = 1; } } else if(((p + i)->buldge_concave_info[j][0]) < 0) { for(k = 6; k >= 6 + ((p + i)->buldge_concave_info[j][0]) + 1; k--) { Block[i].block[4][k] = 0; } } if(((p + i)->buldge_concave_info[j][1]) > 0) { for(k = 7; k <= 7 + ((p + i)->buldge_concave_info[j][1]) - 1; k++) { Block[i].block[5][k] = 1; } } else if(((p + i)->buldge_concave_info[j][1]) < 0) { for(k = 6; k >= 6 + ((p + i)->buldge_concave_info[j][1]) + 1; k--) { Block[i].block[5][k] = 0; } } break; case 2: if(((p + i)->buldge_concave_info[j][0]) > 0) { for(k = 2; k >= 2 - ((p + i)->buldge_concave_info[j][0]) + 1; k--) { Block[i].block[k][4] = 1; } } else if(((p + i)->buldge_concave_info[j][0]) < 0) { for(k = 3; k <= 3 - ((p + i)->buldge_concave_info[j][0]) - 1; k++) { Block[i].block[k][4] = 0; } } if(((p + i)->buldge_concave_info[j][1]) > 0) { for(k = 2; k >= 2 - ((p + i)->buldge_concave_info[j][1]) + 1; k--) { Block[i].block[k][5] = 1; } } else if(((p + i)->buldge_concave_info[j][1]) < 0) { for(k = 3; k <= 3 - ((p + i)->buldge_concave_info[j][1]) - 1; k++) { Block[i].block[k][5] = 0; } } break; case 3: if(((p + i)->buldge_concave_info[j][0]) > 0) { for(k = 2; k >= 2 - ((p + i)->buldge_concave_info[j][0]) + 1; k--) { Block[i].block[4][k] = 1; } } else if(((p + i)->buldge_concave_info[j][0]) < 0) { for(k = 3; k <= 3 - ((p + i)->buldge_concave_info[j][0]) - 1; k++) { Block[i].block[4][k] = 0; } } if(((p + i)->buldge_concave_info[j][1]) > 0) { for(k = 2; k >= 2 - ((p + i)->buldge_concave_info[j][1]) + 1; k--) { Block[i].block[5][k] = 1; } } else if(((p + i)->buldge_concave_info[j][1]) < 0) { for(k = 3; k <= 3 - ((p + i)->buldge_concave_info[j][1]) - 1; k++) { Block[i].block[5][k] = 0; } } break; } } void solveForConcaveLength(struct _Buldge_concave_info *p, int i, int j) { int k, count0, count1; count0 = 0; count1 = 0; switch(j) { case 0: for(k = 5; k >= 3; k--) { if(Block[i].block[k][3] == 0 || Block[i].block[k][4] == 0 || Block[i].block[k][5] == 0) break; else count0++; } (p + i)->concave_len[j][0] = count0; for(k = 5; k >= 3; k--) { if(Block[i].block[k][4] == 0 || Block[i].block[k][5] == 0 || Block[i].block[k][6] == 0) break; else count1++; } (p + i)->concave_len[j][1] = count1; break; case 1: for(k = 5; k >= 3; k--) { if(Block[i].block[3][k] == 0 || Block[i].block[4][k] == 0 || Block[i].block[5][k] == 0) break; else count0++; } (p + i)->concave_len[j][0] = count0; for(k = 5; k >= 3; k--) { if(Block[i].block[4][k] == 0 || Block[i].block[5][k] == 0 || Block[i].block[6][k] == 0) break; else count1++; } (p + i)->concave_len[j][1] = count1; break; } } void processBlockBuffer(struct _Block_buffer *b, struct _Buldge_concave_info *p, int i) { int k; int min0[2]; if((((b + i)->block_buffer[0][0] >= 0) && ((b + i)->block_buffer[0][1] >= 0)) || (((b + i)->block_buffer[1][0] >= 0) && ((b + i)->block_buffer[1][1] >= 0))) //緩衝了個寂寞 { (p + i)->buldge_concave_info[2][0] = (b + i)->block_buffer[0][0]; (p + i)->buldge_concave_info[2][1] = (b + i)->block_buffer[0][1]; applyInfoToBlock(p, i, 2); (p + i - 4)->buldge_concave_info[0][0] = - ((b + i)->block_buffer[0][0]); (p + i - 4)->buldge_concave_info[0][1] = - ((b + i)->block_buffer[0][1]); applyInfoToBlock(p, i - 4, 0); } else//處理緩衝區 { //根據方塊緩衝區左邊兩個域的凹凸資訊求得方塊緩衝區上邊兩個域的凹凸資訊的最小值(直接到凹凸資訊,不使用凹陷度) if((b + i)->block_buffer[1][0] == -1 && (b + i)->block_buffer[1][1] == 0) { min0[0] = 0; min0[1] = -3; } else if(((b + i)->block_buffer[1][0] == -2 || (b + i)->block_buffer[1][0] == -3) && (b + i)->block_buffer[1][1] == 0) { min0[0] = 0; min0[1] = 0; } else if((b + i)->block_buffer[1][1] == -1 && (b + i)->block_buffer[1][0] == 0) { min0[0] = -1; min0[1] = -3; } else if(((b + i)->block_buffer[1][1] == -2 || (b + i)->block_buffer[1][1] == -3) && (b + i)->block_buffer[1][0] == 0) { min0[0] = -1; min0[1] = -1; } else if((b + i)->block_buffer[1][0] == -1 && (b + i)->block_buffer[1][1] == -1) { min0[0] = 0; min0[1] = -3; } else if(((b + i)->block_buffer[1][1] == -2 || (b + i)->block_buffer[1][1] == -3) && (b + i)->block_buffer[1][0] == -1) { min0[0] = 0; min0[1] = -1; } else { min0[0] == 0; min0[1] == 0; } //根據方塊緩衝區上邊兩個域的凹凸資訊的最小值修正上邊兩個域的凹凸資訊 for(k = 0; k < 2; k++) { if((b + i)->block_buffer[0][k] < 0) { if(min0[k] == -1) { (b + i)->block_buffer[0][k] = -1; } else if(min0[k] == 0) { (b + i)->block_buffer[0][k] = 0; } //對於min0[k] == -3的,是啥就是啥 } } //若處理結果是雙平,再處理 if(((b + i)->block_buffer[0][0] == 0) && ((b + i)->block_buffer[0][1] == 0)) { //自注:此時下面的if和else if同級,不存在先後問題 if(min0[0] < 0) { (b + i)->block_buffer[0][0] = -1; } else if(min0[1] < 0) { (b + i)->block_buffer[0][1] = -1; } else//沒辦法只能往緩衝塊的上源塊改,得獲取上源塊兩個域的凹陷度,全域性變數很方便 { //不隨機取上源塊域0還是域1了,直接if,else if if((p + i - 4)->concave_len[0][0] > 0) { (b + i)->block_buffer[0][0] = 1; } else if((p + i - 4)->concave_len[0][1] > 0) { (b + i)->block_buffer[0][1] = 1; } //上面這一對if, else if對上源塊方陣的值的改變不會使由上源塊左邊和上邊(如果有上邊兩個域的凹凸資訊的話)兩個域的凹凸資訊生成的上源塊方陣的相關值發生改變 else//兩個上源塊下邊兩個域的凹陷度均等於0,直接修改上源塊矩陣值。由於凹凸資訊是-1,後續用統一賦值applyInfoToBlock給該塊賦值恰好也到第5行結束 { Block[i - 4].block[5][4] = 1; Block[i - 4].block[5][5] = 1; Block[i - 4].block[5][6] = 1; (b + i)->block_buffer[0][1] = 1; //處理連鎖問題,即上源塊左邊和上邊(如果有上邊兩個域的凹凸資訊的話)兩個域的凹凸資訊生成的上源塊方陣的相關值可能發生改變 Block[i - 5].block[5][8] = 0; Block[i - 5].block[5][9] = 0; if((i >= 9 && i <= 11) || (i >= 13 && i <= 15)) { Block[i - 8].block[9][4] = 0; Block[i - 8].block[9][5] = 0; } } } } //將處理後的緩衝區凹凸資訊原封賦值給最終固定的 (p + i)->buldge_concave_info[2][0] = (b + i)->block_buffer[0][0]; (p + i)->buldge_concave_info[2][1] = (b + i)->block_buffer[0][1]; applyInfoToBlock(p, i, 2); (p + i - 4)->buldge_concave_info[0][0] = - ((b + i)->block_buffer[0][0]); (p + i - 4)->buldge_concave_info[0][1] = - ((b + i)->block_buffer[0][1]); applyInfoToBlock(p, i - 4, 0); } } void createAllBuldgeConcaveInfo() { struct _Buldge_concave_info *p; p = Buldge_concave_info; struct _Block_buffer *b; b = Block_buffer; int i, j, k;//16個塊,下左上右4個方向,每個方向2個值表示該方向的凹凸情況 for(i = 0; i < 16; i++) { for(j = 0; j < 4; j++) { for(k = 0; k < 2; k++) { (p + i)->buldge_concave_info[j][k] = 0; (p + i)->concave_len[j][k] = 3; } } } for(i = 0; i < 16; i++) { for(j = 0; j < 2; j++) { for(k = 0; k < 2; k++) (b + i)->block_buffer[j][k] = 0; } } //第一波 createBuldgeConcaveInfo(p, 0, 0);//d solveForConcaveLength(p, 0, 1); createBuldgeConcaveInfo(p, 0, 1);//r //第二波 solveForConcaveLength(p, 4, 1); createBuldgeConcaveInfo(p, 4, 1);//r solveForConcaveLength(p, 1, 0); createBuldgeConcaveInfo(p, 1, 0);//d solveForConcaveLength(p, 4, 0); createBuldgeConcaveInfo(p, 4, 0);//d solveForConcaveLength(p, 1, 1); createBuldgeConcaveInfo(p, 1, 1);//r //第三波 solveForConcaveLength(p, 8, 1); createBuldgeConcaveInfo(p, 8, 1);//r solveForConcaveLength(p, 5, 0); createBuldgeConcaveInfo(p, 5, 0);//d solveForConcaveLength(p, 5, 1); createBuldgeConcaveInfo(p, 5, 1);//r solveForConcaveLength(p, 2, 0); createBuldgeConcaveInfo(p, 2, 0);//d solveForConcaveLength(p, 8, 0); createBuldgeConcaveInfo(p, 8, 0);//d solveForConcaveLength(p, 2, 1); createBuldgeConcaveInfo(p, 2, 1);//r //第四波 solveForConcaveLength(p, 12, 1); createBuldgeConcaveInfo(p, 12, 1);//r solveForConcaveLength(p, 9, 0); createBuldgeConcaveInfo(p, 9, 0);//d solveForConcaveLength(p, 9, 1); createBuldgeConcaveInfo(p, 9, 1);//r solveForConcaveLength(p, 6, 0); createBuldgeConcaveInfo(p, 6, 0);//d solveForConcaveLength(p, 6, 1); createBuldgeConcaveInfo(p, 6, 1);//r solveForConcaveLength(p, 3, 0); createBuldgeConcaveInfo(p, 3, 0);//d //第五波 solveForConcaveLength(p, 13, 1); createBuldgeConcaveInfo(p, 13, 1);//r solveForConcaveLength(p, 10, 0); createBuldgeConcaveInfo(p, 10, 0);//d solveForConcaveLength(p, 10, 1); createBuldgeConcaveInfo(p, 10, 1);//r solveForConcaveLength(p, 7, 0); createBuldgeConcaveInfo(p, 7, 0);//d //第六波 solveForConcaveLength(p, 14, 1); createBuldgeConcaveInfo(p, 14, 1);//r solveForConcaveLength(p, 11, 0); createBuldgeConcaveInfo(p, 11, 0);//d } void initBlock() { int i, j, k; for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) { if(j >= 3 && j <= 6 && k >= 3 && k <= 6) Block[i].block[j][k] = 1; else Block[i].block[j][k] = 0; } } } createAllBuldgeConcaveInfo(); rotateForInit(); } int getRand(int min, int max) { int Rand; Rand = rand() % (max - min + 1) + min; return Rand; } int createLevel() { int i, j, k; FILE *fp; struct _Level new_level; initBlock();//不想再增加指標的數量,恰好Block為全域性變數 strcpy(new_level.level_name, getLocalTime()); strcpy(current_level_name, new_level.level_name); strcpy(new_level.creator, current_player_ID); for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) { new_level.level_block[i].block[j][k] = Block[i].block[j][k]; } } } if((fp = fopen("all_level.dat", "ab")) == NULL) { printf("拉取關卡庫失敗,即將返回上一級..."); return -1; } new_level.player_win_total = 0; fwrite(&new_level, sizeof(struct _Level), 1, fp); fclose(fp); return 1; } void rotateForInit() { int i, j, k, direction; struct _Block temp_block1, temp_block2; for(i = 0; i < 16; i++) { for(direction = 0; direction < 3; direction++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) { if(direction == 0) temp_block1.block[j][k] = Block[i].block[j][k]; else temp_block1.block[j][k] = temp_block2.block[j][k]; } } for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) temp_block2.block[j][k] = temp_block1.block[10 - k - 1][j]; } for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) Block[i].block[j][k] += (temp_block2.block[j][k]) * ((int)(pow(10, direction + 1))); } } } } void cpyBlockFromLevel(struct _Level *lp) { int i, j, k; for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) { Block[i].block[j][k] = lp->level_block[i].block[j][k]; } } } } struct _Block_node *createBlockNode() { struct _Block_node *node; if((node = (struct _Block_node*)malloc(sizeof(struct _Block_node))) == NULL) { system("cls"); printf(" 建立方塊顯示列表失敗,即將返回上一級... \n"); return NULL; } node->next = NULL; node->prev = NULL; return node; } struct _Block_node *createBlockList(int rand_sequence[]) { int j, k; struct _Block_node *new_node, *head, *rear; int cnt; for(cnt = 0; cnt < 16; cnt ++) { if((new_node = createBlockNode()) == NULL) return NULL; if(cnt == 0) { head = rear = new_node; head->next = head; } else { head->prev = new_node; new_node->next = head; rear->next = new_node; new_node->prev = rear; rear = new_node; } new_node->init_num = rand_sequence[cnt]; new_node->list_num = cnt + 1; new_node->color = getRandColor(); } return head; } void getRandSequence(int rand_sequence[]) { int tmp; int times = 1000; while(times--) { int a = getRand(0, 15); int b = getRand(0, 15); tmp = rand_sequence[a]; rand_sequence[a] = rand_sequence[b]; rand_sequence[b] = tmp; } } void randRotate(struct _Block_node *np) { int j, k; int pow1, pow2; int index = getRand(0, 3); pow1 = (int)(pow(10, index + 1)); pow2 = (int)(pow(10, index)); for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) np->node_block[j][k] = ((Block[np->init_num].block[j][k]) % pow1) / pow2; } np->direction_index = index; } int getRandColor() { int color = getRand(0, 5); switch(color) { case 0: color = 242; break; case 1: color = 245; break; case 2: color = 243; break; case 3: color = 249; break; case 4: color = 252; break; case 5: color = 246; break; } return color; } void playerRotate(struct _Block_node *np) { int j, k; int pow1, pow2; pow1 = (int)(pow(10, (np->direction_index) + 1)); pow2 = (int)(pow(10, np->direction_index)); for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) np->node_block[j][k] = ((Block[np->init_num].block[j][k]) % pow1) / pow2; } } void showNodeBlock(struct _Block_node *np) { int j, k; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), np->color); for(j = 0; j < 10; j++) { gotoxy(2, j + 2); for(k = 0; k < 10; k++) { if(np->node_block[j][k] == 1) printf("■"); else printf(" "); } } } struct _Block_node *deleteBlockNode(struct _Block_node *np, struct _Block_node *head) { struct _Block_node *pre, *tmp; tmp = np->next; if(tmp == np) { free(np); return NULL; } while(tmp != head) { (tmp->list_num)--; tmp = tmp->next; } pre = np->prev; pre->next = np->next; np->next->prev = pre; free(np); return pre->next; } void showListNum(struct _Block_node *np, int total) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(7, 12); if((np->list_num) < 10) { if(total < 10) printf("←0%d--0%d→", np->list_num, total); else printf("←0%d--%d→", np->list_num, total); } else printf("←%d--%d→", np->list_num, total); } void showReference(int direct, int top, int bottom, int leftmost, int rightmost, int buldge_info[]) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); switch(direct) { case 0: gotoxy(34, 14 + top + (3 - buldge_info[0]) + 1); printf("[]"); gotoxy(34, 14 + bottom - (buldge_info[1] - 6) + 1); printf("[]"); break; case 1: gotoxy(34, 14 + top + (3 - buldge_info[0]) - 1); printf("[]"); gotoxy(34, 14 + bottom - (buldge_info[1] - 6) - 1); printf("[]"); break; case 2: gotoxy(2 + 2 * (leftmost + (3 - buldge_info[2]) + 1), 30); printf("[]"); gotoxy(2 + 2 * (rightmost - (buldge_info[3] - 6) + 1), 30); printf("[]"); break; case 3: gotoxy(2 + 2 * (leftmost + (3 - buldge_info[2]) - 1), 30); printf("[]"); gotoxy(2 + 2 * (rightmost - (buldge_info[3] - 6) - 1), 30); printf("[]"); break; } gotoxy(34, 14 + top + (3 - buldge_info[0])); printf("●"); gotoxy(34, 14 + bottom - (buldge_info[1] - 6)); printf("●"); gotoxy(2 + 2 * (leftmost + (3 - buldge_info[2])), 30); printf("●"); gotoxy(2 + 2 * (rightmost - (buldge_info[3] - 6)), 30); printf("●"); } void showMovedBlock(int **min_block, int direct, int top, int bottom, int leftmost, int rightmost, int row, int col) { int i, j; switch(direct) { case 0: for(j = 0; j < col; j++) { gotoxy(2 + (leftmost + j) * 2, 14 + bottom + 1); if(color_map[bottom + 1][leftmost + j] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[bottom + 1][leftmost + j]); printf("■"); } else printf(" "); } break; case 1: for(j = 0; j < col; j++) { gotoxy(2 + (leftmost + j) * 2, 14 + top - 1); if(color_map[top - 1][leftmost + j] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[top - 1][leftmost + j]); printf("■"); } else printf(" "); } break; case 2: for(i = 0; i < row; i++) { gotoxy(2 + (rightmost + 1) * 2, 14 + top + i); if(color_map[top + i][rightmost + 1] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[top + i][rightmost + 1]); printf("■"); } else printf(" "); } break; case 3: for(i = 0; i < row; i++) { gotoxy(2 + (leftmost - 1) * 2, 14 + top + i); if(color_map[top + i][leftmost - 1] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[top + i][leftmost - 1]); printf("■"); } else printf(" "); } break; } for(i = 0; i < row; i++) { gotoxy(2 + leftmost * 2, 14 + top + i); for(j = 0; j < col; j++) { if(min_block[i][j] == 1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 247); printf("■"); } else if(color_map[top + i][leftmost + j] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[top + i][leftmost + j]); printf("■"); } else printf(" "); } } } int ifQuit(struct _Block_node *head) { int i, j; struct _Block_node *p; struct _Block_node *q; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(9, 13); printf("退出?是(y)或否(n)"); while(1) { choose = getch(); if(choose == 121) { p = head->next; while(p != head) { q = p; p = p->next; free(q); } free(head); for(i = 0; i < 16; i++) for(j = 0; j < 16; j++) color_map[i][j] = 0; return 1; } else if(choose == 110) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(9, 13); printf("][][][][][][][][]["); return 0; } } } int runLevel() { struct _Block_node *head, *np; struct _Level tmp_level; FILE *fp1, *fp2, *fp1_new; int rand_sequence[16] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int buldge_info[4]; int top, bottom, leftmost, rightmost, row, col; int **min_block; int i, j, cnt, cnt_br = 0, tm_cost, player_win_num; int doc_num, flag = 0; int forbid = 0, total = 16; time_t first,second; double sc, tm_score, br_score; char gr; fp1 = fp2 = NULL; if(if_first == 1) { if((fp2 = fopen(player_trace, "ab")) == NULL) { printf(" 拉取玩家資料失敗,即將返回上一級... \n"); return -1; } fwrite(current_level_name, sizeof(char), 30, fp2); fclose(fp2); } getRandSequence(rand_sequence); if((head = createBlockList(rand_sequence)) == NULL) return -1; np = head; initGameArea(); time(&first); while(1) { doc_num=getRand(0, 3); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); for (i = 6; i <= 11; i++) { gotoxy(24, i); printf(doc[doc_num].docLine[i-6]); } //瀏覽方塊列表 while(1) { if(forbid == 0) { randRotate(np); showNodeBlock(np); showListNum(np, total); } choose = getch(); switch(choose) { case -32: switch(choose = getch()) { case 75: np = np->prev; cnt_br++; forbid = 0; break; case 77: np = np->next; cnt_br++; forbid = 0; break; default: forbid = 1; } break; case 113: if(ifQuit(head) == 1) menu(); else forbid = 1; break; default: forbid = 1; } if(choose == 32) break; } gotoxy(7, 12); printf("][][][][]["); gotoxy(11, 12); printf("↑"); //玩家旋轉 while(1) { choose = getch(); switch(choose) { case -32: switch(choose = getch()) { case 72: (np->direction_index)++; if(np->direction_index == 4) np->direction_index = 0; playerRotate(np); showNodeBlock(np); break; } break; case 113: if(ifQuit(head) == 1) menu(); break; } if(choose == 32) break; } SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(7, 12); printf(" ↑↓←→ "); //移動方塊準備工作 //獲取方塊最大凸值 getBuldgeInfo(buldge_info, np); top = 0; bottom = buldge_info[1] - buldge_info[0]; leftmost = 0; rightmost = buldge_info[3] - buldge_info[2]; row = bottom - top + 1; col = rightmost - leftmost + 1; //獲取最小有效方塊 min_block = (int**)malloc(sizeof(int*) * row); for(i = 0; i < row; i++) *(min_block + i) = (int*)malloc(sizeof(int) * col); for(i = 0; i < row; i++) { for(j = 0; j < col; j++) min_block[i][j] = np->node_block[buldge_info[0] + i][buldge_info[2] + j]; } //臨時列印當前選擇的方塊,不覆蓋方塊空白區域對應的地圖顏色 for(i = 0; i < row; i++) { gotoxy(2, 14 + i); for(j = 0; j < col; j++) { if(min_block[i][j] == 1) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 247); printf("■"); } else if(color_map[i][j] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[i][j]); printf("■"); } else printf(" "); } } //列印參考點 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(34, 14 + top + (3 - buldge_info[0])); printf("●"); gotoxy(34, 14 + bottom - (buldge_info[1] - 6)); printf("●"); gotoxy(2 + 2 * (leftmost + (3 - buldge_info[2])), 30); printf("●"); gotoxy(2 + 2 * (rightmost - (buldge_info[3] - 6)), 30); printf("●"); //移動塊 while(1) { choose = getch(); switch(choose) { case -32: switch(choose = getch()) { case 72: if(top != 0) { top--; bottom--; showMovedBlock(min_block, 0, top, bottom, leftmost, rightmost, row, col); showReference(0, top, bottom, leftmost, rightmost, buldge_info); } break; case 80: if(bottom != 15) { top++; bottom++; showMovedBlock(min_block, 1, top, bottom, leftmost, rightmost, row, col); showReference(1, top, bottom, leftmost, rightmost, buldge_info); } break; case 75: if(leftmost != 0) { leftmost--; rightmost--; showMovedBlock(min_block, 2, top, bottom, leftmost, rightmost, row, col); showReference(2, top, bottom, leftmost, rightmost, buldge_info); } break; case 77: if(rightmost != 15) { leftmost++; rightmost++; showMovedBlock(min_block, 3, top, bottom, leftmost, rightmost, row, col); showReference(3, top, bottom, leftmost, rightmost, buldge_info); } break; } break; case 113: if(ifQuit(head) == 1) { for(i = 0; i < row; i++) free(*(min_block + i)); free(min_block); menu(); } break; } if(choose == 32) { cnt = 0; for(i = 0; i < row; i++) { for(j = 0; j < col; j++) { if(min_block[i][j] != 0) { if(color_map[top + i][leftmost + j] != 0) break; else cnt++; } else cnt++; } if(j == 0) break; else if(cnt % col != 0) break; } if(cnt == row * col) { for(i = 0; i < row; i++) { gotoxy(2 + 2 * leftmost, 14 + top + i); for(j = 0; j < col; j++) { if(color_map[top + i][leftmost + j] != 0) { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), color_map[top + i][leftmost + j]); printf("■"); } else if(min_block[i][j] != 0) { color_map[top + i][leftmost + j] = np->color; SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), np->color); printf("■"); } else printf(" "); } } SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | FOREGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(34, 14 + top + (3 - buldge_info[0])); printf("[]"); gotoxy(34, 14 + bottom - (buldge_info[1] - 6)); printf("[]"); gotoxy(2 + 2 * (leftmost + (3 - buldge_info[2])), 30); printf("[]"); gotoxy(2 + 2 * (rightmost - (buldge_info[3] - 6)), 30); printf("[]"); break; } else continue; } } for(i = 0; i < row; i++) free(*(min_block + i)); free(min_block); //放完了後 np = deleteBlockNode(np, head); if(np == NULL) { time(&second); tm_cost = (int)difftime(second,first); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 255); gotoxy(7, 12); printf("][][][][]["); for(i = 0; i < 10; i++){ gotoxy(2, 2 + i); for(j = 0; j < 10; j++) printf(" "); } SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); gotoxy(10, 4); printf("恭喜!"); gotoxy(8, 5); printf("您通關了。"); gotoxy(4, 6); printf("用時:%2d分%2d秒", tm_cost / 60, tm_cost % 60); gotoxy(2, 7); printf("瀏覽方塊移動次數:%d", cnt_br); if(tm_cost <= 180) tm_score = 100; else if(tm_cost > 300) tm_score = 60; else tm_score = - 1 / 3.0 * (double)tm_cost + 160.0; if(cnt_br <= 16) br_score = 100; else if(cnt_br > 50) br_score = 60; else br_score = - 20 / 17.0 * (double)cnt_br + 2020 / 17.0; sc = (tm_score + br_score * 2) / 3.0; gotoxy(6, 8); printf("分數:%.2lf", sc); if(sc >= 95) gr = 'S'; else if(sc >= 85) gr = 'A'; else if(sc >= 70) gr = 'B'; else gr = 'C'; gotoxy(8, 9); printf("等級:%c", gr); break; } //大費周折才寫出了“if...head = np”這兩行 else if(np->list_num == 1) head = np; total--; forbid = 0; } //memset(color_map, 0, 16 * sizeof(int));//memset不好使,編譯不報錯 for(i = 0; i < 16; i++) for(j = 0; j < 16; j++) color_map[i][j] = 0; //錄入有效記錄 if(if_first == 1 && if_full == 0) { fp1 = fopen("all_level.dat", "rb"); fp1_new = fopen("new_all_level.out", "wb"); if(fp1 == NULL || fp1_new == NULL) { gotoxy(0, 21); printf("抱歉,儲存有效成績失敗,按任意鍵繼續"); getch(); gotoxy(0, 22); printf("即將返回上一級..."); return -1; } while(1) { fread(&tmp_level, sizeof(struct _Level), 1, fp1); if(feof(fp1)) break; if(strcmp(tmp_level.level_name, current_level_name) == 0) { player_win_num = tmp_level.player_win_total; tmp_level.player_win_total += 1; strcpy(tmp_level.level_player_win[player_win_num].player_win_ID, current_player_ID); tmp_level.level_player_win[player_win_num].time_cost = tm_cost; tmp_level.level_player_win[player_win_num].cnt_browse = cnt_br; tmp_level.level_player_win[player_win_num].score = sc; tmp_level.level_player_win[player_win_num].grade = gr; } fwrite(&tmp_level, sizeof(struct _Level), 1, fp1_new); } fclose(fp1); fclose(fp1_new); remove("all_level.dat"); rename("new_all_level.out", "all_level.dat"); } gotoxy(5, 12); printf("按任意鍵繼續.."); getch(); return 1; } void getBuldgeInfo(int buldge_info[], struct _Block_node *np) { int i, j, k, cnt = 0; for(i = 0; i < 4; i++) { for(j = 3; j < 7; j++) { if((np->node_block[i][j]) == 1) break; else cnt++; } if(cnt != 4) { cnt = 0; break; } cnt = 0; } buldge_info[0] = i; for(i = 9; i > 5; i--) { for(j = 3; j < 7; j++) { if((np->node_block[i][j]) == 1) break; else cnt++; } if(cnt != 4) { cnt = 0; break; } cnt = 0; } buldge_info[1] = i; for(j = 0; j < 4; j++) { for(i = 3; i < 7; i++) { if((np->node_block[i][j]) == 1) break; else cnt++; } if(cnt != 4) { cnt = 0; break; } cnt = 0; } buldge_info[2] = j; for(j = 9; j > 5; j--) { for(i = 3; i < 7; i++) { if((np->node_block[i][j]) == 1) break; else cnt++; } if(cnt != 4) { cnt = 0; break; } cnt = 0; } buldge_info[3] = j; } int ifPlain() { int tmp = getRand(0, 4); if(tmp < 2) return 1;//有平的 else return 0;//沒平的 } int getRandLength(int max_len) { int tmp; switch(max_len) { case 3: tmp = getRand(0, 8); if(tmp >= 0 && tmp <= 3) return 1; if(tmp >= 4 && tmp <= 6) return 2; if(tmp >= 7 && tmp <= 8) return 3; case 2: tmp = getRand(0, 6); if(tmp >= 0 && tmp <= 3) return 1; if(tmp >= 4 && tmp <= 6) return 2; case 1: return 1; } } int ifTwoSides() { int tmp = getRand(0, 2); if(tmp == 0 || tmp ==1) return 0; else return 1; } void preventDouble3()//若凹凸資訊絕對值都為3,重來 { while(info_tag0 == info_tag1 && (info_tag0 == 3 || info_tag0 == -3)) { info_tag0 = getRandLength(3); info_tag1 = getRandLength(3); } } char *getLocalTime() { char local_time[30]; char *p; int tag = 0; time_t ptime; time(&ptime); strcpy(local_time, ctime(&ptime)); p = local_time; while(local_time[tag] != ' ') { tag++; p++; } while(local_time[tag] != '\n') tag++; local_time[tag] = '\0'; p++; return p; } void printLogo() { int i, j; sleep(1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY| FOREGROUND_INTENSITY | FOREGROUND_RED | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); for(i = 5; i <= 8; i++) { gotoxy(17, i); for(j = 0; j <= 2; j++) { if(logo[i - 5][j] == '1') printf("■"); else printf(" "); } printf("\n"); } sleep(1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY| FOREGROUND_INTENSITY | FOREGROUND_BLUE | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); for(i = 8; i <= 10; i++) { gotoxy(17, i); for(j = 0; j <= 3; j++) { if(logo[i - 4][j] == '1') printf("■"); else gotoxy(17 + (j + 1) * 2, i); } printf("\n"); } sleep(1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY| FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); for(i = 7; i <= 10; i++) { gotoxy(23, i); for(j = 0; j <= 2; j++) { if(logo[i][j] == '1') printf("■"); else gotoxy(23 + (j + 1) * 2, i); } printf("\n"); } sleep(1); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY| FOREGROUND_INTENSITY | FOREGROUND_GREEN | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); for(i = 5; i <= 7; i++) { gotoxy(21, i); for(j = 0; j <= 3; j++) { if(logo[i + 6][j] == '1') printf("■"); else gotoxy(21 + (j + 1) * 2, i); } printf("\n"); } sleep(1); } void printMenuPage() { printf("****************平面榫卯拼拼看****************\n"); printf("****************Mortise & Tenon***************\n"); printf("****** 我的遊戲(m) ******\n"); printf("****** 全部關卡(l) ******\n"); printf("****** 幫助(h) ******\n"); printf("****** 關於(a) ******\n"); printf("****** 退出(q) ******\n"); } void printHelpPage() { printf("****************************************幫助****************************************\n"); printf(" 1.基本流程 \n"); printf(" 開始遊戲後, \n"); printf("選擇塊(←→),確認(空格),旋轉(↑),再確認(空格),移動塊(↑↓←→),確認位置(空格)\n"); printf(" 重複以上操作,直至成功將所有塊放置於遊戲區域內 \n"); printf(" 塊一旦被成功放置,其位置將不能被更改,請謹慎操作 \n"); printf(" 提示:您完成某關卡的有效記錄機會只有一次,為第一次您執行該關卡時 \n"); printf(" \n"); printf(" 2.其他 \n"); printf(" 您可在任意時間退出遊戲(q),一旦退出,您的遊戲進度不會被儲存 \n"); printf(" 用時越短,瀏覽方塊列表的移動次數越少,得分越高 \n"); printf(" 完成某關卡的用時得分和瀏覽方塊列表的移動次數得分會以二比三開加權給總得分 \n"); printf("************************************************************************************\n"); printf("****** 返回主選單(b) ******\n"); } void printAboutPage() { printf("*********************關於*********************\n"); printf("在B站上看到用C語言寫的膝上型電腦(自行搜尋),\n"); printf(" 受到了啟發,想做一個拼圖小遊戲。 \n"); printf(" 磨嘰一個多月做成了,很高興。 \n"); printf(" 也祝您玩得開心。 \n"); printf(" <鳴謝> \n"); printf(" @(GitHub)winter-master \n"); printf("**********************************************\n"); printf("****** 返回主選單(b) ******\n"); } void printMyGamePage() { printf("*******************我的遊戲*******************\n"); printf("****** 新建遊戲(n) ******\n"); printf("****** 歷史記錄(h) ******\n"); printf("**********************************************\n"); printf("****** 返回主選單(b) ******\n"); } int main() { srand((unsigned)time(NULL)); hideCursor(); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE); system("mode con cols=46 lines=16"); system("cls"); printLogo(); menu(); return 0; }
外掛:
//外掛。輸入“全部關卡”中的序號,檢視答案。無效輸入會出錯 #include <conio.h> #include <stdio.h> #include <stdlib.h> #include <windows.h> struct _Block{ int block[10][10]; }Block[16]; struct _Player_win{ char player_win_ID[10]; int time_cost; int cnt_browse; double score; char grade; }; struct _Level{ char level_name[30]; struct _Block level_block[16]; struct _Player_win level_player_win[5]; char creator[30]; int player_win_total; }; void cpyFirstDigit(struct _Level *lp); void printBlockForShow(); void gotoxy(int x, int y); int main(void) { struct _Level* lp; struct _Level tmp_level; FILE *fp; int cnt = 0; int length = 3; int i, j, k, chosen; fp = fopen("all_level.dat", "rb"); lp = (struct _Level*)malloc(sizeof(struct _Level) * length); while(1) { fread(&tmp_level, sizeof(struct _Level), 1, fp); if(feof(fp)) break; cnt++; if(cnt >= length) lp = (struct _Level*)realloc(lp, sizeof(struct _Level) * (++length)); for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) (lp + cnt - 1)->level_block[i].block[j][k] = tmp_level.level_block[i].block[j][k]; } } } fclose(fp); scanf("%d", &chosen); cpyFirstDigit(lp + chosen); free(lp); printBlockForShow(); return 0; } void cpyFirstDigit(struct _Level *lp) { int i, j, k; for(i = 0; i < 16; i++) { for(j = 0; j < 10; j++) { for(k = 0; k < 10; k++) { Block[i].block[j][k] = lp->level_block[i].block[j][k] % 10; } } } } void printBlockForShow() { int i, j, k; system("cls"); SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), 245); system("mode con cols=100 lines=100"); for(i = 0; i < 16; i++) { for(j = (i / 4) * 10; j < (i / 4) * 10 + 10; j++) { gotoxy((i % 4) * 20, j); for(k = 0; k < 10; k++) { if(Block[i].block[j - (i / 4) * 10][k] == 1) { printf("■"); } else { printf(" "); } } } } getch(); } void gotoxy(int x, int y) { HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE); COORD pos; pos.X = x; pos.Y = y; SetConsoleCursorPosition(handle, pos); }