数独游戏项目报告
數獨游戲
一、項目開發的PSP表格總結
| Planning | 計劃 | 80 | 60 |
| · Estimate | · 估計這個任務需要多少時間 | 600 | 600 |
| Development | 開發 | 120 | 120 |
| · Analysis | · 需求分析 (包括學習新技術) | 180 | 180 |
| · Design Spec | · 生成設計文檔 | 150 | 150 |
| · Design Review | · 設計復審 (和同事審核設計文檔) | 60 | 60 |
| · Coding Standard | · 代碼規范 (為目前的開發制定合適的規范) | 60 | 60 |
| · Design | · 具體設計 | 180 | 180 |
| · Coding | · 具體編碼 | 120 | 120 |
| · Code Review | · 代碼復審 | 30 | 30 |
| · Test | · 測試(自我測試,修改代碼,提交修改) | 300 | 300 |
| Reporting | 報告 | 200 | 220 |
| · Test Report | · 測試報告 | 180 | 200 |
| · Size Measurement | · 計算工作量 | 20 | 30 |
| · Postmortem & Process Improvement Plan | · 事后總結, 并提出過程改進計劃 | 60 | 60 |
| 合計 | 2340 | 2370 |
二、項目介紹及要求
項目:生成數獨終局并且能求解數獨問題的控制臺程序
項目需求:
在命令行中使用-c參數加數字N(1<=N<=1000000)控制生成數獨終局的數量,例如下述命令將生成20個數獨終局至文件中:
sudoku -c 20將生成的數獨終局用一個文本文件(假設名字叫 sudoku.txt)的形式保存起來,每次生成的txt文件需要覆蓋上次生成的txt文件,文件內的格式如下,數與數之間由空格分開,終局與終局之間空一行,行末無空格:
2 6 8 4 7 3 9 5 1 3 4 1 9 6 5 2 7 8 7 9 5 8 1 2 3 6 4 5 7 4 6 2 1 8 3 9 1 3 9 5 4 8 6 2 7 8 2 6 3 9 7 4 1 5 9 1 7 2 8 6 5 4 3 6 8 3 1 5 4 7 9 2 4 5 2 7 3 9 1 8 64 5 1 7 8 2 3 6 9 7 8 6 4 9 3 5 2 1 3 9 2 1 5 6 4 8 7 5 2 7 6 4 9 8 1 3 9 6 8 5 3 1 2 7 4 1 3 4 2 7 8 6 9 5 8 1 5 3 6 7 9 4 2 6 7 3 9 2 4 1 5 8 2 4 9 8 1 5 7 3 69 5 8 3 6 7 1 2 4 2 3 7 4 5 1 9 6 8 1 4 6 9 2 8 3 5 7 6 1 2 8 7 4 5 9 3 5 7 3 6 1 9 4 8 2 4 8 9 2 3 5 6 7 1 7 2 4 5 9 3 8 1 6 8 9 1 7 4 6 2 3 5 3 6 5 1 8 2 7 4 9 ……程序在處理命令行參數時,不僅能處理格式正確的參數,還能夠處理各種異常的情況,如:
sudoku.exe -c abc
在生成數獨矩陣時,左上角的第一個數為:(學號后兩位相加)% 9 + 1。例如學生A學號后2位是80,則該數字為(8+0)% 9 + 1 = 9,那么生成的數獨棋盤應如下(x表示滿足數獨規則的任意數字):
9 x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x x二、需求分析
1.功能建模
0層圖:
1層圖:
2.功能建模
#mermaid-svg-Q4KPT1pnrgOPX4P7 .label{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);fill:#333;color:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .label text{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .node rect,#mermaid-svg-Q4KPT1pnrgOPX4P7 .node circle,#mermaid-svg-Q4KPT1pnrgOPX4P7 .node ellipse,#mermaid-svg-Q4KPT1pnrgOPX4P7 .node polygon,#mermaid-svg-Q4KPT1pnrgOPX4P7 .node path{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .node .label{text-align:center;fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .node.clickable{cursor:pointer}#mermaid-svg-Q4KPT1pnrgOPX4P7 .arrowheadPath{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edgePath .path{stroke:#333;stroke-width:1.5px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .flowchart-link{stroke:#333;fill:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edgeLabel{background-color:#e8e8e8;text-align:center}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edgeLabel rect{opacity:0.9}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edgeLabel span{color:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .cluster rect{fill:#ffffde;stroke:#aa3;stroke-width:1px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .cluster text{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:12px;background:#ffffde;border:1px solid #aa3;border-radius:2px;pointer-events:none;z-index:100}#mermaid-svg-Q4KPT1pnrgOPX4P7 .actor{stroke:#ccf;fill:#ECECFF}#mermaid-svg-Q4KPT1pnrgOPX4P7 text.actor>tspan{fill:#000;stroke:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .actor-line{stroke:grey}#mermaid-svg-Q4KPT1pnrgOPX4P7 .messageLine0{stroke-width:1.5;stroke-dasharray:none;stroke:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .messageLine1{stroke-width:1.5;stroke-dasharray:2, 2;stroke:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 #arrowhead path{fill:#333;stroke:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sequenceNumber{fill:#fff}#mermaid-svg-Q4KPT1pnrgOPX4P7 #sequencenumber{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 #crosshead path{fill:#333;stroke:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .messageText{fill:#333;stroke:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .labelBox{stroke:#ccf;fill:#ECECFF}#mermaid-svg-Q4KPT1pnrgOPX4P7 .labelText,#mermaid-svg-Q4KPT1pnrgOPX4P7 .labelText>tspan{fill:#000;stroke:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .loopText,#mermaid-svg-Q4KPT1pnrgOPX4P7 .loopText>tspan{fill:#000;stroke:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .loopLine{stroke-width:2px;stroke-dasharray:2, 2;stroke:#ccf;fill:#ccf}#mermaid-svg-Q4KPT1pnrgOPX4P7 .note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-Q4KPT1pnrgOPX4P7 .noteText,#mermaid-svg-Q4KPT1pnrgOPX4P7 .noteText>tspan{fill:#000;stroke:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activation0{fill:#f4f4f4;stroke:#666}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activation1{fill:#f4f4f4;stroke:#666}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activation2{fill:#f4f4f4;stroke:#666}#mermaid-svg-Q4KPT1pnrgOPX4P7 .mermaid-main-font{font-family:"trebuchet ms", verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .section{stroke:none;opacity:0.2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .section0{fill:rgba(102,102,255,0.49)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .section2{fill:#fff400}#mermaid-svg-Q4KPT1pnrgOPX4P7 .section1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .section3{fill:#fff;opacity:0.2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sectionTitle0{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sectionTitle1{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sectionTitle2{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sectionTitle3{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .sectionTitle{text-anchor:start;font-size:11px;text-height:14px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .grid .tick{stroke:#d3d3d3;opacity:0.8;shape-rendering:crispEdges}#mermaid-svg-Q4KPT1pnrgOPX4P7 .grid .tick text{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .grid path{stroke-width:0}#mermaid-svg-Q4KPT1pnrgOPX4P7 .today{fill:none;stroke:red;stroke-width:2px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .task{stroke-width:2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText{text-anchor:middle;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText:not([font-size]){font-size:11px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutsideRight{fill:#000;text-anchor:start;font-size:11px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutsideLeft{fill:#000;text-anchor:end;font-size:11px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .task.clickable{cursor:pointer}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutsideLeft.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutsideRight.clickable{cursor:pointer;fill:#003163 !important;font-weight:bold}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskText3{fill:#fff}#mermaid-svg-Q4KPT1pnrgOPX4P7 .task0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .task1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .task2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .task3{fill:#8a90dd;stroke:#534fbc}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutside0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutside2{fill:#000}#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutside1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .taskTextOutside3{fill:#000}#mermaid-svg-Q4KPT1pnrgOPX4P7 .active0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .active1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .active2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .active3{fill:#bfc7ff;stroke:#534fbc}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeText0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeText1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeText2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeText3{fill:#000 !important}#mermaid-svg-Q4KPT1pnrgOPX4P7 .done0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .done1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .done2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .done3{stroke:grey;fill:#d3d3d3;stroke-width:2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneText0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneText1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneText2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneText3{fill:#000 !important}#mermaid-svg-Q4KPT1pnrgOPX4P7 .crit0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .crit1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .crit2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .crit3{stroke:#f88;fill:red;stroke-width:2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCrit0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCrit1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCrit2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCrit3{stroke:#f88;fill:#bfc7ff;stroke-width:2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCrit0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCrit1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCrit2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCrit3{stroke:#f88;fill:#d3d3d3;stroke-width:2;cursor:pointer;shape-rendering:crispEdges}#mermaid-svg-Q4KPT1pnrgOPX4P7 .milestone{transform:rotate(45deg) scale(0.8, 0.8)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .milestoneText{font-style:italic}#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCritText0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCritText1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCritText2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .doneCritText3{fill:#000 !important}#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCritText0,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCritText1,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCritText2,#mermaid-svg-Q4KPT1pnrgOPX4P7 .activeCritText3{fill:#000 !important}#mermaid-svg-Q4KPT1pnrgOPX4P7 .titleText{text-anchor:middle;font-size:18px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.classGroup text{fill:#9370db;stroke:none;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family);font-size:10px}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.classGroup text .title{font-weight:bolder}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.clickable{cursor:pointer}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.classGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.classGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 .classLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.5}#mermaid-svg-Q4KPT1pnrgOPX4P7 .classLabel .label{fill:#9370db;font-size:10px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .relation{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .dashed-line{stroke-dasharray:3}#mermaid-svg-Q4KPT1pnrgOPX4P7 #compositionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #compositionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #aggregationStart{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #aggregationEnd{fill:#ECECFF;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #dependencyStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #dependencyEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #extensionStart{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 #extensionEnd{fill:#9370db;stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 .commit-id,#mermaid-svg-Q4KPT1pnrgOPX4P7 .commit-msg,#mermaid-svg-Q4KPT1pnrgOPX4P7 .branch-label{fill:lightgrey;color:lightgrey;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .pieTitleText{text-anchor:middle;font-size:25px;fill:#000;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .slice{font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.stateGroup text{fill:#9370db;stroke:none;font-size:10px;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.stateGroup text{fill:#9370db;fill:#333;stroke:none;font-size:10px}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.statediagram-cluster .cluster-label text{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.stateGroup .state-title{font-weight:bolder;fill:#000}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.stateGroup rect{fill:#ECECFF;stroke:#9370db}#mermaid-svg-Q4KPT1pnrgOPX4P7 g.stateGroup line{stroke:#9370db;stroke-width:1}#mermaid-svg-Q4KPT1pnrgOPX4P7 .transition{stroke:#9370db;stroke-width:1;fill:none}#mermaid-svg-Q4KPT1pnrgOPX4P7 .stateGroup .composit{fill:white;border-bottom:1px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .stateGroup .alt-composit{fill:#e0e0e0;border-bottom:1px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .state-note{stroke:#aa3;fill:#fff5ad}#mermaid-svg-Q4KPT1pnrgOPX4P7 .state-note text{fill:black;stroke:none;font-size:10px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .stateLabel .box{stroke:none;stroke-width:0;fill:#ECECFF;opacity:0.7}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edgeLabel text{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .stateLabel text{fill:#000;font-size:10px;font-weight:bold;font-family:'trebuchet ms', verdana, arial;font-family:var(--mermaid-font-family)}#mermaid-svg-Q4KPT1pnrgOPX4P7 .node circle.state-start{fill:black;stroke:black}#mermaid-svg-Q4KPT1pnrgOPX4P7 .node circle.state-end{fill:black;stroke:white;stroke-width:1.5}#mermaid-svg-Q4KPT1pnrgOPX4P7 #statediagram-barbEnd{fill:#9370db}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-cluster rect{fill:#ECECFF;stroke:#9370db;stroke-width:1px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-cluster rect.outer{rx:5px;ry:5px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-state .divider{stroke:#9370db}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-state .title-state{rx:5px;ry:5px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-cluster.statediagram-cluster .inner{fill:white}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-cluster.statediagram-cluster-alt .inner{fill:#e0e0e0}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-cluster .inner{rx:0;ry:0}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-state rect.basic{rx:5px;ry:5px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-state rect.divider{stroke-dasharray:10,10;fill:#efefef}#mermaid-svg-Q4KPT1pnrgOPX4P7 .note-edge{stroke-dasharray:5}#mermaid-svg-Q4KPT1pnrgOPX4P7 .statediagram-note rect{fill:#fff5ad;stroke:#aa3;stroke-width:1px;rx:0;ry:0}:root{--mermaid-font-family: '"trebuchet ms", verdana, arial';--mermaid-font-family: "Comic Sans MS", "Comic Sans", cursive}#mermaid-svg-Q4KPT1pnrgOPX4P7 .error-icon{fill:#522}#mermaid-svg-Q4KPT1pnrgOPX4P7 .error-text{fill:#522;stroke:#522}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edge-thickness-normal{stroke-width:2px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edge-thickness-thick{stroke-width:3.5px}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edge-pattern-solid{stroke-dasharray:0}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edge-pattern-dashed{stroke-dasharray:3}#mermaid-svg-Q4KPT1pnrgOPX4P7 .edge-pattern-dotted{stroke-dasharray:2}#mermaid-svg-Q4KPT1pnrgOPX4P7 .marker{fill:#333}#mermaid-svg-Q4KPT1pnrgOPX4P7 .marker.cross{stroke:#333}:root { --mermaid-font-family: "trebuchet ms", verdana, arial;}#mermaid-svg-Q4KPT1pnrgOPX4P7 {color: rgba(0, 0, 0, 0.75);font: ;}用戶命令分析系統終局生成命令錯誤命令需要生成的終局個數生成終局終局文件用戶命令分析系統終局生成三、解題思路
在拿到題目的時候,首先我們不難看出項目的關鍵在于生成1000000中不同的數獨。在此之前我們應該先來了解一下數獨的含義。
百度百科如下所示:
在了解完數獨之后,我們就要來想一想怎么去實現這個過程。
在上網查詢完資料之后,我選擇了一種較為簡單且較為好理解的一種算法。
根據項目要求,我們數獨的第一行第一個數字是確定的。以我為例,我的學號后兩位37計算所得到的首數字就為2。
首先,我們先考慮行內變換,因為數獨的其中一行變換,其他的也要變換,所以我們只考慮第一行的情況就可以。因為第一行的首數字確認,所以我們對其他8個數字進行全排列,得到8!種方案,也就是40320種方案,
核心代碼為:
但是這還不夠項目所要求的1000000種方案。那么接下來我們就可以進行行間變換,首先我們知道數獨中九宮格內的數字各不相同,一個九宮格包含三行。
那么我們就可以在2-3,4-6,7-9行間進行交換。同理,我們也對他們進行全排列,這樣我們就可以得到2!*3!*3!*8!=2903040種方案,遠遠滿足項目所要求的1000000種方案,由于該全排列數目較少,所以我們可以直接列出交換順序,如下所示:
這樣我們就完成了數獨生成方面的算法思路構造。
四、設計實現過程
在進行程序設計時,我采用的是結構化開發方法,開發語言為C++。因為vs上自帶的性能分析和單元測試工具,所以我的開發平臺為vs2019.
首先我設計了程序流程圖如下所示:
在整理完程序的流程圖之后,我們就開始結構化編程了。首先來說明一下我所定義的函數與數據結構,如下所示:
Shudo:(存放完整數獨)
打印函數PrintSudoku:將信息打印到sudoku.txt文件中
void PrintSudoku(FILE* fp, Shudo shudo, int num)全排列函數Permutation:對第一行進行全排列,獲取第一行行間交換的所有情況
void Permutation(int now)創造數獨函數CreatSudoku:根據所需數獨個數生成數獨
int CreatSudoku(int count)下面就來展示程序的具體實現過程:
首先,我們現根據設計思路自我定義一個初始的一行數據以及第一行變換所得其他行的數據變更順序,代碼如下:
int firstline[40320][9] = { 0 };//用一個二維數組來存放第一行的變換情況,也就是8!種 int first[size] = { 2,3,4,5,6,7,8,9,1 };//存放初始的第一行數字 int shunxu[9] = { 0,3,6,1,4,7,2,5,8 };//表示行間的交換順序 int num = 0;由于行間交換的全排列情況較少,所以我們可以提前進行定義,減少程序運行時間,代碼如下:
//行間交換順序全排列結果 int paixu1_3[2][3] = { {0,1,2},{0,2,1} }; int paixu4_6[6][3] = { {3,4,5},{3,5,4},{4,3,5},{4,5,3},{5,3,4},{5,4,3} }; int paixu7_9[6][3] = { {6,7,8},{6,8,7},{7,6,8},{7,8,6},{8,6,7},{8,7,6} };之后我們在對打印輸出函數PrintSudoku和全排列函數Permutation進行設計實現,其中全排列算法我參考了全排列算法的理解與實現(遞歸+字典序)這篇文章,文章講得很好,讓我完全理解了全排列算法的思想,兩個函數的代碼構造如下:
void PrintSudoku(FILE* fp, Shudo shudo, int num) {if (num != 0)fputc('\n', fp);for (int i = 0;i < 9;i++) {for (int j = 0;j < 9;j++) {fprintf(fp, "%d%c", shudo.form[i][j], j == 8 ? '\n' : ' ');}} } //對第一行進行全排列 void Permutation(int now) {if (now == 8) {for (int i = 0;i < 9;i++) {firstline[num][i] = first[i];}num++;}else {for (int i = now;i < 9;i++) {swap(first[i], first[now]);//把要打頭的數放到最開頭的位置Permutation(now + 1);swap(first[i], first[now]);//為避免重復排序,每個數打頭結束后都恢復初始排序,防止重復的方法很多,不止這一種}} }之后就是我們的核心函數 CreatSudoku的設計實現了。因為我們已經獲得第一行行間交換的所有情況,所以我們可以直接根據之前設定好的**shunxu[9]**中所表示的數據來直接得到其余8行的數據,之后根據外部傳來的參數來決定行間交換的次數,這樣就可以實現生成數獨的功能了。代碼如下:
//構造所需的數獨 int CreatSudoku(int count) {FILE* fp;fp = fopen("sudoku.txt", "w");//只允許寫入int num = 0;Shudo shudu;for (int i = 0;i < 40320;i++) {Shudo backup;//為每一種第一行情況構造完整數獨for (int j = 0;j < 9;j++) {backup.form[0][j] = firstline[i][j];}for (int j = 1;j < 9;j++) {for (int k = 0;k < 9;k++) {backup.form[j][k] = backup.form[0][(k + shunxu[j]) % 9];}}shudu = backup;//將構造好的數獨進行行間交換for (int j = 0;j < 1;j++) {for (int k = 0;k < 6;k++) {for (int l = 0;l < 6;l++) {if (num < count) {for (int m = 0;m < 3;m++) {for (int n = 0;n < 9;n++) {shudu.form[m][n] = backup.form[paixu1_3[j][m]][n];}}for (int m = 3;m < 6;m++) {for (int n = 0;n < 9;n++) {shudu.form[m][n] = backup.form[paixu4_6[k][m - 3]][n];}}for (int m = 6;m < 9;m++) {for (int n = 0;n < 9;n++) {shudu.form[m][n] = backup.form[paixu7_9[l][m - 6]][n];}}PrintSudoku(fp, shudu, num);num++;}else if (num == count) {fclose(fp);return 1;}else if (num > count) {fclose(fp);printf("程序運行錯誤!\n");}}}}}//若程序運營到這里還沒有終止,表示程序出錯fclose(fp);printf("程序運行錯誤!\n"); }最后就是我們主函數main的構造:
首先我們先對命令行參數進行一系列的判斷,這里就不具體描述了,詳見代碼。如果符合,我們就先調用全排列函數,獲取第一行行間交換的所有情況,之后將需要的數獨個數傳入數獨生成函數中,就完成了項目的要求,代碼如下:
注意:其中的返回值沒有特殊含義,是為了方便單元測試路徑測試所設立的
五、程序正確性以及性能測試
程序正確性測試:輸入范圍限制在 1-1000,要求程序在 60 s 內給出結果,超時則認定運行結果無效
下圖為生成1000個數獨的正確性測試結果:
程序性能測試:輸入范圍限制在 10000-1000000,沒有時間的最小要求限制
下圖為生成1000000個數獨的性能測試結果:
六、單元測試的設計及性能分析
在單元測試中,我們應用的是vs自帶的工具,首先我們創建一個test.h的頭文件,將我們要測試的模塊寫進去。之后創建測試項目UnitTest1。
根據程序流程圖以及main函數的編寫,我采用的單元測試策略為條件組合測試,一共設計了5個測試用例,測試代碼如下所示:
VS的測試結果圖片如下所示:
之后我們利用VS的性能探查器來進行性能分析
結果如下所示:
通過上圖我們可以看出,程序的時間主要消耗在打印輸出方面了,因此我們可以通過改進輸出流來進行程序的優化,可以節約大量的時間。
七、第一階段總結與反思
在第一階段的任務中,我第一次感覺到了軟件工程的必要性,深深地意識到軟件的開發不只是編程這么簡單,編程知識軟件工程中的一部分。
在項目的開始,由于對各種工具缺乏認識,導致我開始的進程十分緩慢,開發過程十分沒有動力,但逐漸了解這些工具之后,我深深的感受到了這些工具對我們的幫助。其中單元測試、性能分析以及需求分析過程中的建模也用到了我們課程所學的知識,讓我學以致用,收獲了許多!
總結
- 上一篇: The mook jong 计数DP
- 下一篇: Jenkins构建 netcore5.0