JAVA下的第一个程序

来源:互联网 发布:vs2015中开发php 编辑:程序博客网 时间:2024/06/07 08:49

        本人是新手。没有系统学过编程的知识。只是对计算机比较感兴趣而已。这是自己写的第一个程序。当然具体方法都是借鉴他人的。但自己也在写的过程中学到了好多平时可能只是听说过,但没真正理解其实质的知识。发现看得懂一段程序是基础,而能自己写才是最重要的。很多时候看懂了,但自己再写就会各种报错。记录一下,当给自己的一种鼓励和鞭策。

        这个程序是关于八皇后问题的。按要求用回溯的算法去实现。代码如下。

        

/** * 回溯法解八皇后问题 * @author Frank */public class Queens {//以(0,0)为原点,皇后的坐标为(Column,Row=Row[Column]),Column为自变量------其实(0,0)应位于左上角public int QueensNum = 8; //皇后数量public int[] Row = new int[QueensNum];//皇后纵坐标,即皇后所在行    public boolean [] RowExist = new boolean [QueensNum];//皇后纵坐标即皇后所在行判断    public boolean [] DiaNEExist = new boolean [2*QueensNum-1];//皇后东北西南方向对角线判断    public boolean [] DiaNWExist = new boolean [2*QueensNum-1];//皇后西北东南方向对角线判断    public int count; //统计每种解法是第几种解        private void initial() {                       //将3个判断数组初始化,true表示可放皇后,false则相反    for(int i=0; i<=QueensNum-1; i++)    {    RowExist[i] = true;                         }    for(int i=0; i<=2*QueensNum-2; i++){    DiaNEExist[i]=DiaNWExist[i] = true;    }    }        public boolean Exist(int Column, int Row){  //皇后所在行及两条对角线统一判断                                            //参数Column是皇后的横坐标,即皇后所在列;Row是纵坐标,皇后所在行    return(RowExist[Row]&&                  //皇后所在行判断    DiaNEExist[Row-Column+QueensNum-1]&&    //对角线方程y=x+b,取值范围-7~7,为防止负数出现,故要加QueensNum-1    DiaNWExist[Row+Column]);                //对角线方程y=-x+b    }        public void print(){                        //打印结果    System.out.println("第"+count+"种解法");    for (int i=0; i<=QueensNum-1; i++){     //横坐标,列循环     for (int j=0; j<=QueensNum-1; j++){ //纵坐标,行循环        if(Row[i]==j){        System.out.print("0 ");        }        else{           System.out.print("+ ");        }    }    System.out.println();               //打印一行后换行       }         System.out.println();                   //打印一组解法之后的回车    }                                                   public void Test (int i){                        //i=Column,确定列数,即横坐标,通过递归函数省去了for循环    for(int j=0; j<=QueensNum-1;j++){        //j=Row循环,确定行数,即纵坐标       if(Exist(i, j)){          Row[i]=j;                          //确定放置皇后的坐标(Column,Row[Column])                    RowExist[j]=false;                 //以下三行将放置后的皇后所在行和对角线                                                                      DiaNEExist[j-i+QueensNum-1]=false; //改为不可放置别的皇后的状态。因循环以横坐标          DiaNWExist[j+i]=false;             //为自变量,所以可以不考虑所在列的状态改变                       if(i==7){                          //若已经遍历完所有横坐标,产生了一组放置方法,则打印皇后放置方法               count++;           print();                                   }                    else{Test (i+1);}                 //若没有遍历完所有横坐标,则递归,进行下一个皇后的放置                                            //也是下一步无可放置的皇后的情况下,Test(i+1)出栈后                                                  //Test(i)开始的位置                    RowExist[j]=true;                  //回溯。在下一步无可放置的皇后的情况下,将上一步皇后放置后                                                                  DiaNEExist[j-i+QueensNum-1]=true;  //产生的别的皇后不可放置的行和对角线取消          DiaNWExist[j+i]=true;              //以及在一组解出现之后,再将这组解的最后一个皇后坐标取消                                             //将其放置后所产生的别的皇后不可放置的的行和对角线取消       }              }        }        public static void main (String args[]){    Queens operate = new Queens();    System.out.println("纪念一下第一个程序");    System.out.println("---------------");    System.out.println();    operate.initial();    operate.Test(0);    } }

       在写得过程中明白了以下几点:

       1、栈的意义:递归会把上一个方法如Test(i)压在栈里,下一个方法Test(i+1)出栈后,会继续执行上一个方法Test(i)。所以递归的入口,也是下一方法出栈之后,上一方法继续执行的起点。正如本程序中的 else{Test (i+1);} 这一行。在Test(i+1)出栈后,会继续执行Test(i)下面的 else{Test (i+1);} 之后的语句,即将上一方法Test(i)下,放置正确的那个皇后形成的判断条件取消,也即回溯。程序就在递归和回溯的作用下不断运行。

       2、回溯的那三行语句。它既实现了Test(i+1)失败后,递归回Test(i)之后,将Test(i)中放置正确的皇后形成的判断条件取消的作用,也实现了在找到一种放置8个皇后的方法后,取消第八列上的那个放置正确的皇后形成的判断条件,使程序继续回溯递归,从而遍历所有放置方法的作用。因此,这段语句要放置在打印期盼的if else之后的原因。

       3、system.out.println()会自动换行而system.out.print()不会。所以在打印棋盘的+/0号时,要用到后者。

       4、自己写能使自己了解一些Java语言语法结构上的东西。如return();&&;||;for(; ; ;)等。


       当然也有未解的疑惑和问题:

      1、如何在main()方法的最开始就打印出会有多少种解法;

      2、想得知程序一共回溯、递归了多少次;

      3、想知道其他的非递归解法(据软开的哥们说,那个更简单,因为递归回溯在栈里压的程序太多,费资源)


      欢迎各位大大指正。也希望对新手们有所帮助。