zoukankan      html  css  js  c++  java
  • 利用程序随机构造N个已解答的数独棋盘

    项目需求:利用程序随机构造N个已解答的数独棋盘

     输入:数独棋盘题目个数N (0 < N <= 1000000)

     输出:随机生成N个不重复的已解答完毕的数独棋盘, 并输出到sudotiku.txt,每个数独棋盘中间隔一行

    #include<iostream>
    #include<cstdlib>
    #include<ctime>
    #include<fstream>
    using namespace std;
    
    ofstream ocout;
    int sudo[9][9];
    bool set(int x,int y,int val)
    {
        if(sudo[x][y]!=0)        //非空
            return false;    
        int x0,y0;
        for(y0=0;y0<9;y0++)        //行冲突
        {
            if(sudo[x][y0]==val)
                return false;
        }
        for(x0=0;x0<9;x0++)        //列冲突  
        {
            if(sudo[x0][y]==val)
                return false;
        }
        for(x0=x/3*3;x0<x/3*3+3;x0++)        //格冲突
        {
            for(y0=y/3*3;y0<y/3*3+3;y0++)
            {
                if(sudo[x0][y0]==val)
                    return false;
            }
        }
        sudo[x][y]=val;
        return true;
    }
    
    void current(int* cur)     ///0~9随机序列
    {
        int i,j,temp;
        for(int i=0;i<9;i++)
        {
            cur[i]=i;
        }
        for(int i=0;i<9;i++)
        {
            j=rand()%9;
            temp=cur[j];
            cur[j]=cur[i];
            cur[i]=temp;
        }
    }
    
    void reset(int x,int y)
    {
        sudo[x][y]=0;
    }
    
    bool fill(int x,int val)
    {
        int cur[9];
        current(cur);    //生成当前行的扫描序列
        for(int i=0;i<9;i++)
        {
            int y=cur[i];
            if(set(x,y,val))    //可以先把每一行的1填了,再填每一行的2...以此类推
            {
                if(x==8)    //到了最后一行
                {
                if(val==9||fill(0,val+1))    //当前填9则结束,否则从第一行填下一个数
                    return true;
                }
                else
                {
                    if(fill(x+1,val))    //下一行继续填当前数
                        return true;    
                }
                reset(x,y);        //回溯
            }
        }
        return false;
    }
    void clear(int temp[9][9])    //清空
    {
        for(int i=0;i<9;i++)
        {
            for(int j=0;j<9;j++)
            {
                temp[i][j]=0;
            }
        }
    }
    
    void printsudo()        //输出到屏幕
    {
        for(int x=0;x<9;x++)
        {
            (x%3==0)?(cout<<"  -----------------------
     "):(cout<<" ");
            cout<<"| ";
            for(int y=0;y<9;y++)
            {
            cout<<sudo[x][y]<<" ";
            (y%3==2)?(cout<<"| "):(cout<<"");
            }
            cout<<endl;
        }
        cout<<"  -----------------------
    "<<endl;
    }
    
    void printsudotxt()        //输出到sudotiku.txt
    {
        for(int x=0;x<9;x++)
        {
            (x%3==0)?(ocout<<"  -----------------------
     "):(ocout<<" ");
            ocout<<"| ";
            for(int y=0;y<9;y++)
            {
            ocout<<sudo[x][y]<<" ";
            (y%3==2)?(ocout<<"| "):(ocout<<"");
            }
            ocout<<endl;
        }
        ocout<<"  -----------------------
    "<<endl;
    }
    
    
    int main()
    {
        srand((unsigned)time(NULL));    //这个是种子函数 为rand函数提供不同的种子 每次运行程序产生不同的随机数,不然rand函数每次运行程序产生的随机数都是一样的
        ocout.open("sudotiku.txt");
        cout<<"请输入数独棋盘题目个数N (0 < N <= 1000000):"<<endl;
        int N;
        cin>>N;
        cout<<"随机生成"<<N<<"个不重复的已解答完毕的数独棋盘如下:"<<endl;
        ocout << "随机生成"<<N<<"个不重复的已解答完毕的数独棋盘如下:" << endl;
        for(int i=0;i<N;i++)
        {
            clear(sudo);
            while(!fill(0,1));
            printsudo();
            printsudotxt();
        }
        ocout.close();
        return 0;
    }

    程序运行结果如下:

    随机生成3个不重复的已解答完毕的数独棋盘如下:
    -----------------------
    | 4 1 7 | 3 8 2 | 9 5 6 |
    | 2 9 3 | 6 4 5 | 8 7 1 |
    | 6 8 5 | 7 9 1 | 2 4 3 |
    -----------------------
    | 1 7 6 | 5 3 8 | 4 9 2 |
    | 8 2 4 | 9 6 7 | 3 1 5 |
    | 3 5 9 | 2 1 4 | 6 8 7 |
    -----------------------
    | 9 3 1 | 4 5 6 | 7 2 8 |
    | 5 6 2 | 8 7 9 | 1 3 4 |
    | 7 4 8 | 1 2 3 | 5 6 9 |
    -----------------------

    -----------------------
    | 6 7 3 | 1 9 2 | 5 4 8 |
    | 2 8 1 | 6 5 4 | 9 7 3 |
    | 5 4 9 | 8 7 3 | 2 6 1 |
    -----------------------
    | 3 9 8 | 4 6 1 | 7 5 2 |
    | 4 6 7 | 2 8 5 | 3 1 9 |
    | 1 5 2 | 7 3 9 | 4 8 6 |
    -----------------------
    | 8 2 4 | 3 1 7 | 6 9 5 |
    | 7 1 5 | 9 2 6 | 8 3 4 |
    | 9 3 6 | 5 4 8 | 1 2 7 |
    -----------------------

    -----------------------
    | 3 4 9 | 6 7 8 | 5 2 1 |
    | 7 8 1 | 2 4 5 | 9 3 6 |
    | 6 2 5 | 3 1 9 | 8 4 7 |
    -----------------------
    | 8 5 3 | 4 6 2 | 1 7 9 |
    | 2 9 7 | 8 5 1 | 4 6 3 |
    | 4 1 6 | 9 3 7 | 2 5 8 |
    -----------------------
    | 1 3 2 | 7 9 4 | 6 8 5 |
    | 5 6 8 | 1 2 3 | 7 9 4 |
    | 9 7 4 | 5 8 6 | 3 1 2 |
    -----------------------

    经测试,程序可以正确运行,运行时间也较短。

    通过此次作业,我不仅了解了数独这个游戏,还对回溯的用法有了更深刻的认识,有些平时掌握不牢的知识点,经过程序运行中出现的错误,都能进行很好的纠正。完成这个程序,我花了好几天时间,因为没有思路,所以只能上网查资料,在之后的运行过程中,遇到了如下几个问题:

    1.需要在主函数开头加srand((unsigned)time(NULL));这个种子函数,为rand函数提供不同的种子,每次运行程序产生不同的随机数,不然rand函数每次运行程序产生的随机数都是一样的;

    2.将程序运行结果输出到sudotiku.txt,ofstream ocout;语句需要写在开头;

    3.回溯法的运用,需要理清思路。

    这些问题的解决都是通过百度别人的经验来进行解决的。

    我认为对我特别重要的技能有以下几项:

    1.程序理解(如何理解已有的程序,通过阅读、分析、debug)

    2.架构设计、模块化设计、接口设计

    3.模块实现、逐步细化

    4.效能分析与改进

    5.线程之间/进程之间/不同平台的进程之间

    6.个人软件过程:估计、记录工作量,并逐步提高

    目前我具备的专业知识、技能、能力都处于一个基础阶段,掌握了基本的书面知识和实践技能,希望在学完这门课程后,可以掌握基本的理论和实践知识,通过一般相关企业的面试。

  • 相关阅读:
    CF # 296 C Glass Carving (并查集 或者 multiset)
    linux 基本命令
    为什么是丰田——丰田的七个习惯之习惯一
    关注C-RAN 的五大理由
    一个效果非常华丽的仿桌面APP,却胜似Launcher
    IOS6.0自带下拉刷新控件UIRefreshControl
    POJ 2421--Constructing Roads【水题 &amp;&amp; 最小生成树 &amp;&amp; kruskal】
    ORACLE-017:SQL优化-is not null和nvl
    数据结构——栈
    数据结构——静态链表
  • 原文地址:https://www.cnblogs.com/kfy-1104/p/9741866.html
Copyright © 2011-2022 走看看