我对Suduku的一个循环排除算法

本文介绍了一种基于排除法的数独游戏解决方案,通过Java编程实现了一个能够自动求解特定数独谜题的程序。文章详细展示了如何利用候选数字进行逐步排除,最终找到唯一解的过程。

昨天晚上,在kfc网站看到了一个玩游戏赢游戏机的宣传.

打开一看,原来是sudoku 81宫格游戏.对这个游戏,以前我曾经看到过,没有怎么留意,今天来了兴趣,

玩了一会,没有进展,有点着急了.心想何不用程序来算一下?

算法比较笨,采用的是排除法. 希望能籍此能得到各位朋友的更好算法

根据所在行,所在列,所在3X3 宫格的数字,确定该格子数字的侯选数字,然后再逐步排除.

 

下面是我的代码:

 

package dyt.game;
import java.util.ArrayList;
import java.util.List;
/**
 * 每个宫格是个对象
 * @author Tom
 * ValueObject.java
 *
 */
public class ValueObject {
 
  private List<Integer> values=new ArrayList<Integer>();
  private int value=0;
  public int getX() {
   return x;
  }
  public int getY() {
   return y;
  }
  public void setX(int x) {
   this.x = x;
  }
  public void setY(int y) {
   this.y = y;
  }
  public ValueObject(){
   
  }
  public int getValue() {
   return value;
  }
  private int x,y;
  public ValueObject(int value,int x,int y){
   this.value=value;
   this.x=x;
   this.y=y;
   addValue(1);
   addValue(2);
   addValue(3);
   
   addValue(4);
   addValue(5);
   addValue(6);
   
   addValue(7);
   addValue(8);
   addValue(9);   
   
  }
  public void setValue(int value) {
   this.value = value;
  }
  public List getValues() {
   return values;
  }
  public void setValues(List<Integer> values) {
   this.values = values;
  }
  public void addValue(Integer value){
   if(!this.values.contains(value))
    this.values.add(value);
  }
  //注意不要把Integer,写成了int
  //那样调用list.remove 的时候会出错.
  //因为我们这里是期望直接移动对象,
  //但是如果使用int,就回按照index移动.
  public void removeValue(Integer value1){
   if(this.values.contains(value1)){
    this.values.remove(value1);    
   }
   if(this.values.size()==1)
    this.value=this.values.get(0);
   //千万不能合并,合并就会出错.
   if(this.values.size()==1)
    values.clear();
   
  }
}
package dyt.game;
import java.util.Iterator;
/**
 * Sudoku.java
 * @author Tom
 *
 */
public class Sudoku {
 private boolean isok=false;
 public ValueObject o[][]= new ValueObject[9][9];
 //判断只有一个
 public void isOne(){
  /**
   * 已知的数据
   */
  int  a[][]={
    {7, 0, 0, 0, 0, 0, 8, 4, 0},
    {0, 0, 3, 7, 5, 0, 6, 0, 0},
    {1, 0, 0, 9, 0, 2, 0, 0, 0},
    {0, 9, 5, 3, 0, 7, 2, 0, 0},
    {6, 2, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 8, 6, 0, 4, 0, 9, 0},
    {0, 0, 0, 2, 0, 9, 0, 6, 4},
    {9, 0, 4, 0, 3, 0, 7, 0, 0},
    {0, 6, 2, 4, 0, 1, 0, 0, 3}
  };
//  赋值给数组
  for(int i=0;i<9;i++){
   for(int j=0;j<9;j++){
    o[i][j]=new ValueObject(a[i][j],i,j);
   }
  }
  
  //剔除不允许的值
  for(int i=0;i<9;i++){
   for(int j=0;j<9;j++){
    if(o[i][j].getValue()==0){
     o[i][j]=this.removeSame(o[i][j],a);     
    }else{
     o[i][j].getValues().clear();
    }
     
   }
   
  }
  
  System.out.println("可选值和已知值");
  print(o);
  while(!isok){
   o=remove(o);
   System.out.println("筛选");
   print(o);
  }
 }
 public ValueObject[][] remove (ValueObject o[][]){
  isok=true;
  for(int a=0;a<9;a++){
   for(int b=0;b<9;b++){
    ValueObject oo=o[a][b];
    //如果这个数已经确定
    //那么横向,纵向,所在方格内,不能再有这个数.
    if(oo.getValue()!=0){      
     o=removeSame1(o, a,b);     
    }                       
    if(o[a][b].getValues().size()>0){     
     o=removeSame2(o,a,b);  
     isok=false;
    }         
   }   
  }
  return o;
 }
 public void print(ValueObject o[][]){
  System.out.println("");
  System.out.println("---------------------------------");
  for(int i=0;i<9;i++){
   for(int j=0;j<9;j++){
    if(o[i][j].getValue()==0){
     Iterator it=o[i][j].getValues().iterator();
     while (it.hasNext()){      
      System.out.print(it.next()+" ");       
     }     
    }
    else {
     System.out.print(o[i][j].getValue());
    }    
    if(j==8){
     System.out.println("");     
    }else{
     System.out.print(",");
    }
   }
  }  
 }
 /**
  *剔除 该方格侯选值.
  * $Author:Tom
  */
 public  ValueObject[][] removeSame2 (ValueObject old[][] ,int x1,int y1){
  
  
  int x2=x1-(x1+3)%3;
  int y2=y1-(y1+3)%3;
  
  for(int c=x2;c<x2+3&&c!=x1;c++)
   for(int d=y2;d<y2+3&&d!=y1;d++){
    old[x1][y1].removeValue(old[c][d].getValue());
   }     
  for(int d=0;d<9&&d!=y1;d++){
   old[x1][y1].removeValue(old[x1][d].getValue());
    
  }
  for(int c=0;c<9&&c!=x1;c++){
   old[x1][y1].removeValue(old[c][y1].getValue());     
  }
  
  return old;
 }
 /**
  * 剔除与这个格子相关的其他格子内的这个值
  * $Author:Tom
  */
 public  ValueObject[][] removeSame1(ValueObject old[][],int x1,int y1){  
  
  int x2=x1-(x1+3)%3;
  int y2=y1-(y1+3)%3;
  
  //3X3方格
  for(int c=x2;c<x2+3&&c!=x1;c++){
   for(int d=y2;d<y2+3&&d!=y1;d++){
    old[c][d].removeValue(old[x1][y1].getValue());
   }
  }
        
  for(int d=0;d<9&&d!=y1;d++){
   o[x1][d].removeValue(old[x1][y1].getValue());   
  }
  for(int c=0;c<9&&c!=x1;c++){
   o[c][y1].removeValue(old[x1][y1].getValue());   
  }
  return old;
 }
 
 public ValueObject removeSame (ValueObject old,int a[][]){
  int x=old.getX()-old.getX()%3;
  int y=old.getY()-old.getY()%3;
  
  for(int i=x;i<x+3;i++)
   for(int j=y;j<y+3;j++)
    old.removeValue(a[i][j]);
  
  for(int j=0;j<9;j++){
   old.removeValue(a[old.getX()][j]);
  }
  for(int i=0;i<9;i++){
   old.removeValue(a[i][old.getY()]);
  }
  return old;
 }
 /**
  * $Author:Tom
  */
 public static void main(String[] args) {
  // TODO Auto-generated method stub
  
   Sudoku s=new Sudoku();
   s.isOne();
  
 }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值