public class SudokuAlgo { // ³­À̵µ¿¡ µû¸¥ blind Cell ºí·Ï ¼ö ¼³Á¤ private static int [] levelBlindCount = new int [] {30,50,80}; public final int level1 = 0; public final int level2 = 1; public final int level3 = 2; // ÇعýÀ» À§ÇÑ Queue Å©±â ¼³Á¤ private static int queSize = 1024; // ºí·Ï Å©±â ¼³Á¤ public final static int widthCell = 3, heightCell = 3, block = 3; public final int totalWidthCell = widthCell*block, totalHeightCell = heightCell*block, totalCell = widthCell*heightCell*block*block, blockCell = widthCell*heightCell; // ¸Ê public int [] originalMap = new int[totalCell]; // ¹®Á¦ Ç®ÀÌ ´ä¾È public int [] blindMap = new int[totalCell]; // »ç¿ëÀÚ°¡ Ç®°Ô µÉ ¹®Á¦ // ÇعýÀ» À§ÇÑ Queue Data Ŭ·¡½º class MapQueData { int index; int number; int [] map = new int [totalCell]; } // Ŭ·¡½º »ý¼ºÀÚ public SudokuAlgo() { initMap(); } // ¸Ê ÃʱâÈ­ public void initMap() { int i = 0; for( i = 0 ; i < totalCell ; i++ ) { originalMap[i] = 0; blindMap[i] = 0; } } // ¹è¿­¿¡ µî·ÏµÈ ¼ö¸¦ Çϳª¾¿ °¡Á®¿À±â À§ÇÔ. public int getBlindNumber( int index ) { return blindMap[index]; } // °á°ú ÀÛ¼ºÈÄ °ª ºñ±³ (°á°ú º¸±â ¹öÆ° ½Ã »ç¿ë. 0ÀÌ Æ²¸°°Å, 1ÀÌ ¸Â´Â°Å) public int getComparResult() { for (int i = 0; i < totalCell; i ++) { if(originalMap[i] != blindMap[i]) return 0; } return 1; } // ƯÁ¤ À妽ºÀÇ Á¤´ä °ª º¸±â public int getOriginalNumber( int index ) { return originalMap[index]; } // ³­À̵µ ¹öÆ°¿¡ ³ÖÀ»¶§ ¾µ °Í. 0ÀÌ ½¬¿ò, 1ÀÌ º¸Åë, 2°¡ ¾î·Á¿ò. public void setDifficult(int diff) { blindMap(diff); } // ¸ÊÀ» Ãâ·ÂÇÑ´Ù. (È®ÀÎ ¿ëÀ¸·Î »ç¿ëµÇ¾ú´Ù.) private void printMap( int [] map ) { int x = 0, y = 0; System.out.print( "+======================+\n" ); for( y = 0 ; y < totalHeightCell ; y++ ) { System.out.print("|"); for( x = 0 ; x < totalWidthCell ; x++ ) { System.out.printf("%d ", map[x+y*totalHeightCell] ); if( ((x+1)%heightCell) == 0 ) System.out.print("| "); } System.out.print( "\n" ); if( ((y+1)%heightCell) == 0 ) System.out.print( "+----------------------+\n" ); } } // Original Map Ãâ·Â public void printOriginalMap() { printMap( originalMap ); } // Blind Map Ãâ·Â public void printBlindMap() { printMap( blindMap ); } // ¿À·ù °Ë»ç 3´Ü°è¸¦ ¼öÇàÇÏ¿© ÀÔ·ÂÇÑ ¼ýÀÚ¸¦ °Ë»ç private boolean checkValidNumber( int [] map, int inIndex, int inNumber ) { int index = 0, offset = 0; int i = 0; int curNum = 0; int step = 0; boolean [] seqNumFlag = new boolean[9]; assert( index < totalCell ); assert( inNumber <= blockCell ); // ¸Ê¿¡ °Ë»çÇÒ ¼ýÀÚ¸¦ ´ëÀÔ map[inIndex] = inNumber; // 3´Ü°è¿¡ °Éó °Ë»ç¸¦ ÇÑ´Ù. for( step = 0 ; step < 3 ; step++ ) { // ÃʱâÈ­ for( i = 0 ; i < blockCell ; i++ ) seqNumFlag[i] = false; // Offset °è»ê(¼Óµµ Çâ»óÀ» À§ÇØ) if( step == 0 ) // 3x3 Box °Ë»ç offset = (inIndex /(totalWidthCell*heightCell))*(totalWidthCell*heightCell) + ((inIndex%totalWidthCell)/widthCell)*widthCell; else if( step == 1 ) // °¡·Î ÁÙ °Ë»ç offset = (inIndex / totalWidthCell)*totalWidthCell; else if( step == 2 ) // ¼¼·Î ÁÙ °Ë»ç offset = (inIndex % totalHeightCell); for( i = 0 ; i < 9 ; i++ ) { // index °ª °è»ê if( step == 0 ) // 3x3 Box °Ë»ç index = offset + (i%widthCell) + (i/widthCell)*totalWidthCell; else if( step == 1 ) // °¡·Î ÁÙ °Ë»ç index = offset + i; else if( step == 2 ) // ¼¼·Î ÁÙ °Ë»ç index = offset + i*totalWidthCell; assert( index < totalCell ); curNum = map[index]; // ºóÄ­ ÀÏ °æ¿ì if( curNum == 0 ) continue; // SeqNumFlag ¹è¿­¿¡ Áߺ¹‰ç´ÂÁö ÇØ´ç ¼ýÀÚ¸¦ üũÇÑ´Ù. if( seqNumFlag[curNum-1] == false ) seqNumFlag[curNum-1] = true; else break; } if( i < 9 ) return false; } return true; } // ¿À·ù °Ë»ç 3´Ü°è¸¦ ¼öÇàÇÏ¿© ÀÔ·ÂÇÑ ¼ýÀÚ¸¦ °Ë»ç public boolean checkValidNumber( int index, int number ) { return checkValidNumber( blindMap, index, number ); } // ¸Ê »ý¼º±â public boolean makeOriginalMap() { int index = 0; int ranNum = 0; int [] numArray = new int[blockCell]; // Ç®ÀÌ MapQueData [] mapQueData = new MapQueData [queSize]; int head = 0; int i = 0; int totalRunCount = 0; int data = 0; // Map À» À§ÇÑ Queue Buffer ÇÒ´ç for( i = 0 ; i < queSize ; i++ ) mapQueData[i] = new MapQueData(); do { // ÀÌ¹Ì ¸Ê¿¡ µ¥ÀÌÅÍ°¡ ÀÖ´Ù¸é Åë°ú if( originalMap[index] != 0 ) { index++; continue; } for( i = 1 ; i <= blockCell ; i++ ) numArray[i-1] = i; // Push Index for( i = 1 ; i <= blockCell ; i++ ) { // 1~9 Áß ·£´ýÀ¸·Î Áߺ¹À» ¸·±â À§ÇØ // Table À» »ç¿ëÇÏ¿© 9¹ø ·£´ýÀ» ½ÇÇàÇϸé Ç×»ó 1~9°¡ ³ª¿Àµµ·Ï ÇÔ. ranNum = (int)(Math.random() * (blockCell+1-i)); data = numArray[ranNum]; numArray[ranNum] = numArray[blockCell-i]; // ¼ýÀÚ°¡ ¿À·ù³ªÁö ¾Ê´Â´Ù¸é Queue ¿¡ Push ÇÑ´Ù. if( checkValidNumber(originalMap, index, data) == true ) { mapQueData[head].index = index; mapQueData[head].number = data; // ÇöÀç ¸ÊÀ» ÀúÀå System.arraycopy(originalMap, 0, mapQueData[head].map, 0, totalCell); head++; if( head >= queSize ) return false; } totalRunCount++; } // Pop Index head--; // Pop ÇÏ¿© ¾òÀº ¸ÊÀÇ Á¤º¸¿Í µ¥ÀÌÅÍ ¼³Á¤ System.arraycopy(mapQueData[head].map, 0, originalMap, 0, totalCell); index = mapQueData[head].index; originalMap[index] = mapQueData[head].number; index++; if( index >= totalCell ) return false; totalRunCount++; }while( head > 0 ); System.out.printf("END (%d,%d) %d\nRunCount:%d\n", index%widthCell, index/heightCell, head, totalRunCount ); return true; } // ¹®Á¦ ÃâÁ¦Çϱâ À§ÇØ Level ¿¡ µû¶ó ¸ÊÀÇ ¼ýÀÚ¸¦ °¨Ãã public void blindMap( int level ) { int i = 0; int leftBlind = levelBlindCount[level]; assert( leftBlind > 0 ); System.arraycopy( originalMap, 0, blindMap, 0, totalCell ); while( leftBlind-- > 0 ) { i = (int)(Math.random() * totalCell); if( blindMap[i] == 0 ) continue; blindMap[i] = 0; } } // Original ¸Ê µ¥ÀÌÅÍ ¾ò±â public int [] getOriginalMap() { int [] map = (int [])originalMap.clone(); return map; } // blind ¸Ê µ¥ÀÌÅÍ ¾ò±â public int [] getBlindMap() { int [] map = (int [])blindMap.clone(); return map; } // blind ¸Ê¿¡ ¼ýÀÚ ÀÔ·ÂÇϱâ public boolean setDataBlindMap( int index, int number ) { if( blindMap[index] != 0 ) return false; blindMap[index] = number; return true; } // ÀÚµ¿À¸·Î ¹®Á¦ »ý¼º ¹× Blind public void autoMakeMap( int level ) { // ¸Ê ÃʱâÈ­ initMap(); // ¸Ê »ý¼º makeOriginalMap(); // Blind ¸Ê »ý¼º(3¹ø° ÀÎÀÚ´Â ³­À̵µ) blindMap( level ); } }