GUI界面:
package cn.sf.sudoku1; import java.awt.*; import java.awt.event.*; import java.io.*; import javax.swing.*; public class GUI implements ActionListener { JButton submit = new JButton("Submit"); JLabel CorrOrWrong = new JLabel("---"); private static int[][] array; private static int[][] sudoku; private static JTextField[][] index = new JTextField[9][9]; //UI界面 public GUI (){ JFrame frame = new JFrame("Sudoku"); frame.setSize(500,500); submit.addActionListener(this); JPanel board = new JPanel(); JPanel panel = new JPanel(); board.setLayout(new GridLayout (9,9)); for (int i =0;i<9;i++) for (int j=0;j<9;j++){ index[i][j]=new JTextField(1); index[i][j].setText(""+sudoku[i][j]); if (sudoku[i][j]!=0) index[i][j].setEditable(false); board.add(index[i][j]); } frame.getContentPane().add(board); frame.getContentPane().add(submit,"South"); frame.getContentPane().add(CorrOrWrong, "North"); frame.setVisible(true); } public void actionPerformed(ActionEvent e){ if (e.getSource() == submit) { int[][] temp=submit(); write(temp); try { Thread.sleep(2000); } catch (InterruptedException r) { r.printStackTrace(); } if(testSudoku()) CorrOrWrong.setText("Correct!"); else CorrOrWrong.setText("Wrong!"); } } public boolean testSudoku() { return SudokuChecker.main(null); } public static int[][] submit(){ int[][]result = new int[9][9]; for (int i =0;i<9;i++) for (int j=0;j<9;j++){ try { result[i][j]=Integer.parseInt(index[i][j].getText()); }catch (Exception e){ result[i][j]=-1; } } return result; } public static int[][] readIn(){ int[][] array = new int [9][9]; int x=0; try { BufferedReader br = new BufferedReader(new FileReader("sudoku.txt")); String s; while ((s = br.readLine())!= null) { String[] parts = s.split(" "); for (int y=0;y<9;y++) array[x][y]=Integer.parseInt(parts[y]); x++; } br.close(); } catch (IOException e) { System.out.println("ERROR"); } return array; } public static void write(int[][] array){ try { PrintWriter pw = new PrintWriter(new FileWriter("output.txt")); for (int i=0;i<9;i++) { String s=""; for (int j=0;j<9;j++) s+=array[i][j]+" "; pw.println(s); } pw.close(); } catch (IOException e) { System.out.println("The following error occurred " + e); } } public static int[][] generate(){ int[][] temp = new int [9][9]; for (int i =0;i<9;i++) for (int j=0;j<9;j++){ temp[i][j]=array[i][j]; } int num=41; //输入41个数字 while (num>0){ int x=(int)(Math.random()*9); int y=(int)(Math.random()*9); if (temp[x][y]!=0){ temp[x][y]=0; num--; } } return temp; } public static void main(String[] args) { //打开数独 SudokuGenerator.main(null); try { Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); } array=readIn(); sudoku=generate(); for (int i = 0; i<9;i++){ for (int j=0;j<9;j++) System.out.print(array[i][j] + " "); System.out.println(); } new GUI(); } }
游戏运行检查:
package cn.sf.sudoku1; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; public class SudokuChecker{ private static int [] temp = new int [9]; private static int [][]sudoku = new int [9][9]; private static int RowCheck ( int[][] x) { for (int i=0; i<9; i++) { for (int j= 0; j<9; j++) temp[j] = x[i][j]; if ( Check (temp) == 0 ) return 0; } return 1; } //主检查功能 private static int Check (int[] y) { int lineartemp; for (int i=0; i<9; i++) { lineartemp = y[i]; for (int j=i+1; j<9; j++) { //搜索重复 if (y[j] == lineartemp) return 0; } } return 1; } //检查每列中的重复项 private static int ColumnCheck ( int[][] x) { for (int i=0; i<9; i++) { for (int j= 0; j<9; j++) temp[j] = x[j][i]; if ( Check (temp) == 0 ) return 0; } return 1; } //检查九个方格 private static int SquaresCheck (int[][] x) { //行列索引 int i,j,column,row,k; for (column=0; column <= 6; column += 3) { for (row=0; row <= 6; row += 3) { for (k=0, i=0; i<3; i++) { for (j=0; j<3; j++) temp[k++] = x[row+i][column+j]; } if (Check(temp) ==0) return 0; } } return 1; } public static int[][] readIn(){ int[][] array = new int [9][9]; int x=0; try { BufferedReader br = new BufferedReader(new FileReader("output.txt")); String s; while ((s = br.readLine())!= null) { String[] parts = s.split(" "); for (int y=0;y<9;y++) array[x][y]=Integer.parseInt(parts[y]); x++; } br.close(); } catch (IOException e) { System.out.println("ERROR"); } return array; } public static boolean main(String [] args) { sudoku = SudokuChecker.readIn(); //通过 if ( RowCheck(sudoku) == 0 || ColumnCheck(sudoku)==0 || SquaresCheck(sudoku)==0) return false; //失败 return true; } }
异常检查及管理:
package cn.sf.sudoku1; import java.io.FileNotFoundException; import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.util.Random; public class SudokuGenerator { private static Random rnd = new Random(); public static void main(String[]args) { int[][] board; do { board = new int[9][9]; board = SudokuGenerator.create(board, 0,0); } while(board == null); SudokuGenerator.createTXTFile(board); } private static int[][] create(int[][] ray, int row, int col){ try{ //用于检测数独谜题是否卡住的变量 int countLoop = 0; do{ if(countLoop ==10) {ray = cleanRow(ray, row); col = 0;} ray[row][col] = rnd.nextInt(9)+1; //return a number from 1 to 9. countLoop++; } while(!(testSquare(ray, row, col) && testColRow(ray, row, col))); countLoop = 0; //如果完成,返回提供的数组 if(row == 8 && col==8) return ray; //重启行 if(col==8) return create(ray, row+1, 0); //重启列 return create(ray, row, col+1); } catch (StackOverflowError e) { return null; } catch (NullPointerException e) { return null; } } //检查生成值是否在行列中 private static boolean testColRow(int[][] ray, int row, int col) { //检查列 for(int r = 0; r<row; r++) { if(ray[row][col] == ray[r][col]) return false; } //检查行 for(int c = 0; c<col; c++) { if(ray[row][col] == ray[row][c]) return false; } return true; } //检查生成值是否在方块中 private static boolean testSquare(int[][] ray, int row, int col) { //每个元素起始值 int rStart = 0, cStart = 0; //给每个元素设值 if(row/3 == 0 && col/3 == 0) {rStart = 0; cStart = 0;} //A else if(row/3 == 0 && col/3 == 1) {rStart = 0; cStart = 3;} //B else if(row/3 == 0 && col/3 == 2) {rStart = 0; cStart = 6;} //C else if(row/3 == 1 && col/3 == 0) {rStart = 3; cStart = 0;} //D else if(row/3 == 1 && col/3 == 1) {rStart = 3; cStart = 3;} //E else if(row/3 == 1 && col/3 == 2) {rStart = 3; cStart = 6;} //F else if(row/3 == 2 && col/3 == 0) {rStart = 6; cStart = 0;} //G else if(row/3 == 2 && col/3 == 1) {rStart = 6; cStart = 3;} //H else {rStart = 6; cStart = 6;} //I for(int r = rStart; r<(rStart+3); r++){ for(int c = cStart; c<(cStart+3); c++){ if(!(row==r && col == c) && ray[row][col] == ray[r][c]) return false; } } return true; } public static void toConsole(int[][] ray) { for(int r = 0; r<9; r++) { for(int c = 0; c<9; c++) { System.out.print(ray[r][c] + " "); } System.out.println(); } } //卡住时清理行 private static int[][] cleanRow(int[][] ray, int rInt) { int[][] newAr = new int[9][9]; for(int c = 0; c<9; c++) { for(int r = 0; r<rInt; r++) { newAr[r][c] = ray[r][c]; } } return newAr; } public static void createTXTFile(int[][] ray) { try { PrintWriter writer = new PrintWriter("sudoku.txt", "UTF-8"); for(int r = 0; r<9; r++) { for(int c = 0; c<9; c++) { writer.print(ray[r][c]+ " "); } writer.println(""); } writer.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } } }
接下来则是运行效果(使用说明):
设定预先值为41个。
请在空格处填充数字,
输入错误的话上方会提示输入有误。
输入正确的话也会显示“恭喜您输入正确!”
该程序运行顺利,并且代码已经长传至coding,传送门是: https://coding.net/u/dhlg_1810812006/p/sudikutest/git/tree/master
由于这次基于上一次要求更多,要多加很多判断。所以在网上也看了很多资料,也问了问Java能力比较好的朋友,解决一些不懂的问题,对文件输入输出流也更掌握了点,另外各种逻辑的判断也有所感悟,程序是一个很严谨的事情,每个细节都可能是造成程序错误的原因,让我对细节的把我也更加上心。程序缺点就是没有自动修正功能,以后有机会再去改进。