利用程序随机构造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<<"  -----------------------\n "):(cout<<" ");
        cout<<"| ";
        for(int y=0;y<9;y++)
        {
        cout<<sudo[x][y]<<" ";
        (y%3==2)?(cout<<"| "):(cout<<"");
        }
        cout<<endl;
    }
    cout<<"  -----------------------\n"<<endl;
}

void printsudotxt()        //输出到sudotiku.txt
{
    for(int x=0;x<9;x++)
    {
        (x%3==0)?(ocout<<"  -----------------------\n "):(ocout<<" ");
        ocout<<"| ";
        for(int y=0;y<9;y++)
        {
        ocout<<sudo[x][y]<<" ";
        (y%3==2)?(ocout<<"| "):(ocout<<"");
        }
        ocout<<endl;
    }
    ocout<<"  -----------------------\n"<<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.个人软件过程:估计、记录工作量,并逐步提高

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

原文地址:https://www.cnblogs.com/kfy-1104/p/9741866.html

时间: 2024-11-10 02:18:06

利用程序随机构造N个已解答的数独棋盘的相关文章

已知有个rand7()的函数,返回1到7随机自然数,让利用这个rand7()构造rand10() 随机1~10

1.int rand7()    2.{    3.  return rand()%7+1;    4.}    5.  6.int rand10()  7.{  8.    int x=0;  9.    do  10.    {  11.        x=(rand7()-1)*7+rand7();  12.    }  13.    while(x>40);  14.    return x%10+1;  15.} 分析:要保证rand10()在整数1-10的均匀分布,可以构造一个1-1

利用VBA+OO4O构造CTAIS开放式通用平台

利用VBA+OO4O构造CTAIS开放式通用平台2010-06-08 14:59:28 | 来源:税务信息化论文集 | 作者:于非 易飞 摘  要:文立足于CTAIS系统体系,探讨如何通过OO4O技术和VBA技术搭建ORACLE前端开放式通用平台,同时以通过最低编程技术满足基层信息化建设的要求,从而实现CTAIS功能的扩展.本文提供的通用平台建设通过笔者精简的满足OO4O连接必需的ORACLE免安装客户端,通过EXCEL的VBA接口,采取用户编写的各类查询语句的方式查询综合征管软件分发服务器数据

iOS开发- 文件共享(利用iTunes导入文件, 并且显示已有文件)

今天要实现一个功能, 通过iTunes导入文件到应用中, 并且在应用中对这个文件进行编辑. 类似我们平时经常使用的 PDF阅读器那样的东西, 我们可以自己导入我们的电子书. 源码下载:https://github.com/colin1994/iTunesTest.git 下面具体介绍下实现过程. 先看效果图. 图1. 未实现功能前, iTunes截图 图2. 实现功能后, iTunes截图 图3. 实现功能后, 运行截图. 好了, 通过图片, 我们可以看到实现的效果. 功能包括: 允许通过iTu

vs项目,点击.sln文件时出错:“项目所需的应用程序未安装,确保已安装项目类型(.csproj)的应用程序”解决办法

关键词:VS2005程序用VS2008打开 程序无法使用 项目所需的应用程序未安装,确保已安装项目类型(.csproj)的应用程序 在要打开的项目sln文件上右键,打开方式,不要用Micrisoft visual studio version selector,用D:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe打开. vs项目,点击.sln文件时出错:"项目所需的应用程序未安装,确保已安装项目类型(.cspro

Linux下运行C++程序出现&quot;段错误(核心已转储)&quot;的原因

今天写程序出现了“段错误(核心已转储)"的问题,查了一下资料,加上自己的实践,总结了以下几个方面的原因. 1.内存访问出错  这类问题的典型代表就是数组越界. 2.非法内存访问 出现这类问题主要是程序试图访问内核段内存而产生的错误. 3.栈溢出  Linux默认给一个进程分配的栈空间大小为8M.c++申请变量时,new操作申请的变量在堆中,其他变量一般在存储在栈中.  因此如果你数组开的过大变会出现这种问题.  首先我们先看一下系统默认分配的资源: 1 ulimit -a 可以看到默认分配的栈大

利用后缀数组构造后缀树

由于蒟蒻azui前段时间忙着准备省选,并在省选中闷声滚大粗,博客停更了好久.. 省选过后整个人各种颓,整天玩玩泥巴什么的... 前段时间学后缀数组的时候上网查相关资料,看到说后缀数组和后缀树是可以相互转化的,并且uoj上有大量通过后缀自动机建出后缀树然后dfs遍历获得后缀数组的模板,但是通过后缀数组来建后缀树的资料确实稀缺. 也许大牛们都觉得这xjbYY一下就可以写了,所以网上没找到对应的代码,那么我来补个坑吧.大牛勿喷.. 先谈谈我的理解吧.. 讲道理后缀数组和后缀树应该是完全等价的,但前两者

利用程序破案问题

3.日本某地发生了一件谋杀案,警察通过排查确定杀人凶手必为4个嫌疑犯的一个.以下为4个嫌疑犯的供词. A说:不是我. B说:是C. C说:是D. D说:C在胡说 已知3个人说了真话,1个人说的是假话. 现在请根据这些信息,写一个程序来确定到底谁是凶手. 程序代码: #include<stdio.h> #include<stdlib.h> int main() { int a, b, c, d; for (a = 0; a < 2;a++) for (b = 0; b <

适用于抽奖程序 随机广告的PHP概率算法实例

做网站类的有时会弄个活动什么的,来让用户参加,既吸引用户注册,又提高网站的用户活跃度.同时参加的用户会获得一定的奖品,有100%中奖的,也有按一定概率中奖的,大的比如中个ipad.iphone5,小的中个Q币什么的 那么我们在程序里必然会设计到算法,即按照一定的概率让用户获得奖品.先来看两个概率算法函数. 算法一 代码如下: /** * 全概率计算 * * @param array $p array('a'=>0.5,'b'=>0.2,'c'=>0.4) * @return string

利用随机函数随机产生大写字母

rand和srand.后者产生随机种子,前者利用后者产生的随机种子进而产生随机数.例如: 产生随机大写字母: 1 #include<iostream> 2 #include<stdlib.h> 3 #include<time.h> 4 #include<conio.h> 5 using namespace std; 6 int main() 7 {while(1) 8 { 9 srand(time(NULL)); 10 char ch; 11 ch=rand