本文实例为大家分享了Java实现数独小游戏的具体代码,供大家参考,具体内容如下
题目要求:
制作一个数独游戏。数据游戏拼图由一个3*3的九宫格组成,每个格式又分成一个小九宫格,共九九八十一个小格子。游戏规则:游戏开始前会有一些格式了写好了1-9的数,在剩下的格式里填写1-9的数,直到把所有格式填满,要求任何一行或一列或者任一个小九宫中没有相同的数字。拼图示例如下:
任务要求:
(1) 可以根据在九宫格中初始给出的数字个数设定游戏难度,如初始给出30个数设定为难、35个数设定为中等难度、40个数设定为容易。
(2) 对于初始给出的数据要能验证题目的合法性(即验证给出数据本身是否符合游戏规则,行、列及小九宫中不能出现重复数字1-9),对玩游戏中填入的数字在提交后要能验证其正确性(任何一行或一列或者任一个小九宫中没有相同的数字)。
(3) 程序能保存玩家的信息、游戏记录以及成绩(最高分),并能够在游戏结束时查看玩家排名。
工作流程如下:
该数独游戏需要连接数据库,登录用户和保存数据记录,连接数据库创建表等暂不作显示。主要数独游戏部分(除去登录页面,注册页面,查看排名页面不做显示)分为Main(生成数独,将生成100个数独保存在文件中,也可以不保存,每次生成数独都为一次新的数独不做记录,效率较差)和Play(数独显示页面,同时包括填写数独和判断数独是否正确)两类。
1、Main类
package shudu; import java.awt.BorderLayout; import java.awt.Button; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.SystemColor; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.util.Random; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JPanel; public class Main { private int[][] Arry; //得到一个9*9的数独 private int[][] shudu; //挖空arry数组中的数字 private int[][] answer; //存储数独答案 private int[][] game; //最终数独 private int grade; private int[] row; //每一行的个数 private int[] col; //每一列的个数 private int[] places; //每一个九宫格的个数 private boolean flag=false; //读取文件名 private String filename=new String("C:\\Users\\liaolilan\\Desktop\\shudu.txt"); public static void main(String[] args){ Main mainer=new Main(); // mainer.UI(); } public void UI(){ for(int k=0;k<100;k++){ this.Arry=new int[9][9]; this.shudu=new int[9][9]; this.game=new int[9][9]; this.answer=new int[9][9]; this.row=new int[9]; this.col=new int[9]; this.places=new int[9]; this.grade=grade; flag=false; //初始化数组 for(int i=0;i<9;i++) row[i]=col[i]=places[i]=9; //调试 // this.answer=new int[9][9]; //最终答案存储再arry中 rand();//先产生15个随机数加上随机位置,一定需要随机生成,不然就会一直都是一个数组 for(int i=0;i<9;i++){ for(int j=0;j<9;j++) System.out.print(Arry[i][j]); System.out.println(); } dfs(Arry,0);//获得一个数组答案d // diger(grade);//挖空数组 //将100个数独写入文件中 try{ String data = ""; File file =new File(filename); //if file doesnt exists, then create it if(!file.exists()){ file.createNewFile(); } //true = append file FileWriter fileWritter = new FileWriter(filename,true); BufferedWriter bufferWritter = new BufferedWriter(fileWritter); bufferWritter.write(k+1+"\r\n"); for(int i=0;i<9;i++){ data=""; for(int j=0;j<9;j++){ data=data+answer[i][j]+""; } System.out.println(data); bufferWritter.write(data+"\r\n"); } bufferWritter.close(); System.out.println("Done"); }catch(IOException e){ e.printStackTrace(); } } } //随机给数 public void rand(){ int t=0; //t=14不随机性太高,容易产生没有解的数独,经过参考资料发现,当t=6的时候,几乎100%有解 while(t<6){ int x=new Random().nextInt(9); int y=new Random().nextInt(9); int i=new Random().nextInt(9)+1; if(Arry[x][y]==0){ if(istrue(Arry,x,y,i)){ //判断数是否能填 Arry[x][y]=i; t++; } } } } //判断在arry[x][y]上是否能放num public boolean istrue(int arry[][],int x,int y,int num){ //横竖是否有num for(int i=0;i<9;i++){ if(arry[x][i]==num||arry[i][y]==num) return false; } for(int i=(x/3)*3;i<(x/3+1)*3;i++) for(int j=(y/3)*3;j<(y/3+1)*3;j++) if(arry[i][j]==num) return false; return true; } //根据前面放的数获得一个正确的答案,dfs获取 public void dfs(int arry[][],int n){ if(n<81){ if(flag==true) return; int x=n/9;//x第N个数的横坐标 int y=n%9;//y第N个数的纵坐标 if(arry[x][y]==0){ //若第N个数为0,没有被填过,则判断0~9是否能被填 for(int i=1;i<10;i++){ if(istrue(arry,x,y,i)){ //第N个数可以填i,填入然后dfs arry[x][y]=i; dfs(arry,n+1); //dfs回溯 arry[x][y]=0; } } } else{ dfs(arry,n+1); } } else{ //获得第一个结果,flag置true!!!!! flag=true; //将获得的数组放入shudu中然后再挖空 //if(all==false){ for(int i=0;i<9;i++) for(int j=0;j<9;j++) shudu[i][j]=answer[i][j]=arry[i][j]; System.out.println("###################"); for(int i=0;i<9;i++){ for(int j=0;j<9;j++) System.out.print(arry[i][j]); System.out.println(); } } } //为了避免数独无解,保证数独有唯一解 //挖空数组,分难易程度,,grade为挖空个数 //是否有一个行、列、九宫格已经为空 boolean emptyrow=false,emptycol=false,emptyplaces=false; //挖空数、关卡 public void diger(int grade,int level){ this.shudu=new int[9][9]; this.game=new int[9][9]; this.answer=new int[9][9]; this.row=new int[9]; this.col=new int[9]; this.places=new int[9]; this.grade=grade; File file=new File(filename); BufferedReader reader = null; try { System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8")); // reader = new BufferedReader(new FileReader(file)); String tempString = null; int line = 1,k=0; boolean flag=false; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null&&k<9) { // 显示行号 System.out.println(" line " + line + ": " + tempString); if(tempString.equals(level+"")){ flag=true; continue; } if(flag==true){ for(int i=0;i<9;i++) answer[k][i]=tempString.charAt(i)-48; k++; } line++; } reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } for(int i=0;i<9;i++) for(int j=0;j<9;j++) shudu[i][j]=answer[i][j]; int t=grade; while(t>0){ //随机抽到x,y int x=new Random().nextInt(9); int y=new Random().nextInt(9); //若x,y没有被挖空则挖空x,y if(shudu[x][y]!=0){ row[x]--; col[y]--; places[(y/3)*3+x/3]--; if((row[x]==0&&emptyrow)||(col[y]==0&&emptycol)||(places[(y/3)*3+x/3]==0&&emptyplaces)) { System.out.println(x+" "+y+" 不可以"); continue; } else{ shudu[x][y]=0; t=t-1;} if(row[x]==0) emptyrow=true; if(col[y]==0) emptycol=true; if(places[(y/3)*3+x/3]==0) emptyplaces=true; } } //获得最终游戏数独 for(int i=0;i<9;i++) for(int j=0;j<9;j++) game[i][j]=shudu[i][j]; } //获得最终游戏数独 public int[][] getArr(){ int t=0; for(int i=0;i<9;i++){ for(int j=0;j<9;j++){ System.out.print(game[i][j]); if(game[i][j]==0) t++; } System.out.println(); } System.out.println("###################"); System.out.println("挖空数为:"+t); return this.game; } //获得答案数独 public int[][] getAnswer(){ for(int i=0;i<9;i++){ for(int j=0;j<9;j++) System.out.print(answer[i][j]); System.out.println(); } System.out.println("###################"); return this.answer; } }
2、Play类
package shudu; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.Font; import java.awt.GridLayout; import java.awt.SystemColor; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.FocusEvent; import java.awt.event.FocusListener; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.util.ArrayList; import java.util.List; import java.util.Timer; import java.util.TimerTask; import javax.swing.BorderFactory; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.border.Border; import SQLconnect.UserDao; import shudu.Main; import vo.User; //游戏界面的设计 public class Play { //设置全局变量,九宫格 JTextField[][] numberFields=new JTextField[9][9]; //游戏数独数组 int[][] gamearr=new int[9][9]; //游戏答案数组 int[][] answerarr=new int[9][9]; //灰色 Color green=new Color(93, 200, 138); Color lightGray = new Color(217, 217, 217); Color blue = new Color(102, 183, 255); //挖空数! private int grade=40; //过去的 private int usedgrade=0; //计时器 Timer time; JLabel timeLabel; TimerTask task; //用标签表示游戏进展 JLabel labelsc=new JLabel(); //创建字体,之后所有的字体为该字体 Font f=new Font("方正仿宋简体", Font.BOLD, 25); //选择九宫格中的格子的坐标 int sx=10; int sy=10; //是否已经看过答案 private boolean isanswer; //用户名 JLabel username=new JLabel(); JLabel usergrade=new JLabel(); private int gamegrade=0;//游戏分数 //登录 login loger=new login(); User user=loger.user; //读取文件名 private String filename=new String("C:\\Users\\liaolilan\\Desktop\\SuDoKu.txt"); //以前游戏数组 private int[][] usedgame=new int[9][9]; //以前的游戏时间 private int usedtim=1; //判断是不是新用户 //是否为新用户 private boolean isnew=true; //保存用户名存在在第几行 private int act=-1; //关卡 JLabel levels=new JLabel(); int levs=1; //窗口 private JFrame jf ; public Play(){ //制作游戏界面 System.out.println(user.getUsername()+" "+user.getUserpwd()+" "+user.getUsergrade()); jf = new JFrame(); jf.setTitle("数独游戏"); jf.setBounds(400, 0, 1100, 1000); jf.setResizable(false);//不允许窗口最大化 jf.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);//不执行任何操作;要求程序在已注册的 WindowListener 对象的 windowClosing 方法中处理该操作 jf.setLocationRelativeTo(null);//居中,不用定位窗口大小 jf.setVisible(true); //打开时,判断是否上一局游戏 jf.addWindowListener(new WindowAdapter() { @Override public void windowOpened(WindowEvent arg0) { //如果是新用户,保存数组 //保存记录,读取文件,读出文件,在开始游戏的时候读出 File file=new File(filename); BufferedReader reader = null; try { System.out.println("以行为单位读取文件内容,一次读一整行:"); reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8")); // reader = new BufferedReader(new FileReader(file)); String tempString = null; int line = 1; // 一次读入一行,直到读入null为文件结束 while ((tempString = reader.readLine()) != null) { // 显示行号 System.out.println(" line " + line + ": " + tempString); if(tempString.equals(user.getUsername())){ act=line; isnew=false; } else if(isnew==false){ //关卡 levs=Integer.valueOf(tempString); System.out.println(levs); break; } line++; } reader.close(); } catch (IOException e) { e.printStackTrace(); } finally { if (reader != null) { try { reader.close(); } catch (IOException e1) { } } } newGame(grade,levs); } }); //关闭时,保存关卡记录 jf.addWindowListener(new WindowAdapter() { @Override public void windowClosing(WindowEvent arg0) { BufferedReader reader = null; //保存记录,读取文件,读出文件,在开始游戏的时候读出 File file=new File(filename); int num=0;//第几行 boolean flag=false; System.out.println("act:"+act); List list = new ArrayList(); try{ reader = new BufferedReader(new InputStreamReader(new FileInputStream(file),"utf-8")); // reader = new BufferedReader(new FileReader(file)); String str = null; // 一次读入一行,直到读入null为文件结束 while ((str = reader.readLine())!= null) { ++num; System.out.println(num+"行:"+str); if(isnew==false&&(num==act||num==act+1)){ System.out.println(str); continue; } list.add(str); } }catch(IOException e){ e.printStackTrace(); } System.out.println("list size:"+list.size()); System.out.println("删除成功"); //重新写入 try{ FileWriter fileWritter = new FileWriter(filename); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(filename), "utf-8")); //BufferedWriter bw= new BufferedWriter(fileWritter); for( int i=0;i
最后生成数独页面的效果如下:
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。