基于第二次数独游戏,在此基础上进行添加GUI界面,GUI界面代码如下:创建一个ShuduGUI类。
1 package sudoku; 2 import javax.swing.*; 3 import java.awt.*; 4 import java.awt.event.*; 5 import java.util.Random; 6 7 public class ShuduGUI extends JFrame{ 8 private static JTextField a[][]=new JTextField[9][9]; //存储文本框中的数字 9 static int check[][]=new int[9][9]; //存储输入后的两位数组 10 GenerateNumber example=new GenerateNumber(); //产生数字 11 public int right[][]=example.GenerateNumberMatrix(); 12 public int rightans[][]; 13 private int[][] blank(int a[][]){ //挖空 14 Random c=new Random(); 15 int a1,a2; 16 a1=c.nextInt(9); 17 a2=c.nextInt(9); 18 for(int i=0;i<100;i++) 19 { 20 a[a1][a2]=0; 21 a1=c.nextInt(9); 22 a2=c.nextInt(9); 23 } 24 return a; 25 } 26 public ShuduGUI(){ //画GUI界面 27 Container r=getContentPane(); 28 r.setLayout(new BorderLayout(2, 1)); //边框布局 29 JMenuItem jmiOk=new JMenuItem("提交"); //定义菜单 30 JMenuItem jmiExplain=new JMenuItem("提示"); 31 JPanel panel=new JPanel(); //定义一个容器 32 panel.add(jmiOk); //将菜单在容器内显示 33 panel.add(jmiExplain); 34 JPanel p1=new JPanel(new GridLayout(9,9,5,5)); //定义9行9列的网格布局 35 add(panel,BorderLayout.NORTH); //将菜单放置在北面 36 add(p1,BorderLayout.CENTER); //将数字放置在正中间 37 rightans=blank(right); 38 for(int k=0;k<9;k ++) 39 { 40 for(int n=0;n<9;n++) 41 { 42 if(rightans[k][n]!= 0) 43 { 44 a[k][n]=new JTextField(""+rightans[k][n]); 45 a[k][n].setHorizontalAlignment(SwingConstants.CENTER);//将数字水平居中 46 a[k][n].setEditable(false); //只可显示不可修改 47 p1.add(a[k][n]); //添加文本框 48 } 49 else 50 { 51 a[k][n]=new JTextField(); 52 a[k][n].setHorizontalAlignment(SwingConstants.CENTER); 53 p1.add(a[k][n]); 54 } 55 } 56 } 57 add(p1); //将数字面板显示在容器里 58 jmiOk.addActionListener(new ActionListener(){//匿名创建事件监听器 59 @Override 60 public void actionPerformed(ActionEvent e) 61 { 62 if(gettext()==1) 63 { 64 if(judge()==true) 65 { 66 JOptionPane.showMessageDialog(null, "Your answer is right!","Result",JOptionPane.INFORMATION_MESSAGE); 67 } 68 else 69 { 70 JOptionPane.showMessageDialog(null, "Your answer is wrong!","Result",JOptionPane.INFORMATION_MESSAGE); 71 } 72 } 73 } 74 }); 75 explainListenerClass listener2=new explainListenerClass(); 76 jmiExplain.addActionListener(listener2); 77 messageListenerClass listener3=new messageListenerClass(); 78 } 79 static int gettext() //获取挖空文本框的文字 内容 80 { 81 int i,j; 82 for(i=0;i<9;i++) 83 { 84 for(j=0;j<9;j++) 85 { 86 check[i][j]=0; 87 } 88 } 89 for(int k=0;k<9;k++) 90 { 91 for(int n=0;n<9;n++) 92 { 93 try //异常处理 94 { 95 check[k][n] = Integer.parseInt(a[k][n].getText()); 96 //将答案类型转换之后传给check 97 } 98 catch(NumberFormatException nfe) 99 { 100 JOptionPane.showMessageDialog(null,"数据中包括非数字,请重新输入"); 101 return 0; 102 } 103 } 104 } 105 return 1; 106 } 107 public static boolean judge() //判断输入的答案是否正确 108 { 109 int i,j,k; 110 int [][]answer=check; 111 112 for(i=0;i<9;i++) 113 { 114 if(judge9(answer[i])==false) //判断每列是否有重复数字 115 return false; 116 } 117 for(j =0;j<9;j++) //判断每行是否有重复数字 118 { 119 120 int[] newAnswerColumn=new int[9]; 121 for(i =0;i<9;i++) 122 { 123 newAnswerColumn[i]=answer[i][j]; 124 } 125 if(judge9(newAnswerColumn)==false) 126 return false; 127 } 128 for(i=0;i<3;i++) //判断每个小九宫格内是否有重复数字 129 { 130 for(j=0;j<3;j++) 131 { 132 k=0; 133 int[] newAnswer=new int[9]; 134 for(int m=i*3;m) 135 { 136 for(int n=j*3;n) 137 { 138 newAnswer[k]=answer[m][n]; 139 k++; 140 } 141 } 142 if(judge9(newAnswer)==false) 143 { 144 return false; 145 } 146 } 147 } 148 return true; 149 } 150 public static boolean judge9(int[] answer) 151 { 152 int i,j; 153 for(i=0;i<9;i++) 154 { 155 for(j=0;j<9;j++) 156 { 157 if(i==j) 158 continue; 159 if(answer[i]==answer[j]) //如果有重复的数字,返回false 160 { 161 return false; 162 } 163 } 164 } 165 return true; //没有重复数字,返回true 166 } 167 168 public static void main(String[] args) { 169 // TODO 自动生成的方法存根 170 JFrame frame=new ShuduGUI(); 171 frame.setTitle("数独游戏"); 172 frame.setSize(600,900); 173 frame.setLocationRelativeTo(null); 174 frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); 175 frame.setVisible(true); 176 } 177 } 178 class explainListenerClass implements ActionListener{ //事件监听器 179 @Override 180 public void actionPerformed(ActionEvent e){ 181 JOptionPane.showMessageDialog(null, "填入数字保证每行每列及每个小的九宫格内数字无重复","Explain",JOptionPane.INFORMATION_MESSAGE); 182 } 183 }
数独棋盘(带挖空)的生成代码如下:创建一个GenerateNumber类。
1 package sudoku; 2 import java.util.Random; 3 4 public class GenerateNumber{ 5 private Random random=new Random(); 6 private static final int MAXTIMES=220; 7 private int currentTimes=0; 8 public int[][] GenerateNumberMatrix(){ 9 // TODO 自动生成的方法存根 10 int[][] randomMatrix=new int[9][9]; 11 for (int row=0;row<9;row++){ 12 if (row==0){ 13 currentTimes=0; 14 randomMatrix[row]=buildRandomArray(); 15 } 16 else{ 17 int[] tempRandomArray=buildRandomArray(); 18 for (int col=0;col<9;col++){ 19 if (currentTimes<MAXTIMES){ 20 if (!isCandidateNmbFound(randomMatrix,tempRandomArray,row,col)){ 21 resetValuesInRowToZero(randomMatrix,row); 22 row-=1; 23 col=8; 24 tempRandomArray=buildRandomArray(); 25 } 26 } 27 else{ 28 row=-1; 29 col=8; 30 resetValuesToZeros(randomMatrix); 31 currentTimes=0; 32 } 33 } 34 } 35 } 36 return randomMatrix; 37 } 38 private void resetValuesInRowToZero(int[][] matrix,int row){ 39 // TODO 自动生成的方法存根 40 for (int j=0;j<9;j++){ 41 matrix[row][j]=0; 42 } 43 } 44 private void resetValuesToZeros(int[][] matrix){ 45 // TODO 自动生成的方法存根 46 for (int row=0;row<9;row++){ 47 for (int col=0;col<9;col++){ 48 matrix[row][col]=0; 49 } 50 } 51 } 52 private boolean isCandidateNmbFound(int[][] randomMatrix,int[] randomArray,int row,int col){ 53 // TODO 自动生成的方法存根 54 for (int i=0;i<9;i++){ 55 randomMatrix[row][col]=randomArray[i]; 56 if (noConflict(randomMatrix,row,col)){ 57 return true; 58 } 59 } 60 return false; 61 } 62 private boolean noConflict(int[][] candidateMatrix,int row,int col){ 63 // TODO 自动生成的方法存根 64 return noConflictInRow(candidateMatrix,row,col)&&noConflictInColumn(candidateMatrix,row,col) && noConflictInBlock(candidateMatrix, row, col); 65 } 66 private boolean noConflictInRow(int[][] candidateMatrix,int row,int col){ 67 // TODO 自动生成的方法存根 68 int currentValue=candidateMatrix[row][col]; 69 for (int colNum=0; colNum){ 70 if (currentValue==candidateMatrix[row][colNum]){ 71 return false; 72 } 73 } 74 return true; 75 } 76 private boolean noConflictInColumn(int[][]candidateMatrix,int row,int col){ 77 // TODO 自动生成的方法存根 78 int currentValue=candidateMatrix[row][col]; 79 for (int rowNum=0;rowNum ){ 80 if (currentValue==candidateMatrix[rowNum][col]){ 81 return false; 82 } 83 } 84 return true; 85 } 86 private boolean noConflictInBlock(int[][] candidateMatrix,int row,int col){ 87 // TODO 自动生成的方法存根 88 int baseRow=row/3*3; 89 int baseCol=col/3*3; 90 for (int rowNum=0;rowNum<8;rowNum++){ 91 if (candidateMatrix[baseRow+rowNum/3][baseCol+rowNum%3]==0){ 92 continue; 93 } 94 for (int colNum=rowNum+1;colNum<9;colNum++){ 95 if (candidateMatrix[baseRow+rowNum/3][baseCol+rowNum%3]==candidateMatrix[baseRow+colNum/3][baseCol+colNum%3]) 96 { 97 return false; 98 } 99 } 100 } 101 return true; 102 } 103 private int[] buildRandomArray(){ 104 // TODO 自动生成的方法存根 105 currentTimes++; 106 int[] array=new int[]{1,2,3,4,5,6,7,8,9}; 107 int randomInt = 0; 108 for (int i=0;i<20;i++){ 109 randomInt=random.nextInt(8)+1; 110 int temp=array[0]; 111 array[0]=array[randomInt]; 112 array[randomInt]=temp; 113 } 114 return array; 115 } 116 public int getCurrentTimes(){ 117 // TODO 自动生成的方法存根 118 return currentTimes; 119 } 120 public void setCurrentTimes(int currentTimes){ 121 // TODO 自动生成的方法存根 122 this.currentTimes=currentTimes; 123 } 124 }
运行效果截图如下:如图1所示,是运行效果图,图中有两个按钮,一个“提交”按钮,一个“提示”按钮,当答题者在空格区域内输完数字解题完毕,点击“提交”按钮,会立马显示答题者的答案正确与否,答错了提示“Your answer is wrong!”,答对了提示“Your answer is right!”,如图2所示,如果答题者未答完题就点击“提交”按钮,系统会显示“数据中包含非数字,请重新输入”,你是不能进行提交的,必须答完将所有空格填满才能进行提交,如图3所示,;如果不会写,点击“提示”按钮,会提示你该怎么填,其实这功能并未实现,点击“提示”按钮,只会提示你“填入数字保证每行每列及每个小的九宫格内数字无重复”,如图4所示。这提示对于答题者来说很鸡肋,除非没玩过数独的人才有那么一丁点作用。
图1
图2
图3
图4
备注:两个程序的代码已上传至coding:地址为:https://git.coding.net/AnanKing/ShuDu.git
2、程序运行的正确性以及性能分析:该游戏的GUI界面运行显示正常,有较为友好的游戏说明,只能提示数独题目中空格是否填满,以及答案是否错误等,性能一般。 3、心得:在本次做题过程中,一共花了4~5天的时间才做完,其中遇到的问题还是有很多的,幸运的是,我都把它解决了,解决问题的途径有两种方式,一种是上网百度,另一种就是问已经在工作的同学。此次题目是在上一次的基础上进行添加GUI界面,本科学习的时候,学了一点, 但是没学的怎么深,然后也就忘了,幸运的是,我大四校内生产实习的时候,结课的时候是完成一个五子棋小游戏开发, 也是用java写的,所以对画GUI界面还是有点印象,然后把以前写的代码找出来,然后看了一些时间,把以前遗忘的知识点回忆了一下,很多东西都已经忘的差不多, 然后又去查看官网的API文档重新温习,然后就进行写程序,但是期间还是遇到了一下问题,比如:怎么将棋盘进行挖空、怎么添加事件监听等,通过百度和问已经在工作的同学,然后将其解决了,在此感谢在百忙之中抽空出来帮我解决问题的同学,对他们的帮助表示感谢。通过此次作业,发现以前学的东西基本上都还给老师了,感觉有点羞愧,说明自己的动手能力还是比较差,本科期间所花时间在敲代码上还是比较少的,这也是现在我的一个主要问题,也是我现在需要加强改进的地方,加油吧。