• java暴力回朔法解数独


    BeginIndexRangeVO.java:
    1. import lombok.Getter;
    2. import lombok.Setter;
    3. import java.io.Serializable;
    4. @Getter
    5. @Setter
    6. public class BeginIndexRangeVO implements Serializable {
    7. private int beginRowNum;
    8. private int beginColNum;
    9. public BeginIndexRangeVO(int beginRowNum, int beginColNum) {
    10. this.beginRowNum = beginRowNum;
    11. this.beginColNum = beginColNum;
    12. }
    13. }
    PointVO.java:
    1. import lombok.Getter;
    2. import lombok.Setter;
    3. import java.io.Serializable;
    4. import java.util.List;
    5. @Getter
    6. @Setter
    7. public class PointVO implements Serializable {
    8. /*
    9. 2 - 9 6 - - 8 5 4
    10. 4 8 6 9 5 2 7 3 1
    11. - - - - 4 - 6 2 9
    12. - - 2 4 - 9 5 8 6
    13. 5 - 4 - - - 3 9 2
    14. - 9 - 2 - 5 1 4 7
    15. - - 1 - 2 4 9 - 3
    16. 9 4 - 3 1 - 2 - 5
    17. - 2 - - 9 - 4 1 8
    18. */
    19. private String number;
    20. private String tryNumber;
    21. private int rowNum;
    22. private int colNum;
    23. private int gongNum=0;
    24. private String code;
    25. private List possibleNumbers;
    26. private List impossibleNumbers;
    27. private List possibleNumbers_bak;
    28. public PointVO(String number, int rowNum, int colNum) {
    29. this.number = number;
    30. this.rowNum = rowNum;
    31. this.colNum = colNum;
    32. }
    33. public String getCode(){
    34. if( this.code != null ){
    35. return this.code;
    36. }
    37. this.code = this.rowNum + "-" + this.colNum;
    38. return this.code;
    39. }
    40. public int getGongNum(){
    41. if( this.gongNum > 0 ){
    42. return this.gongNum;
    43. }
    44. if( this.rowNum <= 3 ){
    45. if( this.colNum <= 3 ){
    46. this.gongNum = 1;
    47. }else if( this.colNum <= 6 ){
    48. this.gongNum = 2;
    49. }else {
    50. this.gongNum = 3;
    51. }
    52. }else if( this.rowNum <= 6 ){
    53. if( this.colNum <= 3 ){
    54. this.gongNum = 4;
    55. }else if( this.colNum <= 6 ){
    56. this.gongNum = 5;
    57. }else {
    58. this.gongNum = 6;
    59. }
    60. }else {
    61. if( this.colNum <= 3 ){
    62. this.gongNum = 7;
    63. }else if( this.colNum <= 6 ){
    64. this.gongNum = 8;
    65. }else {
    66. this.gongNum = 9;
    67. }
    68. }
    69. return this.gongNum;
    70. }
    71. }

    RowColVO.java:
    1. import lombok.Getter;
    2. import lombok.Setter;
    3. import java.io.Serializable;
    4. @Getter
    5. @Setter
    6. public class RowColVO implements Serializable {
    7. private int rowNum;
    8. private int colNum;
    9. public RowColVO(int rowNum, int colNum) {
    10. this.rowNum = rowNum;
    11. this.colNum = colNum;
    12. }
    13. }

    ShuduSolver_backtracking.java:
    1. import java.util.*;
    2. public class ShuduSolver_backtracking {
    3. private static final Map map_gongNum_beginIndexRange = new HashMap<>();
    4. private static final Map> map_gongNum_numbers = new HashMap<>();
    5. private static final Map> map_rowNum_numbers = new HashMap<>();
    6. private static final Map> map_colNum_numbers = new HashMap<>();
    7. private static Map map_code_point;
    8. private static int deep_recursion = 0;
    9. private static int count_filled = 0;
    10. static {
    11. map_gongNum_beginIndexRange.put(1, new BeginIndexRangeVO(1, 1));
    12. map_gongNum_beginIndexRange.put(2, new BeginIndexRangeVO(1, 4));
    13. map_gongNum_beginIndexRange.put(3, new BeginIndexRangeVO(1, 7));
    14. map_gongNum_beginIndexRange.put(4, new BeginIndexRangeVO(4, 1));
    15. map_gongNum_beginIndexRange.put(5, new BeginIndexRangeVO(4, 4));
    16. map_gongNum_beginIndexRange.put(6, new BeginIndexRangeVO(4, 7));
    17. map_gongNum_beginIndexRange.put(7, new BeginIndexRangeVO(7, 1));
    18. map_gongNum_beginIndexRange.put(8, new BeginIndexRangeVO(7, 4));
    19. map_gongNum_beginIndexRange.put(9, new BeginIndexRangeVO(7, 7));
    20. }
    21. public static void main(String[] args) {
    22. int[][] chupan ={
    23. { 1,0,4, 0,0,0, 0,0,0 },
    24. { 0,0,0, 0,0,5, 0,0,0 },
    25. { 0,6,0, 0,8,0, 0,7,3 },
    26. { 0,0,0, 8,0,1, 9,0,0 },
    27. { 6,5,0, 0,0,0, 0,0,0 },
    28. { 0,0,0, 3,0,0, 0,0,8 },
    29. { 0,2,0, 0,3,0, 0,0,7 },
    30. { 0,0,0, 0,0,7, 1,3,0 },
    31. { 4,7,0, 0,0,0, 8,9,0 }
    32. };
    33. List points = initChuPan( chupan );
    34. map_code_point = points2CodeAndPointMap(points);
    35. init_map_xxxNum_numbers( );
    36. print( );
    37. System.out.println("count_filled = " + count_filled);
    38. calculatePossibleNumbers();
    39. printPossibles();
    40. backtrackingAndCauseError();
    41. System.out.println("aaaaaaaaaaaaaaaaaaaaaaaaaaa");
    42. printPossibles();
    43. print();
    44. System.out.println( "递归深度 = " + deep_recursion );
    45. }
    46. /** ps:下一步填写全部的可能性都错了才表示上一步填错了
    47. * 发生错误,返回 true,
    48. * @return
    49. */
    50. private static boolean backtrackingAndCauseError() {
    51. deep_recursion++;
    52. // todo 找到第一个空格子
    53. PointVO point = searchFirstBlankPoint();
    54. if( point == null ){
    55. System.out.println( "222222222222222222222222222222222222" );
    56. System.out.println( "222222222222222222222222222222222222" );
    57. System.out.println( "222222222222222222222222222222222222" );
    58. System.out.println( "222222222222222222222222222222222222" );
    59. // 没有空格子了,表示游戏结束了
    60. System.exit( 0 );
    61. }
    62. int rowNum = point.getRowNum();
    63. int colNum = point.getColNum();
    64. String pointName = getPointName(rowNum, colNum);
    65. // 计算该格子可能填写的数字集合
    66. List possibleNumbers = getPossibleNumbers( rowNum,colNum );
    67. if( possibleNumbers.size() == 0 ){
    68. // 该空格子不能填任何数字了,表示出现了错误
    69. return true;
    70. }
    71. possibleNumbers = deepCopyList( possibleNumbers );
    72. int count_possible = possibleNumbers.size();
    73. int count_error = 0;
    74. for( String possibleNumber:possibleNumbers ){
    75. fillNumber( rowNum,colNum,possibleNumber );
    76. boolean causeError = backtrackingAndCauseError();
    77. if( causeError ){
    78. count_error++;
    79. }
    80. clearNumber( rowNum,colNum,null );
    81. }
    82. if( count_error == count_possible ){
    83. // 该格子尝试全部的可能性都错,表示出现了错误
    84. return true;
    85. }
    86. return backtrackingAndCauseError();
    87. }
    88. private static PointVO searchFirstBlankPoint() {
    89. Set codes = map_code_point.keySet();
    90. for( String code:codes ){
    91. PointVO point = map_code_point.get(code);
    92. if( point.getNumber() == null ){
    93. return point;
    94. }
    95. }
    96. return null;
    97. }
    98. private static void clearNumber(int rowNum, int colNum, String number) {
    99. String code = getCode(rowNum, colNum);
    100. PointVO point = map_code_point.get(code);
    101. point.setNumber( null );
    102. count_filled--;
    103. List impossibleNumbers = point.getImpossibleNumbers();
    104. if( impossibleNumbers ==null ){
    105. impossibleNumbers = new ArrayList<>();
    106. point.setImpossibleNumbers( impossibleNumbers );
    107. }
    108. impossibleNumbers.add( number );
    109. // 初始化 当前格子所在的行、列、宫的 numers集合
    110. init_map_xxxNum_numbers( rowNum,colNum );
    111. }
    112. private static boolean gameSuccess(){
    113. return count_filled == 81;
    114. }
    115. private static String getPointName(int rowNum, int colNum) {
    116. return rowNum + "行" + colNum + "列";
    117. }
    118. /**
    119. * 初始化 当前格子所在的行、列、宫的 numers集合
    120. * @param targetRowNum
    121. * @param targetColNum
    122. */
    123. private static void init_map_xxxNum_numbers( int targetRowNum,int targetColNum ){
    124. // 行
    125. Set numbers_currRow = map_rowNum_numbers.get(targetRowNum);
    126. numbers_currRow.clear();
    127. for (int colNum = 1; colNum <=9 ; colNum++) {
    128. String code = getCode(targetRowNum, colNum);
    129. PointVO point = map_code_point.get(code);
    130. if( point.getNumber() == null ){
    131. continue;
    132. }
    133. numbers_currRow.add( point.getNumber() );
    134. }
    135. // 列
    136. Set numbers_currCol = map_colNum_numbers.get(targetColNum);
    137. numbers_currCol.clear();
    138. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    139. String code = getCode(rowNum, targetColNum);
    140. PointVO point = map_code_point.get(code);
    141. if( point.getNumber() == null ){
    142. continue;
    143. }
    144. numbers_currCol.add( point.getNumber() );
    145. }
    146. // 宫
    147. int gongNum = getGongNum(targetRowNum, targetColNum);
    148. Set numbers_currGong = map_gongNum_numbers.get(gongNum);
    149. numbers_currGong.clear();
    150. BeginIndexRangeVO beginIndexRange = map_gongNum_beginIndexRange.get(gongNum);
    151. int beginRowNum = beginIndexRange.getBeginRowNum();
    152. int endRowNum = beginRowNum + 2;
    153. int beginColNum = beginIndexRange.getBeginColNum();
    154. int endColNum = beginColNum + 2;
    155. for (int rowNum = beginRowNum; rowNum <=endRowNum ; rowNum++) {
    156. for (int colNum = beginColNum; colNum <=endColNum ; colNum++) {
    157. String code = getCode(rowNum, colNum);
    158. PointVO point = map_code_point.get(code);
    159. if( point.getNumber() == null ){
    160. continue;
    161. }
    162. numbers_currGong.add( point.getNumber() );
    163. }
    164. }
    165. }
    166. /**
    167. * 初始化三个缓存map( map_rowNum_numbers、map_colNum_numbers、map_gongNum_numbers )
    168. */
    169. private static void init_map_xxxNum_numbers( ) {
    170. // 1~9行
    171. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    172. Set numbers_row = map_rowNum_numbers.get(rowNum);
    173. if( numbers_row == null ){
    174. numbers_row = new HashSet<>();
    175. map_rowNum_numbers.put( rowNum,numbers_row );
    176. }else {
    177. numbers_row.clear();
    178. }
    179. for (int colNum = 1; colNum <=9 ; colNum++) {
    180. String code = getCode(rowNum, colNum);
    181. PointVO point = map_code_point.get(code);
    182. if( point.getNumber() == null ){
    183. continue;
    184. }
    185. numbers_row.add( point.getNumber() );
    186. }
    187. }
    188. // 1~9列
    189. for (int colNum = 1; colNum <=9 ; colNum++) {
    190. Set numbers_col = map_colNum_numbers.get(colNum);
    191. if( numbers_col == null ){
    192. numbers_col = new HashSet<>();
    193. map_colNum_numbers.put( colNum,numbers_col );
    194. }else {
    195. numbers_col.clear();
    196. }
    197. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    198. String code = getCode(rowNum, colNum);
    199. PointVO point = map_code_point.get(code);
    200. if( point.getNumber() == null ){
    201. continue;
    202. }
    203. numbers_col.add( point.getNumber() );
    204. }
    205. }
    206. // 1~9宫
    207. for (int gongNum = 1; gongNum <=9 ; gongNum++) {
    208. Set numbers_gong = map_gongNum_numbers.get(gongNum);
    209. if( numbers_gong == null ){
    210. numbers_gong = new HashSet<>();
    211. map_gongNum_numbers.put( gongNum,numbers_gong );
    212. }else {
    213. numbers_gong.clear();
    214. }
    215. BeginIndexRangeVO beginIndexRange = map_gongNum_beginIndexRange.get(gongNum);
    216. int beginRowNum = beginIndexRange.getBeginRowNum();
    217. int endRowNum = beginRowNum + 2;
    218. int beginColNum = beginIndexRange.getBeginColNum();
    219. int endColNum = beginColNum + 2;
    220. for (int rowNum = beginRowNum; rowNum <=endRowNum ; rowNum++) {
    221. for (int colNum = beginColNum; colNum <=endColNum ; colNum++) {
    222. String code = getCode(rowNum, colNum);
    223. PointVO point = map_code_point.get(code);
    224. if( point.getNumber() == null ){
    225. continue;
    226. }
    227. numbers_gong.add( point.getNumber() );
    228. }
    229. }
    230. }
    231. }
    232. private static List deepCopyList(List list) {
    233. List list_copy = new ArrayList<>();
    234. for( String item:list ){
    235. list_copy.add( item );
    236. }
    237. return list_copy;
    238. }
    239. private static void calculatePossibleNumbers( ) {
    240. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    241. for (int colNum = 1; colNum <=9 ; colNum++) {
    242. calculatePossibleNumberForTargetRowAndCol( rowNum,colNum );
    243. }
    244. }
    245. }
    246. private static List getPossibleNumbers( int rowNum,int colNum ){
    247. String code = getCode(rowNum, colNum);
    248. PointVO point = map_code_point.get(code);
    249. Set numbers_canNotFill = new HashSet<>();
    250. numbers_canNotFill.addAll( map_rowNum_numbers.get( rowNum ) );
    251. numbers_canNotFill.addAll( map_colNum_numbers.get( colNum ) );
    252. int gongNum = getGongNum( rowNum, colNum );
    253. numbers_canNotFill.addAll( map_gongNum_numbers.get(gongNum) );
    254. List possibleNumbers = new ArrayList<>();
    255. for (int i = 1; i <=9 ; i++) {
    256. possibleNumbers.add( String.valueOf( i ) );
    257. }
    258. possibleNumbers.removeAll( numbers_canNotFill );
    259. if( point.getImpossibleNumbers() != null ){
    260. possibleNumbers.removeAll( point.getImpossibleNumbers() );
    261. }
    262. return possibleNumbers;
    263. }
    264. private static void calculatePossibleNumberForTargetRowAndCol(int targetRowNum, int targetColNum) {
    265. String code = getCode(targetRowNum, targetColNum);
    266. PointVO point = map_code_point.get(code);
    267. if( point.getNumber() != null ){
    268. return;
    269. }
    270. Set numbers_canNotFill = new HashSet<>();
    271. numbers_canNotFill.addAll( map_rowNum_numbers.get(targetRowNum) );
    272. numbers_canNotFill.addAll( map_colNum_numbers.get(targetColNum) );
    273. int gongNum = getGongNum(targetRowNum, targetColNum);
    274. numbers_canNotFill.addAll( map_gongNum_numbers.get(gongNum) );
    275. List numbers_possible = new ArrayList<>();
    276. for (int i = 1; i <=9 ; i++) {
    277. numbers_possible.add( String.valueOf( i ) );
    278. }
    279. numbers_possible.removeAll( numbers_canNotFill );
    280. if( point.getImpossibleNumbers() != null ){
    281. numbers_possible.removeAll( point.getImpossibleNumbers() );
    282. }
    283. point.setPossibleNumbers( numbers_possible );
    284. point.setPossibleNumbers_bak( deepCopyList( numbers_possible ) );
    285. point.setTryNumber( null );
    286. }
    287. private static String getSingleMissingNumber(Set numbers) {
    288. if( numbers == null || numbers.size() != 8 ){
    289. return null;
    290. }
    291. int sum = 0;
    292. for( String number:numbers ){
    293. sum += Integer.valueOf( number );
    294. }
    295. // ps:45 = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9
    296. return String.valueOf( 45 - sum );
    297. }
    298. /**
    299. * 更新三个 map_xxxNum_numbers
    300. * @param rowNum
    301. * @param colNum
    302. * @param number
    303. */
    304. private static void addNumber2_map_xxxNum_numbers(int rowNum, int colNum, String number) {
    305. int gongNum = getGongNum(rowNum, colNum);
    306. map_gongNum_numbers.get( gongNum ).add( number );
    307. map_rowNum_numbers.get( rowNum ).add( number );
    308. map_colNum_numbers.get( colNum ).add( number );
    309. }
    310. private static void deleteNumberFrom_map_xxxNum_numbers(int rowNum, int colNum, String number) {
    311. init_map_xxxNum_numbers();
    312. int gongNum = getGongNum(rowNum, colNum);
    313. map_gongNum_numbers.get( gongNum ).remove( number );
    314. map_rowNum_numbers.get( rowNum ).remove( number );
    315. map_colNum_numbers.get( colNum ).remove( number );
    316. }
    317. private static void fillNumber(int rowNum, int colNum, String number) {
    318. System.out.println( "deep_recursion = " + deep_recursion );
    319. String code = getCode(rowNum, colNum);
    320. PointVO point = map_code_point.get(code);
    321. point.setNumber( number );
    322. count_filled++;
    323. if( gameSuccess() ){
    324. print();
    325. System.exit( 0 );
    326. }
    327. // 初始化 当前格子所在的行、列、宫的 numers集合
    328. init_map_xxxNum_numbers( rowNum,colNum );
    329. }
    330. /*
    331. - 2 - 4 - 9 1 - -
    332. 4 - 6 - 5 - - 8 9
    333. - 7 - - 8 3 - 2 4
    334. 7 1 - 5 3 - - - -
    335. - - - - 9 - 2 - -
    336. - - - - 4 - - - 7
    337. - 6 - - - - - - -
    338. - - 7 3 - - 8 - 1
    339. 3 4 - - - 5 - 6 -
    340. */
    341. private static int getGongNum(int rowNum, int colNum) {
    342. if( rowNum <= 3 ){
    343. if( colNum <= 3 ){
    344. return 1;
    345. }else if( colNum <= 6 ){
    346. return 2;
    347. }else {
    348. return 3;
    349. }
    350. }else if( rowNum <= 6 ){
    351. if( colNum <= 3 ){
    352. return 4;
    353. }else if( colNum <= 6 ){
    354. return 5;
    355. }else {
    356. return 6;
    357. }
    358. }else {
    359. if( colNum <= 3 ){
    360. return 7;
    361. }else if( colNum <= 6 ){
    362. return 8;
    363. }else {
    364. return 9;
    365. }
    366. }
    367. }
    368. private static String getCode(int rowNum, int colNum) {
    369. return rowNum + "-" + colNum;
    370. }
    371. public static Map points2CodeAndPointMap( List points ){
    372. Map map_code_point = new HashMap<>();
    373. for( PointVO point:points ){
    374. map_code_point.put( point.getCode(),point );
    375. }
    376. return map_code_point;
    377. }
    378. public static void print( ){
    379. System.out.println();
    380. System.out.println( "--------------------------------------------------------------------------------------" );
    381. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    382. for (int colNum = 1; colNum <=9 ; colNum++) {
    383. String code = getCode( rowNum,colNum );
    384. PointVO point = map_code_point.get(code);
    385. if( point.getNumber() == null ){
    386. System.out.print( "-" + " ");
    387. }else {
    388. System.out.print( point.getNumber() + " ");
    389. }
    390. if( colNum % 3 == 0 ){
    391. System.out.print(" ");
    392. }
    393. }
    394. System.out.println();
    395. if( rowNum % 3 ==0 ){
    396. System.out.println();
    397. }
    398. }
    399. }
    400. public static void printPossibles( ){
    401. System.out.println();
    402. System.out.println( "--------------------------------------------------------------------------------------" );
    403. Map map_colNum_maxLen = new HashMap<>();
    404. for (int colNum = 1; colNum <=9; colNum++) {
    405. int maxLen = 1;
    406. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    407. String code = getCode(rowNum, colNum);
    408. PointVO point = map_code_point.get(code);
    409. if( point.getNumber() != null ){
    410. continue;
    411. }
    412. List possibleNumbers = point.getPossibleNumbers();
    413. if( possibleNumbers.size() > maxLen ){
    414. maxLen = possibleNumbers.size();
    415. }
    416. }
    417. maxLen+=2;
    418. map_colNum_maxLen.put( colNum,maxLen );
    419. }
    420. for (int rowNum = 1; rowNum <=9 ; rowNum++) {
    421. for (int colNum = 1; colNum <=9 ; colNum++) {
    422. String code = getCode( rowNum,colNum );
    423. PointVO point = map_code_point.get(code);
    424. String value = null;
    425. if( point.getNumber() == null ){
    426. value = "[" + getStickTogetherFormat( point.getPossibleNumbers() ) + "]";
    427. }else {
    428. value = point.getNumber();
    429. }
    430. int maxLen = map_colNum_maxLen.get( colNum );
    431. if( value.length() < maxLen ){
    432. value += getBlank( maxLen - value.length() );
    433. }
    434. System.out.print( value + " ");
    435. if( colNum % 3 == 0 ){
    436. System.out.print(" ");
    437. }
    438. }
    439. System.out.println();
    440. if( rowNum % 3 ==0 ){
    441. System.out.println();
    442. System.out.println();
    443. }
    444. }
    445. }
    446. private static String getBlank(int count) {
    447. String blank = "";
    448. for (int i = 0; i < count; i++) {
    449. blank += " ";
    450. }
    451. return blank;
    452. }
    453. private static String getStickTogetherFormat(List list) {
    454. if( list == null || list.size() == 0 ){
    455. return "";
    456. }
    457. String str = "";
    458. for( String item:list ){
    459. str += item;
    460. }
    461. return str;
    462. }
    463. public static List initChuPan(int[][] chupan) {
    464. List points = new ArrayList<>();
    465. for (int rowNum = 0; rowNum < 9; rowNum++) {
    466. int[] row = chupan[rowNum];
    467. for (int colNum = 0; colNum <9 ; colNum++) {
    468. int number = row[colNum];
    469. String number_str = null;
    470. if( number > 0 && number < 10 ){
    471. count_filled++;
    472. number_str = String.valueOf( number );
    473. }
    474. points.add( new PointVO(number_str,rowNum+1,colNum+1 ) );
    475. }
    476. }
    477. return points;
    478. }
    479. }

  • 相关阅读:
    [vs2017]_[初级]_[常用快捷键*持续更新]
    两个重要的实现模型 AQS和CAS
    洪泛法:计算机网络中的信息洪流——原理、优化与应用全景解析
    uniapp微信小程序半屏跳转小程序
    LeetCode 6. Z 字形变换 找规律
    终端查看端口号并结束进程
    Apache Knox安装测试
    SpringCache_概述、Cacheable、更新缓存、删除缓存、从0搭建缓存项目
    YOLO系列目标检测算法-YOLOv7
    【进阶篇】Java 实际开发中积累的几个小技巧(一)
  • 原文地址:https://blog.csdn.net/heshiyuan1406146854/article/details/133942606