CJ玩数独,刷心机,一言不合就写解算程序(上)

CJ今天太上午太无聊,就下了个数独玩,结果没耐心,突发奇想不如写个程序解数独,一次努力,永久福利。于是就着手了。

CJ比较直,就像先写个界面出来看看,结果就是这样。


别说话,吻我。我知道这界面很丑。不要在意细节,能用就好。下面是代码。

package Soduko;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Resolving implements Runnable {
	
	private int k;//确认数量
	private int[][] sodu = new int[9][9];
	private Piece [][]piece = new Piece[9][9];
	
	private  ArrayList
   
   
    
    
     
     > line=new ArrayList
     
     
      
      
       
       >();//行
	private  List
       
        
        
          > list=new ArrayList 
          
          
            >();//列 private List 
            
            
              > grid=new ArrayList 
              
              
                >();//宫格 // private HashSet 
               
                 []list;//列 // private HashSet 
                
                  []grid;//宫格 public Resolving(int[][] sodu){ this.sodu = sodu; } //初始化 public void init(){ //初始化行列宫格 for (int i = 0; i < 9; i++) { line.add(new HashSet 
                 
                   ()); } for (int i = 0; i < 9; i++) { list.add(new HashSet 
                  
                    ()); } for (int i = 0; i < 9; i++) { grid.add(new HashSet 
                   
                     ()); } //初始化题目已给出的棋格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { piece[i][j]=new Piece(); if(sodu[i][j]!=0){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(sodu[i][j]); piece[i][j].setI(i); piece[i][j].setJ(j); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); } } } System.out.println("成功初始化"+k+"个棋格。"); showResult(); //初始化所有空格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if(sodu[i][j]==0){ piece[i][j].suspects.removeAll(line.get(i)); piece[i][j].suspects.removeAll(list.get(j)); piece[i][j].suspects.removeAll(grid.get(j/3+((int)i/3)*3)); // if(piece[i][j].getStatus()==1){ // // } } } } } @Override public void run() { System.out.println("初始化……"); init(); System.out.println("开始解算……"); while(true){ for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { check(i,j); } } if(k==81){ System.out.println("解算成功!"); showResult(); return; } } } //显示解算结果 public void showResult(){ for (int i = 0; i < 9; i++) { System.out.println(); if(i%3==0){ System.out.println(); } for (int j = 0; j < 9; j++) { System.out.print(piece[i][j].getValue()); if(j%3==2){ System.out.print(" "); } } } } //填入数 public void confirm(int i,int j){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(piece[i][j].getSuspects().iterator().next()); sodu[i][j]=piece[i][j].getValue(); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); System.out.println("i="+i+",j="+j+"填入数:"+sodu[i][j]+" k="+k); showResult(); update(i,j); } //检查是否可填入,如果嫌疑数只剩下一个,即填入数字。 public void check(int i,int j){ if(!piece[i][j].isStatus()&&piece[i][j].getSuspects().size()==1){ confirm(i,j); } } //更新嫌疑数。根据填入的数更新同行、列、宫格其他空格的嫌疑数。 public void update(int i,int j){ for (int m = 0; m < 9; m++) { if(!piece[i][m].isStatus()){ piece[i][m].suspects.remove(piece[i][j].getValue()); check(i,m); } } for (int m = 0; m < 9; m++) { if(!piece[m][j].isStatus()){ piece[m][j].suspects.remove(piece[i][j].getValue()); check(m,j); } } for(int m=((int)i/3)*3;m<((int)i/3)*3+3;m++){ for(int n=((int)j/3)*3;n<((int)j/3)*3+3;n++){ if(!piece[m][n].isStatus()){ piece[m][n].suspects.remove(piece[i][j].getValue()); check(m,n); } } } } } 
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   
界面大概就差不多,具体根据算法算出来的答案整合一下就行。

关键还是算法,真正有趣的地方。

思路一:

private  List<HashSet<Integer>> line=new ArrayList<HashSet<Integer>>();//行
private  List<HashSet<Integer>> list=new ArrayList<HashSet<Integer>>();//列
private  List<HashSet<Integer>> grid=new ArrayList<HashSet<Integer>>();//宫格

//初始化行列宫格
for (int i = 0; i < 9; i++) {
line.add(new HashSet<Integer>());
}
for (int i = 0; i < 9; i++) {
list.add(new HashSet<Integer>());
}
for (int i = 0; i < 9; i++) {
grid.add(new HashSet<Integer>());
}


新建这27个集合类,分别记录每一行、列、宫格已出现的数字。每个棋格排除自己所在的行、列、宫格已出现的数字,得出剩下的数字集Set<Integer> suspects。当剩下的数字集只剩下一个的时候,便是该棋格应填的数字。填入新数字后重新更新以上的集合类。

代码附上

解算代码

package Soduko;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

public class Resolving implements Runnable {
	
	private int k;//确认数量
	private int[][] sodu = new int[9][9];
	private Piece [][]piece = new Piece[9][9];
	
	private  ArrayList
   
   
    
    
     
     > line=new ArrayList
     
     
      
      
       
       >();//行
	private  List
       
        
        
          > list=new ArrayList 
          
          
            >();//列 private List 
            
            
              > grid=new ArrayList 
              
              
                >();//宫格 // private HashSet 
               
                 []list;//列 // private HashSet 
                
                  []grid;//宫格 public Resolving(int[][] sodu){ this.sodu = sodu; } //初始化 public void init(){ //初始化行列宫格 for (int i = 0; i < 9; i++) { line.add(new HashSet 
                 
                   ()); } for (int i = 0; i < 9; i++) { list.add(new HashSet 
                  
                    ()); } for (int i = 0; i < 9; i++) { grid.add(new HashSet 
                   
                     ()); } //初始化题目已给出的棋格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { piece[i][j]=new Piece(); if(sodu[i][j]!=0){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(sodu[i][j]); piece[i][j].setI(i); piece[i][j].setJ(j); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); } } } System.out.println("成功初始化"+k+"个棋格。"); showResult(); //初始化所有空格 for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { if(sodu[i][j]==0){ piece[i][j].suspects.removeAll(line.get(i)); piece[i][j].suspects.removeAll(list.get(j)); piece[i][j].suspects.removeAll(grid.get(j/3+((int)i/3)*3)); // if(piece[i][j].getStatus()==1){ // // } } } } } @Override public void run() { System.out.println("初始化……"); init(); System.out.println("开始解算……"); while(true){ for (int i = 0; i < 9; i++) { for (int j = 0; j < 9; j++) { check(i,j); } } if(k==81){ System.out.println("解算成功!"); showResult(); return; } } } //显示解算结果 public void showResult(){ for (int i = 0; i < 9; i++) { System.out.println(); if(i%3==0){ System.out.println(); } for (int j = 0; j < 9; j++) { System.out.print(piece[i][j].getValue()); if(j%3==2){ System.out.print(" "); } } } } //填入数 public void confirm(int i,int j){ k++; piece[i][j].setStatus(true); piece[i][j].setValue(piece[i][j].getSuspects().iterator().next()); sodu[i][j]=piece[i][j].getValue(); line.get(i).add(sodu[i][j]); list.get(j).add(sodu[i][j]); grid.get(j/3+((int)i/3)*3).add(sodu[i][j]); System.out.println("i="+i+",j="+j+"填入数:"+sodu[i][j]+" k="+k); showResult(); update(i,j); } //检查是否可填入,如果嫌疑数只剩下一个,即填入数字。 public void check(int i,int j){ if(!piece[i][j].isStatus()&&piece[i][j].getSuspects().size()==1){ confirm(i,j); } } //更新嫌疑数。根据填入的数更新同行、列、宫格其他空格的嫌疑数。 public void update(int i,int j){ for (int m = 0; m < 9; m++) { if(!piece[i][m].isStatus()){ piece[i][m].suspects.remove(piece[i][j].getValue()); check(i,m); } } for (int m = 0; m < 9; m++) { if(!piece[m][j].isStatus()){ piece[m][j].suspects.remove(piece[i][j].getValue()); check(m,j); } } for(int m=((int)i/3)*3;m<((int)i/3)*3+3;m++){ for(int n=((int)j/3)*3;n<((int)j/3)*3+3;n++){ if(!piece[m][n].isStatus()){ piece[m][n].suspects.remove(piece[i][j].getValue()); check(m,n); } } } } } 
                    
                   
                  
                 
                
               
              
             
            
           
          
         
       
      
      
     
     
    
    
   
   

棋格类代码
package Soduko;

import java.util.HashSet;
import java.util.Set;

public class Piece  {
	
	private int i,j;
	private boolean status = false;//状态:false表示未知,true表示已确定,1表示未确定
	public Set
    
    
     
      suspects=new HashSet
     
     
      
      ();//可能的结果
	private int value;//确定的值
	
	public Piece(){
		for (int z = 1; z < 10; z++) {
			suspects.add(z);
		}
	}
	
	public Set
      
      
       
        getSuspects() {
		return suspects;
	}
	public boolean isStatus() {
		return status;
	}

	public void setStatus(boolean status) {
		this.status = status;
	}

	public void setSuspects(Set
       
       
        
         suspects) {
		this.suspects = suspects;
	}

	public int getValue() {
		return value;
	}

	public void setValue(int value) {
		this.value = value;
	}

	public int getI() {
		return i;
	}

	public void setI(int i) {
		this.i = i;
	}

	public int getJ() {
		return j;
	}

	public void setJ(int j) {
		this.j = j;
	}
	
	
	
	
}

       
       
      
      
     
     
    
    

当然,仅仅靠这个算法是算不出答案。因为仅仅这算法很容易算到每个未确定的棋格都是2个或以上的嫌疑数。这也和我预期的一样,所以我也早早把上面那算法实现Runnable。接下来就要把更多接数独时人脑使用的方法转换为代码。等用空就把下篇完成了吧!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值