代码改变世界

数独

2018-10-06 21:54  WiilingDil  阅读(352)  评论(0)    收藏  举报

要求:

  1、利用程序随机构造N个已知的数独棋盘

  2、键盘输入数独棋盘的个数N(0<n<1000000)

  3、输出到susotiku.txt文件中,每个数独棋盘隔一#include <stdio.h>

#include <stdlib.h>
#include <time.h>
#include<windows.h>
int main()
{
    int i,j,l;
    int n;
    int sudu(int i,int j,int a[9][9]);  //数独的操作:判断3个重复
    int find_next_empty(int a[9][9],int num, int *i, int *j); //通过指针来查询下一个数据
    srand(time(0));

    printf("输入数独个数 \n");
    //生成不重复的函数
    scanf("%d",&n);
    
    for(l=0;l<n;l++)
    {
        int a[9][9] = {
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0,
            0,0,0,0,0,0,0,0,0
        };
        int time1=rand()%10;
        printf("请等待.... \n");
        Sleep(time1*100);  //设置定时
        for(j=0;j<9;j++)
        {
            int flag=1;
            int random=time1+rand()%10;  //根据时间的不同随机生成不同的数组-->有效的数组个数=1!+2!+3!+4!+5!+6!+7!+8!+9!  因为是随机数随意5,6,7,8,9的可能性较小
            for(i=0;i<9;i++)
            {
                if(random == a[0][i])
                {
                    flag=0;
                }
            }
            if(flag==1)
            {
                a[0][j]=random;
            }
        }

        /*for(i=0;i<9;i++)
        {
            for(j=0;j<9;j++)
            {
                //printf("%d ",a[i][j]);
            }
            //printf("\n");
        }*/

        for(i=0;i<9;i++)
        {
            for(j=0;j<9;j++)
            {
                sudu(i,j,a);
                find_next_empty(a, 0, &i, &j);   
            }
        }

        FILE *fpt;
        fpt = fopen("wendangming.txt","a+");//打开文档,写入

        for(i=0;i<9;i++)
        {
            for(j=0;j<9;j++)
            {
                fprintf(fpt,"%d ",a[i][j]);
                printf("%d ",a[i][j]);
            }
            fprintf(fpt,"\n");
            printf("\n");
        }

        fprintf(fpt,"--------\n");
        printf("--------\n");

        fclose(fpt);
    }
    

    return 0;
}
int sudu(int row,int col,int arr[9][9])
{
    int count=0;
    int flag=1;
    int i,j;
    int next_row,next_col;
    int find_next_empty(int a[9][9], int num, int *i, int *j);

    //获取下一个元素的行和列
    /*for(i=row;i<9;i++)
    {
        for(j=col;j<9;j++)
        {
            if(arr[i][j]==0)
            {
                nextRow=i;
                nextCol=j;
                break;
            }
        }    
    }*/
    tag:
    while(count<9)
    {
        count++;
        int i,j;
        //判断行重复
        for (j = 0; j < 9; j++) {
            if (arr[row][j] == count) {
                goto tag;
            }
        }        
        // 判断列重复
        for (i = 0; i < 9; i++) {
            if (arr[i][col] == count) {
                goto tag;
            }
        }        
        /* 判断3x3宫格重复*/
        int x = (row / 3) * 3;
        int y = (col / 3) * 3;
        for (i = x; i < x + 3; i++) {
            for (j = y; j < y + 3; j++)    {
                if (arr[i][j] == count) {
                    goto tag;
                }
            }
        }
        arr[row][col]=count;

    //查询下一个是否存在, 返回1-->存在 返回0->不存在
if (!find_next_empty(arr, row, &next_row, &next_col)) { return 1; } //否则继续填下一个未填充的格子
    
     //判断下一个是否有效,若无效(返回值==0) 重新取值 if (!sudu(next_row, next_col,arr)) { arr[row][col] = 0; continue; } else { return 1; } return 0; } return 0; } // 寻找下一个未填充的单元 int find_next_empty(int arr[9][9], int startrow, int *row, int *col) { int i, j; for (i = startrow; i < 9; i++) for (j = 0; j < 9; j++) if (arr[i][j] == 0) { *row = i; *col = j; return 1; } return 0; }

 

分析:在程序的运行过程中,偶尔存在时间的设置出现差错导致随机产生数独数组时会出错,如果是单个生成数组不会出现错误。大部分的时间消耗实在 Sleep()这函数中,因为随机生成的数组是按照时间来的,所以需要通过形成时间差距而造成数组的不重复

 

心得:在这次练习中发现这次练习的数独其中的两个重点问题就是:1、取下一个值的i,j;2、回溯

1、取下一个值 i,j 很容易出现错误,错误往往会导致内存消耗过大而电脑死机。所以在查询下一个数组元素的时候我参考的网上其他博主的取值方法,发现其中一个使用指针的方法相对比较简单,所以我就照搬替换之前使用的查询方法。

2、回溯:在程序中通过

if (!sudu(next_row, next_col,arr)) {
  arr[row][col] = 0;
  continue;
} else {
  return 1;
}

来实现,

3、疑问

 在程序中发现在while()循环中 count++;while里面的程序执行完之后count++无法中断 而且加上return 0或者是break; 也是一样;如果没有在程序中使用goto语句 直接通过设置flag(flag->初始化为1  当判断3个中有一个重复时 flag=0 flag==1时将值赋给a[i][j] ;break或者是return 0;跳出while循环) while里面的程序体执行完会出现一种情况

if(flag==1)

{
  arr[row][col]=count;
}
count++;

语句执行完之后的数独数组首行数据是 9,8,7,6,5,4,3,2,1

if(flag==1)
{
  arr[row][col]=count;
  count=10;
  printf("%d --> %d ",arr[row][col],count);
  //printf("--------");
  return 0;
}

数独数组首行数据依然是 9,8,7,6,5,4,3,2,1  本来应该是 1,2,3,4,5,6,7,8,9

 

 

7.课外任务

  在大学四年中自己接触比较频繁的编程语言主要是Html5和PHP,而且还处在入门的水准,在C++和JAVA又相对比较薄弱,所以还是希望可以提升自己在不同编程语言中的代码量了解,从而提升自己的专业能力。

 

技能 目前(满分10分) 课后(满分10分)
程序理解 3.2 7.5
效能分析和改进 1.0 6.0
架构设计、模块设计、接口设计 3.8 8.9
C++ 2.8 6.3
个人的源码管理 6 8.3
处理大数据 1.8 7