数独个人项目

1) GitHub地址

https://github.com/ChengHaoShi/Project

2) PSP表格

PSP2.1

Personal Software Process Stages

预估耗时(小时)

实际耗时(小时)

Planning

计划

1.5

1

·Estimate

  • ·估计这个任务需要多少时间

1.5

1

  • ·Development

·开发

44.5

41.5

  • ·Analysis
  • ·需求分析 (包括学习新技术)
 

12

16

·Design Spec

  • ·生成设计文档

8

5

  • ·Design Review
  • ·设计复审 (和同事审核设计文档)
 

3

4

  • ·Coding Standard
  • ·代码规范 (为目前的开发制定合适的规范)
 

1

2

  • ·Design
  • ·具体设计
 

5

4

  • ·Coding
  • ·具体编码
 

5.5

4

  • ·Code Review
  • ·代码复审
 

3.5

4

  • ·Test
  • ·测试(自我测试,修改代码,提交修改)
 

4.5

2.5

Reporting

报告

5

6

  • ·Test Report
  • ·测试报告
 

1.5

1

  • ·Size Measurement
  • ·计算工作量
 

1

2.5

  • ·Postmortem & Process Improvement Plan
  • ·事后总结, 并提出过程改进计划
 

2.5

2.5

 

合计

51

48.5

3) 解题思路

  • ·数独游戏规则:

      数独是源自18世纪瑞士的一种数学游戏。是一种运用纸、笔进行演算的逻辑游戏。玩家需要根据9×9盘面上的已知数字,推理出所有剩余空格的数字,并满足每一行、每一列、每一个粗线宫(3*3)内的数字均含1-9,不重复。数独盘面是个九宫,每一宫又分为九个小格。在这八十一格中给出一定的已知数字和解题条件,利用逻辑和推理,在其他的空格上填入1-9的数字。使1-9每个数字在每一行、每一列和每一宫中都只出现一次,所以又称“九宫格”。                   ———引用自《数独_百度百科

·题目要求:

1.程序能生成不重复的数独终局至文件;

2.程序能读取文件内的数独问题,求一个可行解并将结果输出到文件;

       ·采用算法:

              回溯法生成数独终局,并检验是否符合数独可行解。

4) 设计实现过程

将部分函数和变量封装成Sudoku类。6个Sudoku类函数:

构造函数void Sudoku(int n)

公有函数int SudokuGenerate(int pos, long& count), void SudokuSolve(char* path)

私有函数bool IsVaild(int pot)、void PrintSudoku()

控制台输出函数void   PrintUsage()

单元测试设计:

      对IsValid() 函数进行测试;

      对命令行进行测试,检测异常输入并提供解决办法;

      对队中生成数独的个数进行测试;

5) 程序使用方法

1.序每次向sudoku.txt文件中输入一个数独终局。

2.使用release进行程序生成。

性能分析图

int SudokuGenerate(int pos, long& count, bool solve);//程序中消耗最大的函数

 

 

6) 核心代码

 

#include "sudoku.h"
#include "stdafx.h"

using namespace std;
string const NOSUCHFILE = "No such file: ";
string const OUTFILE = "sudoku.txt";
int const SQRTSIZE = int(sqrt(GRIDSIZE));

Sudoku::Sudoku(int n)
{
    for (int i = 0; i < GRIDSIZE; i++)
    {
        for (int j = 0; j < GRIDSIZE; j++)
        {
            grid[i][j] = UNKNOWN;
        }
    }
    grid[0][0] = FLAGNUM;
    this->n = n;
    output.open(OUTFILE);
    for (int i = 0; i < GRIDSIZE * GRIDSIZE; i++)
    {
        if ((i + 1) % 9 == 0)
        {
            buff[2 * i + 1] = '\n';
            continue;
        }
        buff[2 * i + 1] = ' ';
    }
    buff[162] = '\n';
}

int Sudoku::SudokuGenerate(int pos, long& count, bool solve)
{
    if (pos == GRIDSIZE * GRIDSIZE)
    {
        PrintSudoku();
        count++;
        if (count == n)
        {
            return 1;
        }
    }
    else
    {
        int x = pos / GRIDSIZE;
        int y = pos % GRIDSIZE;
        if (grid[x][y] == UNKNOWN)
        {
            int base = x / 3 * 3;
            for (int i = 0; i < GRIDSIZE; i++)         // try to fill the pos from 1-9
            {
                grid[x][y] = (i + base) % GRIDSIZE + 1 + '0';
                if (IsValid(pos, solve))               // if the number is valid
                {
                    if (SudokuGenerate(pos + 1, count, solve) == 1)       // try to fill next pos
                    {
                        return 1;
                    }
                }
                grid[x][y] = UNKNOWN;
            }
        }
        else
        {
            if (SudokuGenerate(pos + 1, count, solve) == 1)
            {
                return 1;
            }
        }
    }
    return 0;
}

int Sudoku::SudokuSolve(char* path)
{
    ifstream input;
    input.open(path);
    if (input)
    {
        int total = 0;
        string temp[GRIDSIZE];
        string str;
        int line = 0;
        bool exc = false;     // wrong input such as 'a','.',etc. in the input file
        while (total < 1000000 && getline(input, str))
        {
            temp[line] = str;
            line++;
            if (line == GRIDSIZE)
            {
                for (int i = 0; i < GRIDSIZE; i++)
                {
                    for (int j = 0; j < GRIDSIZE; j++)
                    {
                        grid[i][j] = temp[i][2 * j];
                        if(grid[i][j] < '0' || grid[i][j] > '9')
                        { 
                            exc = true;
                            break;
                        }
                    }
                }
                getline(input, str);
                line = 0;
                if (exc)
                {
                    exc = false;
                    continue;
                }
                total++;
                // solve sudoku
                long count = 0;
                SudokuGenerate(0, count, true);
            }
        }
        //cout << total << endl;
    }
    else
    {
        cout << NOSUCHFILE << string(path) << endl;
        return 0;
    }
    return 1;
}

bool Sudoku::IsValid(int pos, bool solve)
{
    int x = pos / GRIDSIZE;
    int y = pos % GRIDSIZE;
    int z = x / SQRTSIZE * SQRTSIZE + y / SQRTSIZE;
    int leftTop = z / SQRTSIZE * GRIDSIZE * SQRTSIZE + (z % SQRTSIZE) * SQRTSIZE;
    int rightDown = leftTop + (2 * GRIDSIZE + SQRTSIZE - 1);
    int bound = solve ? GRIDSIZE : y;
    // check row
    for (int i = 0; i < bound; i++)
    {
        if (i == y)
        {
            continue;
        }
        if (grid[x][i] == grid[x][y])
        {
            return false;
        }
    }
    // check column
    bound = solve ? GRIDSIZE : x;
    for (int i = 0; i < bound; i++)
    {
        if (i == x)
        {
            continue;
        }
        if (grid[i][y] == grid[x][y])
        {
            return false;
        }
    }   
    // check box
    int bound_x = leftTop / GRIDSIZE;
    int bound_y = leftTop % GRIDSIZE;
    if (bound_x % 3 != 0 || bound_y % 3 != 0 || bound_x > GRIDSIZE -3 || bound_y > GRIDSIZE - 3)
    {
        cout << "error" << endl;
        exit(0);
    }
    for (int i = bound_x; i < (bound_x + 3); i++)
    {
        for (int j = bound_y; j < (bound_y + 3); j++)
        {
            if (i == x && j == y)
            {
                if (solve)
                {
                    continue;
                }
                else
                {
                    return true;
                }
            }
            if (grid[i][j] == grid[x][y])
            {
                return false;
            }
        }
    }
    return true;
}

void Sudoku::PrintSudoku()
{
    for (int i = 0; i < GRIDSIZE; i++)
    {
        for (int j = 0; j < GRIDSIZE; j++)
        {
            buff[18 * i + 2 * j] = grid[i][j];
        }
    }
    output << buff;
}

 

转载于:https://www.cnblogs.com/AmandaYoung/p/8726878.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值