递归算法生成数独


/**
 *
 * 递归方法生成数独
 *
 * @author tiger
 * @date 2010-5-28 完成于公司
 *
 * 复杂度有点高,有空优化。
 */
public class sodu {

 private int[][] sodu = null;
 private int[] tai = null;
 
 /**
  * 构造方法
  * 因为每执行一次递归都会把数组tai元素全置为-1.
  * 所以在执行一次递归后需要重新给tai赋值。
  */
 public sodu(){
  
  do{
   this.init();
   
   tai = getMixArray();
   tiger(0,0,0,0); //upleft
   
   tai = getMixArray();
   tiger(0,3,0,3); //up
   
   tai = getMixArray();
   tiger(0,6,0,6); //upright
   
   tai = getMixArray();
   tiger(3,0,3,0); //left
   
   tai = getMixArray();
   tiger(3,6,3,6); //right
   
   tai = getMixArray();
   tiger(6,0,6,0); //downleft
   
   tai = getMixArray();
   tiger(6,3,6,3); //down
   
   tai = getMixArray();
   tiger(6,6,6,6); //downright
  }while(this.isHaveZero());
   
 }
 
 
 /**
  * 得到一个随机数组(元素1到9无重复)
  * @param array
  */
 private int[] getMixArray()
 {
  int[] array = {1,2,3,4,5,6,7,8,9};
  for (int i = 0; i < array.length; i++)
  {
   int rand = (int) (Math.random() * 9);
   int middle = array[i];
   array[i] = array[rand];
   array[rand] = middle;
  }
  return array;
 }
 
 
 /**
  * 初始化数独数组
  * 会初始化正中间的3*3矩阵
  */
 private void init()
 {
  sodu = new int[9][9];
  
  int[] array = this.getMixArray();
  for (int i = 0; i < 3; i++) {
   for (int j = 0; j < 3; j++) {
    sodu[3+i][3+j] = array[i * 3 + j];
   }
  } 
 }
 
 
 /**
  * 打印
  */
 public void print(){
  for (int i = 0; i < sodu.length; i++) {
   for (int j = 0; j < sodu[i].length; j++) {
    System.out.print(sodu[i][j] + " , ");
   } 
   System.out.println();
  }
 }
 
 
 /**
  * 递归方法
  *
  * 生成(i,j)处的值
  *
  * xi和xj 分别是初始调用该方法时的i和j
  * @return
  */
 private boolean tiger(int i, int j, int xi, int xj)
 {
  if(i - xi == 3)return true;
  for (int j2 = 0; j2 < tai.length; j2++) {
   if(tai[j2] != -1 && isGood(i,j,tai[j2]))
   {
    sodu[i][j] = tai[j2];
    tai[j2] = -1;
    if(j-xj < 2){
     if(tiger(i,j+1,xi,xj))
     {
      return true;
     }else{
      tai[j2] = sodu[i][j];
      sodu[i][j] = 0;
      continue;
     }
    }else{
     if(tiger(i+1,xj,xi,xj))
     {
      return true;
     }else{
      tai[j2] = sodu[i][j];
      sodu[i][j] = 0;
      continue;
     }
    }
   }
  }
  return false;
 }
 
 /**
  * 判断数字number是否可以用在坐标(x,y)处
  */
 private boolean isGood(int i, int j, int number) {
  for (int m = 0; m < 9; m++) {
   if (sodu[i][m] == number) {
    return false;
   }
  }
  for (int n = 0; n < 9; n++) {
   if (sodu[n][j] == number) {
    return false;
   }
  }
  return true;
 }

 /**
  * 判断数独数组中是否有0
  */
 private boolean isHaveZero()
 {
  for (int i = 0; i < sodu.length; i++) {
   for (int j = 0; j < sodu[i].length; j++) {
    if(sodu[i][j] == 0)
    {
     return true;
    }
   }
  }
  
  return false;
 }
 
 /**
  * 程序入口
  * @param args
  */
 public static void main(String[] args) {
  new sodu().print();
 }
 
}


/**
 * 打印结果如下:
 3 , 9 , 7 , 8 , 4 , 1 , 2 , 6 , 5 ,
 6 , 1 , 4 , 2 , 5 , 3 , 7 , 8 , 9 ,
 5 , 8 , 2 , 9 , 7 , 6 , 3 , 4 , 1 ,
 7 , 5 , 6 , 4 , 8 , 2 , 9 , 1 , 3 ,
 9 , 4 , 1 , 3 , 6 , 5 , 8 , 2 , 7 ,
 8 , 2 , 3 , 1 , 9 , 7 , 6 , 5 , 4 ,
 1 , 3 , 8 , 5 , 2 , 9 , 4 , 7 , 6 ,
 4 , 7 , 5 , 6 , 3 , 8 , 1 , 9 , 2 ,
 2 , 6 , 9 , 7 , 1 , 4 , 5 , 3 , 8 ,
 */

 

posted on 2010-06-06 13:21  台哥编程课堂  阅读(1097)  评论(0编辑  收藏  举报

导航