Java实现数独小游戏

本文实例为大家分享了Java实现数独小游戏的具体代码,供大家参考,具体内容如下

题目要求:

制作一个数独游戏。数据游戏拼图由一个3*3的九宫格组成,每个格式又分成一个小九宫格,共九九八十一个小格子。游戏规则:游戏开始前会有一些格式了写好了1-9的数,在剩下的格式里填写1-9的数,直到把所有格式填满,要求任何一行或一列或者任一个小九宫中没有相同的数字。拼图示例如下:

Java实现数独小游戏_第1张图片

任务要求:

(1) 可以根据在九宫格中初始给出的数字个数设定游戏难度,如初始给出30个数设定为难、35个数设定为中等难度、40个数设定为容易。
(2) 对于初始给出的数据要能验证题目的合法性(即验证给出数据本身是否符合游戏规则,行、列及小九宫中不能出现重复数字1-9),对玩游戏中填入的数字在提交后要能验证其正确性(任何一行或一列或者任一个小九宫中没有相同的数字)。
(3) 程序能保存玩家的信息、游戏记录以及成绩(最高分),并能够在游戏结束时查看玩家排名。

工作流程如下:

Java实现数独小游戏_第2张图片

该数独游戏需要连接数据库,登录用户和保存数据记录,连接数据库创建表等暂不作显示。主要数独游戏部分(除去登录页面,注册页面,查看排名页面不做显示)分为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 
 

最后生成数独页面的效果如下:

Java实现数独小游戏_第3张图片

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

你可能感兴趣的:(Java实现数独小游戏)