kurongbudeng 2021-06-30 20:32 采纳率: 100%
浏览 20
已采纳

课上碰到的题 要交了不太能写出来能不能参考一下

img 如题初学碰上的题 怎么写出提示 请把源代码直接甩我脸上求求

  • 写回答

2条回答 默认 最新

  • CSDN专家-微编程 2021-06-30 20:45
    关注

    如果对你有帮助记得采纳一下谢谢~

    参考代码如下

    #include<stdio.h>
    #include<stdlib.h>
    #include<memory.h>
    #include<math.h>
    #include<time.h>
    #include <windows.h>
    #include<string.h>
    #define MAX 999
    
    struct Node{
    Node *up,*down,*left,*right,*colPtr,*rowPtr;//指向row,col对应的行对象和列对象
    int row_num;//记录行数,行专属(从1开始)
    int col_elemCount;//记录该列元素个数,列专属
    };
    
    struct player{//玩家信息结点
    int m ;
    int s ;
    char name[20];
    int level ;
    player* next;
    };
    
    
    int row_size=593;//行数
    int col_size = 324;//列数
    int result[81];//存放结果行的栈
    int index = 0;//栈指针
    int sudoku[81] = {0};//存放数独
    int time_start = 0;
    int time_end = 0;//起始时间
    
    void init(Node* head){
    
        head->left = head;
        head->right = head;
        head->up = head;
        head->down = head;
    
        for(int k = 0;k < row_size;k++){//创建行对象(头插)
            Node* newNode = (Node*)malloc(sizeof(Node));
            newNode->up = head;
            newNode->down = head->down;
            newNode->left = newNode;
            newNode->right = newNode;
            newNode->down->up = newNode;
            head->down = newNode;
            newNode->row_num = row_size-k;
            newNode->col_elemCount = 0;//借用,作为标志
        }
    }
    void init_col(Node* head){
        /************初始化行列对象*******************/
        for(int j = 0;j < col_size;j++){//创建列对象(头插)
            Node* newNode = (Node*)malloc(sizeof(Node));
            newNode->right = head->right;
            newNode->left = head;
            newNode->down = newNode;
            newNode->up = newNode;
            newNode->right->left = newNode;
            head->right = newNode;
            newNode->col_elemCount = 0;//列元素个数初始为0
        }
    }
    
    void link(Node* head,int** matrix){
    /***********插入结点*************/
    Node *current_row, *current_col, *current;//当前行对象,当前列对象,当前节点
    current_row = head;
    for(int row = 0;row<row_size;row++){
        current_row = current_row->down;
        current_col = head;
        for(int col = 0;col<col_size;col++){
            current_col = current_col->right;
            if(matrix[row][col] == 0)
                continue;
    
            /*****插入结点,结点的行和列都用尾插法来与行列对象链接*****/
            Node* newNode = (Node*)malloc(sizeof(Node));
            newNode->colPtr = current_col;//设置节点对应的行和列
            newNode->rowPtr = current_row;
            /**********列尾插************/
            newNode->down = current_col;
            newNode->up = current_col->up;
            newNode->up->down = newNode;
            current_col->up = newNode;//链接当前节点到列双向链尾端
    
            if(current_row->col_elemCount == 0){//行的这个为0,说明该行还没有元素,行双向链表不把行对象包含进来(便于后面覆盖)
                current_row->right = newNode;
                newNode->left = newNode;
                newNode->right = newNode;
                current_row->col_elemCount++;//此为标志,为了不把行对象包含进来
            }
    
            current = current_row->right;
            newNode->left = current->left;
            /**********行尾插************/
            newNode->right = current;
            newNode->left->right = newNode;
            current->left = newNode;//链接当前节点到行双向链尾端
    
            current_col->col_elemCount++;//该列元素加1
            }
        }    
    }
    
    int** create_matrix()//将数独转换为01矩阵
    {
        int** matrix = (int**)malloc(row_size*sizeof(int*));//申请二维数组空间
    
        for(int m=0;m<row_size;m++)
            matrix[m] = (int*)malloc(col_size*sizeof(int));
    
        for(int r=0;r<row_size;r++)
            for(int c=0;c<col_size;c++)
                matrix[r][c] = 0;//初始化
       
        int i = 0;
        for (int x = 0; x < 81; x++){
            int val = sudoku[x];
            if (val != 0){//有值则插入一行
                matrix[i][x] = 1;
                matrix[i][81 + x/9*9 + val -1] = 1;
                matrix[i][162 + x%9*9 + val -1] = 1;
                matrix[i][243 + (x/9/3*3+x%9/3)*9 +val -1] = 1;
                i++;
    
                continue;
            }
    
            for (int j = 0; j < 9; j++){//没值则插入9行(1~9)
                matrix[i][x] = 1;
                matrix[i][81 + x/9*9 + j] = 1;
                matrix[i][162 + x%9*9 +j] = 1;
                matrix[i][243 + (x/9/3*3+x%9/3)*9 +j] = 1;
                i++;
            }
        }
    
        return matrix;
    }
    
    void cover(Node* cRoot){//覆盖
        cRoot->left->right = cRoot->right;
        cRoot->right->left = cRoot->left;//删除该列对象,及该列结点的每行结点
        Node *i, *j;
        i = cRoot->down;
        while (i != cRoot)
        {
            j = i->right;
            while (j != i)
            {
                j->down->up = j->up;
                j->up->down = j->down;
                j->colPtr->col_elemCount--;
                j = j->right;
            }
            i = i->down;
        }
    }
    
    void recover(Node* cRoot){//回溯
    Node *i, *j;
        i = cRoot->up;
        while (i != cRoot)
        {
            j = i->left;
            while (j != i)
            {
                j->colPtr->col_elemCount++;
                j->down->up = j;
                j->up->down = j;
                j = j->left;
            }
            i = i->up;
        }
        cRoot->right->left = cRoot;
        cRoot->left->right = cRoot;
    
    }
    
    bool search(Node* head){
        if(head->right == head){
            return true;
        }
        Node *cRoot, *c;
        int minSize = MAX;//最少列元素个数
        for(c = head->right; c != head; c = c->right)//先选择列元素最少的列对象(提高效率)
        {
            if (c->col_elemCount < minSize)
            {
                minSize = c->col_elemCount;
                cRoot = c;
                if (minSize == 1)//1是最小
                    break;
                if (minSize == 0)//有一列为空,失败
                    return false;
            }
        }
        cover(cRoot);
        Node *current_row,*current;
        for (current_row = cRoot->down; current_row != cRoot; current_row = current_row->down)
        {
            result[index]=current_row->rowPtr->row_num;//将该行加入result中(行数)
            index++;
    
            for (current = current_row->right; current != current_row; current = current->right)
            {
                cover(current->colPtr);
            }
            if (search(head))//递归
                return true;
            for (current = current_row->left; current != current_row; current = current->left)
                recover(current->colPtr);
            index--;//发现该行不符合要求,出栈
    
        }
        recover(cRoot);
        return false;
    }
    
    int* to_sudoku(int** matrix){//01矩阵转化为数独
        int* done = (int*)malloc(81*sizeof(int));
        int temp[162]={0};
    
    for(int i = 0;i<81;i++){
    
        for(int j = 0;j<162;j++)
            temp[j] = matrix[result[i]-1][j];
        
        int pos = 0,val = 0;
    
        for(int k = 0;k<81;k++){
            if(temp[k] == 1)
                break;
            pos++;
        }
    
        for(int m = 81;m<162;m++){
            if(temp[m] == 1)
                break;
            val++;
        }
        done[pos]=val%9+1;
    
    }
    
        return done;
    }
    
    void print(int* answer){//打印数独
    printf("┏━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┳━━┓\n");
        for(int i = 0;i<81;i++){
            if(answer[i]==0)
                printf("┃  ");
            else
                printf("┃ %d",answer[i]);
            if(i==80){
                printf("┃  ");
                printf("\n");
                printf("┗━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┻━━┛\n");
            }
            else if((i+1)%9==0){
                    printf("┃  ");
                    printf("\n");
                    printf("┣━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━╋━━┫\n");
            }
        }
    }
    
    
    bool isRight(int* flag,int x,int y,int val){//判断填入的数是否合法
        for(int i = 0;i<324;i++)
            if(flag[(x-1)*9+(y-1)] == 0 &&
            flag[81+(x-1)*9 + val -1] == 0 &&
            flag[162+(y-1)*9 + val -1] == 0 &&
            flag[243+((x-1)/3*3 + (y-1)/3+1)*9 +val -1] == 0 )
                return true;
    return false;
    }
    
    void create_sudoku(){
        for(int j = 0;j<81;j++)
            sudoku[j] = 0;//初始化
        int flag[324]={0};
        int x,y,val;//行号、列号、值
    
        int i=0;
        while(i<17){//一个数独中有17个数及以上时有唯一解
            x = rand()%9+1;
            y = rand()%9+1;
            val = rand()%9+1;
            if(isRight(flag,x,y,val)){
                i++;
                sudoku[(x-1)*9+(y-1)]=val;
                flag[(x-1)*9+(y-1)] = 1;
                flag[81+(x-1)*9 + val -1] = 1;
                flag[162+(y-1)*9 + val -1] = 1;
                flag[243+((x-1)/3*3 + (y-1)/3+1)*9 +val -1] = 1;
            }
        }
    }
    
    void sudoku_level(int* answer,int count){//难度
        int x,y;//行号、列号
        int num=0;
        srand(time(NULL));
        for(int i = 0;i<81;i++)
            sudoku[i] = answer[i];
        while(num<(81-count)){//挖空
            x = rand()%9+1;
            y = rand()%9+1;
            if(sudoku[(x-1)*9+(y-1)] != 0){
                sudoku[(x-1)*9+(y-1)] = 0;
                num++;
            }
        }
    }
    
    bool receiver(int* player_res){//接收玩家答案
        for(int i=0;i<81;i++){
            scanf("%d",&player_res[i]);
            if(!(player_res[i]>=1&&player_res[i]<=9)){//0 表示玩家放弃
                fflush(stdin);
                return false;
            }
        }
        return true;
    }
    
    int get_time(){//获得当前时间秒
        time_t t;
        t=time(NULL);
        return t;
    }
    
    void ready(){
        print(sudoku);
        printf("你有5秒钟观察时间\n");
        for(int i = 0;i<5;i++){
            printf("●    ");
            Sleep(1000);
        }
        printf("\n");
        printf("观察结束,计时开始,请开始作答。(输入除1~9外,视为放弃作答)\n");
        printf("==========================================================================\n");
    }
    
    bool judge(int* player_res,int* answer){//判断玩家答案
        for(int i = 0;i<81;i++)
            if(player_res[i] != answer[i])
                return false;
    return true;
    }
    
    void record(player info){//记录
        FILE* fp;
        int M = MAX,S = MAX,LEVEL = MAX;
        char NAME[20];
        char remove[100] = {"                                                      "};//用于记录长度固定化,方便更新记录
        //通过这种方法,可以直接在一个文件中更新数据,不必要全篇读—改—写,直接修改一行
        int c = 0;
        if((fp = fopen("record.txt","r+"))==NULL){//文件在cpp同目录下
            printf("文件不存在,保存失败!");//虽然会自动生成文件,but以防万一
            return;
        }
        setbuf(fp,NULL);//设置缓冲区
        rewind(fp);
        c = ftell(fp);//记录当前行的开头指针位置
    
        while(fscanf(fp,"%s %d:%d %d",NAME,&M,&S,&LEVEL) != EOF){
    
            if(!strcmp(NAME,info.name) && LEVEL == info.level){//strcmp比较相同返回0
                
                if(info.m<M || (info.m==M&&info.s<S)){//如果是新纪录,则更新
                    fseek(fp,c,SEEK_SET);
                    fputs(remove,fp);//覆盖旧记录
                    fseek(fp,c,SEEK_SET);//回到该记录的开头位置
                    fprintf(fp,"%s %d:%d %d",info.name,info.m,info.s,info.level);//写入文件
                    fflush(fp);//清除缓冲区
                    return;
                }
                return;//不是新纪录就不插入
            }
            fscanf(fp,"\n");//读取换行
            c = ftell(fp);
        }
    
        fputs(remove,fp);//先覆盖固定长度的区域
        fseek(fp,c,SEEK_SET);//回到覆盖的区域首部
        fprintf(fp,"%s %d:%d %d",info.name,info.m,info.s,info.level);//在覆盖的区域内插入记录
        fseek(fp,0,SEEK_END);//指向尾部
        fprintf(fp,"\n");//插入换行符
        fclose(fp);
    }
    
    
    player* get_record(int level){//返回玩家记录的单向链表头结点
        FILE* fp;
        int M = MAX,S = MAX,LEVEL = MAX;
        char NAME[20];
        player* head = (player*)malloc(sizeof(player));
        head->next = NULL;
        if((fp = fopen("record.txt","r"))==NULL){
            printf("文件不存在!");
            system("pause");
            exit(1);
        }
        setbuf(fp,NULL);//设置缓冲区
        rewind(fp);
        while(fscanf(fp,"%s %d:%d %d",NAME,&M,&S,&LEVEL) != EOF){
            if(LEVEL == level){
                player* p = (player*)malloc(sizeof(player));//采用链表
                strcpy(p->name,NAME);
                p->m = M;
                p->s = S;
                p->next = head ->next;
                head->next = p;
            }    
        }
    fclose(fp);
    return head;
    }
    
    void order(player* head){//单链表排序
    player* p;
    player* q;
    int temp1;
    int temp2;
    char temp3[20];
    for(p = head->next;p != NULL;p = p->next)
        for(q = p->next;q != NULL;q = q->next)
            if(p->m>q->m||(p->m==q->m&&p->s>q->s)){//对换两个结点的内容
                temp1 = p->m;
                temp2 = p->s;
                strcpy(temp3,p->name);
                p->m = q->m;
                p->s = q->s;
                strcpy(p->name,q->name);
                q->m = temp1;
                q->s = temp2;
                strcpy(q->name,temp3);
            }
    
    }
    
    void show(player* easy,player* normal,player* hard){//输出排行
        int no=1;
        player* p1 = easy->next;
        player* p2 = normal->next;
        player* p3 = hard->next;
    printf("==========================================================================\n");
        printf("\t\t   简单\t\t\t  一般\t\t\t   容易\n");
        while(p1 != NULL || p2 != NULL || p3 != NULL){
            printf("NO.%d",no++);
            if(p1 != NULL){
                printf("\t\t%s\t%d:%d\t",p1->name,p1->m,p1->s);
                p1 = p1->next;
            }
            if(p2 != NULL){
                printf("\t%s\t%d:%d\t",p2->name,p2->m,p2->s);
                p2 = p2->next;
            }
            if(p3 != NULL){
                printf("\t%s\t%d:%d\t",p3->name,p3->m,p3->s);
                p3 = p3->next;
            }
            printf("\n");
        }
    }
    
    void re_init(Node* head){//重新初始化行和列对象
    Node* p;
    for(p = head->down;p!=head;p=p->down)
        p->col_elemCount = 0;
    
    if(head->right == head){//如果有解,则列对象会在search中被删除,需要重新链接列对象
        init_col(head);
        return;
        }
    
    for(p = head->right;p!=head;p=p->right){//无解时,则恢复列对象
        p->col_elemCount = 0;
        p->down = p;
        p->up = p;
        }
    }
    
    void main(){
    int player_res[81]={0};
    int choice;
    int** matrix;//存放数独的01矩阵
    int* answer;//存放答案
    player* easy;//容易难度排行
    player* normal;//简单难度排行
    player* hard;//困难难度排行
    player info ;//玩家信息
    
    Node* head =(Node*)malloc(sizeof(Node));
    init(head);init_col(head);//初始化行列对象,建立十字双向循环链表
    srand(time(NULL));
    bool flag = false;//有无解
    while(true){
    
        while(!flag){
            flag=true;
    
            create_sudoku();//创建17个数的数独(17个数及以上唯一解)
    
            matrix = create_matrix();//得到该数独的01矩阵
    
            link(head,matrix);//将01矩阵转化为十字双向循环链表(转化为精准覆盖问题)
    
            if(!search(head))//得到答案行(result)
                flag = false;//如果不幸无解,则重新构建数独(经本人测试,无解的概率大概为1/1000)
            index = 0;//初始化result栈
            
            re_init(head);//重新初始化十字链表
        }
    
    flag = false;
    answer = to_sudoku(matrix);//得到答案
    
    
    printf("                               数独\n");
    printf("==========================================================================\n\n");
    printf("1.开始游戏\n");
    printf("2.查看排名\n");
    printf("3.退出\n\n");
    printf("==========================================================================\n");
    printf("请选择:");
    scanf("%d",&choice);
    switch(choice){
    case 1:
            int option;
            printf("玩家名:");
            scanf("%s",&info.name);
            if(strlen(info.name)>20){
                printf("名字太长!\n");
                break;
            }
            printf("请选择游戏难度:  1.简单\t2.一般\t3.困难\n");
            scanf("%d",&option);
            printf("\n");
            switch(option){
            case 1:
                sudoku_level(answer,81);//挖空答案
                ready();
                time_start = get_time();
                if(!receiver(player_res)){
                    printf("\n您已放弃作答!\t正确答案为:\n\n");
                    print(answer);
                    break;
                }
                time_end = get_time();
                info.m = (time_end-time_start)/60;
                info.s = (time_end-time_start)%60;
                info.level = 1;
            
                if(judge(player_res,answer)){
                    printf("回答正确!\t用时:  %d:%d\n",info.m,info.s);
                    record(info);
                }
                else {
                    printf("\n回答错误!\t正确答案为:\n\n");
                    fflush(stdin);
                    print(answer);
                }
                break;
            case 2:
                sudoku_level(answer,35);
                time_start = get_time();
                ready();
                if(!receiver(player_res)){
                    printf("\n您已放弃作答!\t正确答案为:\n\n");
                    print(answer);
                    break;
                }
                time_end = get_time();
                info.m = (time_end-time_start)/60;
                info.s = (time_end-time_start)%60;
                info.level = 2;
                if(judge(player_res,answer)){
                    printf("回答正确!\t用时:  %d:%d\n",info.m,info.s);
                    record(info);
                }
                else {
                    printf("回答错误!\t正确答案为:\n\n");
                    fflush(stdin);
                    print(answer);
                }
                break;
            case 3:
                sudoku_level(answer,30);
                time_start = get_time();
                ready();
                if(!receiver(player_res)){
                    printf("\n您已放弃作答!\t正确答案为:\n\n");
                    print(answer);
                    break;
                }
                time_end = get_time();
                info.m = (time_end-time_start)/60;
                info.s = (time_end-time_start)%60;
                info.level = 3;
                if(judge(player_res,answer)){
                    printf("回答正确!\t用时:  %d:%d\n",info.m,info.s);
                    record(info);
                }
                else {
                    printf("回答错误!\t正确答案为:\n\n");
                    fflush(stdin);
                    print(answer);
                }
                break;
            default:
                printf("no option!\n");
                fflush(stdin);
                break;
            }
            break;
    case 2:
        easy = get_record(1);
        normal = get_record(2);
        hard = get_record(3);
        order(easy);
        order(normal);
        order(hard);
        show(easy,normal,hard);
        break;
    case 3:
        printf("\n拜拜~\n\n");
        exit(0);
    default:
        printf("no option!\n");
        fflush(stdin);
        break;
    }
    system("pause");
    system("cls");
    }
    }
    
    

    参考文章:https://blog.csdn.net/qq_45218336/article/details/107720395

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
  • ¥15 数据可视化Python
  • ¥15 要给毕业设计添加扫码登录的功能!!有偿
  • ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?
  • ¥15 微信公众号自制会员卡没有收款渠道啊
  • ¥15 stable diffusion
  • ¥100 Jenkins自动化部署—悬赏100元
  • ¥15 关于#python#的问题:求帮写python代码
  • ¥20 MATLAB画图图形出现上下震荡的线条
  • ¥15 关于#windows#的问题:怎么用WIN 11系统的电脑 克隆WIN NT3.51-4.0系统的硬盘