首页 > 编程语言 > 详细

C语言写的榫卯拼图游戏

时间:2021-07-18 23:22:52      阅读:40      评论:0      收藏:0      [点我收藏+]

作者的话:

  简单命令的有趣应用。不会拿别的写游戏,但又想写,就有了此程序。
  本玩具代码没有删除关卡的功能。您一个人玩(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);
}

 

C语言写的榫卯拼图游戏

原文:https://www.cnblogs.com/Quangonglv/p/15027670.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!