软件工程第二次作业——数独

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

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

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

              可执行文件exe,用法:(sudotiku.exe -c 20)(其中20为题目个数)

头文件sudoku.h:

#ifndef SUDOKU_H
#define SUDOKU_H

bool Sudoku_Row(int sudo[9][9], int row, int num);
bool Sudoku_Col(int sudo[9][9], int col, int num);
bool Sudoku_Square(int sudo[9][9], int row, int col, int num);
void print_sudoku(int sudo[9][9]);
bool makeSquare(int sudo[9][9], int num);

#endif

源程序:

#include "pch.h"
#include <iostream>
#include <ctime>
#include <fstream>
#include <stdlib.h>
#include "sudoku.h"
using namespace std;
#define Random(x) (rand()%x)
bool flag = false;

void Init_sudo(int(*sudo)[9])
{
for(int r=0;r<9;r++)
   {
       for (int c = 0; c < 9; c++)
       sudo[r][c] = 0;
   }
  sudo[0][0] = 1;//初始化数独,使第一个数为1
}
void Init_sudo_part(int(*sudo)[9])
{
     for (int r = 3; r < 9; r++)
    {
       for (int c = 0; c < 9; c++)
       sudo[r][c] = 0;
     }
    for (int r = 0; r < 3; r++)
    {
       for (int c = 3; c < 9; c++)
       sudo[r][c] = 0;
    }
}
bool check_sudo(int sudo[9])
{
     int temp;
     for (int i = 0; i < 9; i++)
    {
       temp = sudo[i];
       for (int j = i + 1;j < 9; j++)
         {
              if (sudo[j] == temp)
              return false;
         }
     }
return true;
}
//行检查
bool Sudoku_Row(int sudo[9][9], int row, int num)
{
     bool flag = false;//冲突标志
     for (int i = 0; i < 9; i++)
       {
          if (sudo[row][i] == num)
          {
             flag = true;
             break;
          }
       }
return flag;
}
//列检查
bool Sudoku_Col(int sudo[9][9], int col, int num)
{
      bool flag = false;
     for (int i = 0; i < 9; i++)
     {
         if (sudo[i][col] == num)
         {
             flag = true;
             break;
          }
      }
return flag;
}
//宫检查
bool Sudoku_Square(int sudo[9][9], int row,int col, int num)
{
      bool flag = false;
      int Square_Row = row / 3 * 3;
      int Square_col = col / 3 * 3;
      for (int i = 0; i < 3; i++)
     {
        for (int j = 0; j < 3; j++)
          {

              if (sudo[Square_Row+i][Square_col+j] == num)
              {
                   flag = true;
                   break;
              }
          }
     }
return flag;
}
void print_sudoku(int sudo[9][9])
{
     for (int i = 0; i < 9; i++)
     {
         for (int j = 0; j < 9; j++)
         {
              cout << sudo[i][j] << ' ';
         }
        cout << endl;
    }
    cout << endl;
}
//生成宫格
bool makeSquare(int sudo[9][9], int num)
{
     int square_row = (num / 3) * 3;
     int square_col = (num % 3) * 3;
     int x, y;
     int temp;
     if (num = 0) //第一个宫格
    {
       for (int i = 1; i < 9; i++)
       {
          x = square_row + i / 3;
          y = square_col + i % 3;
         temp = Random(8) + 2;//生成2~9的随机数
         if (!Sudoku_Square(sudo, x, y, temp) && !Sudoku_Col(sudo,
y, temp) && !Sudoku_Row(sudo, x, temp))
         {
           sudo[x][y] = temp;
         }
         else i--;
       }
   }
else //生成其他宫格
 {
      int try_count = 0;
      temp = Random(9) + 1;//生成1~9的随机数
      for (int i = 0; i < 9; i++)
     {
          x = square_row + i / 3;
          y = square_col + i % 3;
          temp++;
          temp = temp % 10;//循环随机数在1~9范围内
          if (!Sudoku_Square(sudo, x, y, temp) && !Sudoku_Col(sudo,
          y, temp) && !Sudoku_Row(sudo, x, temp) && temp != 0)
          {
               sudo[x][y] = temp;
               try_count = 0;
           }
          else
          {
                i--;
                try_count++;
           }
          if (try_count > 10)
          {
                return false;
                break;
           }//若所有可能试完则返回无解
    }

 }
return true;//有解
}
int main(int argc, char *argv[])
{
     int N = atoi(argv[argc-1]);
     int(*sudo)[9] = new int[9][9];
     ofstream outfile;
     outfile.open("sudoku.text");//输出到文档
     if (N > 0 && N <= 1000000)
     {
         srand(unsigned int(time(NULL)));//初始化种子为当前时间
         bool retry;//重试
         int retry_count = 0;//重试次数
         for (int i = 0; i < N;)
        {
           retry = false;
           if (retry_count == 0)
           {
               Init_sudo(sudo);
               makeSquare(sudo, 0);
           }
          else Init_sudo_part(sudo);
          for (int j = 1; j < 9; j++)
          {
               bool flag = makeSquare(sudo, j);
               if (!flag)
               {
                    retry = true;
                    break;
               }
           }
          if (!retry)
         {
              for (int row = 0; row < 9; row++)
              {
                   for (int col = 0; col < 9; col++)
                   {
                       outfile << sudo[row][col] << ' ';
                    }
               outfile << endl;
              }//输出一个数独矩阵
          outfile << endl;
          retry_count = 0;
          i++;
       }
     else
    {
        retry_count++;
     }//无解重试
   }
  outfile.close();
 }
else cout << "please input a proper number:" << endl;
return 0;
}

输出到sudoku.txt中:

程序分析:输出和生成宫格所用的时间比较多,还有待完善改进,但生成的数独没有重复的。这次项目我耗时比较长,也查了许多资料和百度参考别人的经验。我用的是VS2017版本,在调试过程需要在头文件加#include "pch.h"。

心得体会:通过这次作业,我发现我存在了很多有关于算法和编程方面的不足,程序中一点细微的问题都要处理比较久,但值得开心的是学到了一些知识,以后要加强算法和编程方面的练习。

课外任务:大一学过一点C语言,现在正在自学C++,目前能够看懂一些比较基础的程序代码和编写一些简单的程序,算法是个薄弱环节,距离一个合格的IT专业毕业生还有很大的差距,需要提高算法能力和编程能力,还有优化代码的能力。以下这个表是我目前的技能水平和期待课程结束后能达到的水平:

原文地址:https://www.cnblogs.com/muyang2/p/9751411.html