八数码(A*算法使用JAVA实现)

A*算法是一个很有名的算法,百度之星程序设计大赛的名字就是来源于A*算法,说道百度之星,还是很有挑战性的一种网络比赛,我就参加过一次,不过打击挺大的,但是我也看到了自己在算法方面的薄弱,需要自己更多的付出和努力。A*的关键是启发式函数,我们的目标是找出一个决策函数,这个决策函数决定从当前可选的状态集合中选择哪一个状态继续扩展,八数码是一个很不错的练习,我们这里的启发式函数为:f(n) = h(n) + g(n), h(n)表示不在位的棋子数目,g(n)表示当前节点的扩展深度,我们选择启发函数值小的节点进行扩展,这样就能更快地到达目标状态。

源代码如下:

package eight;
class Node {
int [][] num; //the the situation of the current node  
int depth; //the depth of the current node in the recursive tree  
Node parent; //the parent of the current node  
public Node(int[][] num, int depth, Node parent) {
this.num = num;
this.depth = depth;
this.parent = parent;
}
boolean equals(Node obj) {
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
if (this.num[i][j] != obj.num[i][j])
return false;
return true;
}
}package eight;
import java.util.*;

public class Eight {
static int[][] init = {{2, 8, 3}, {6, 5, 7}, {4, 1, 0}};
static int[][] obj = {{8, 5, 3}, {2, 0, 7}, {6, 4, 1}};
static ArrayList<Node> open = new ArrayList<Node>(); //open table  
static ArrayList<Node> close = new ArrayList<Node>(); //close table  
static int currentDepth; //current depth of current recursive tree  
static Node initNode; //initial node of eight number  
static Node objNode; //objective node of eight number  

static Node getNodeFromOpen()
{
int[] f = new int[open.size()];
int minValue = 999999;
int n = 0;

for (int i = 0; i < open.size(); ++i) {
f[i] = computeValue(open.get(i));
if (minValue > f[i]) {
n = i;
minValue = f[i];
}
}

Node resNode = open.get(n);
open.remove(n);
return resNode;
}

static int computeValue(Node obj) {
int counter = 0;
for (int i = 0; i < 3; ++i) 
for (int j = 0; j < 3; ++j) {
if (initNode.num[i][j] != objNode.num[i][j]) 
++counter;
}
return counter + currentDepth; 
}

static void outPutNode(Node node) {
Stack<Node> s = new Stack<Node>();
s.push(node);
Node temp = node.parent;
while (temp != null) {
s.push(temp);
temp = temp.parent;
}

while (!s.empty()) {
Node p = s.pop();
for (int i = 0; i < 3; ++i)
{
for (int j = 0; j < 3; ++j) 
System.out.print(p.num[i][j] + " ");
System.out.println();
}
System.out.println();
}
}
static void addOpenTable(Node node, Node parent) {
if (node.equals(objNode))
{
//output the result and return  
System.out.println("Find the result");
outPutNode(node);
System.exit(0);
}
int i = 0;
for (i = 0; i < open.size(); ++i)
if (open.get(i).equals(node))
break;

//not existed add it  
if (i == open.size())
open.add(node);
else //modify the parent  
{
open.get(i).parent = parent;
}
}

static void computeExtendedNodes(Node node) {
int i = 0, j = 0, k = 0, l = 0;
outer:
for (i = 0; i < 3; ++i) 
for (j = 0; j < 3; ++j) 
if (node.num[i][j] == 0)
break outer;
//left  
if (i - 1 >= 0 && i < 3) {
int[][] temp = new int[3][3];
for (k = 0; k < 3; ++k) 
for (l = 0; l < 3; ++l)
temp[k][l] = node.num[k][l];
temp[i-1][j] = 0;
temp[i][j] = node.num[i-1][j];
Node leftNode = new Node(temp, currentDepth, node);
addOpenTable(leftNode, node);
}

//right  
if (i + 1 < 3) {
int[][] temp = new int[3][3];
for (k = 0; k < 3; ++k)
for (l = 0; l < 3; ++l) 
temp[k][l] = node.num[k][l];
temp[i+1][j] = 0;
temp[i][j] = node.num[i+1][j];
Node rightNode = new Node(temp, currentDepth, node);
addOpenTable(rightNode, node);
}

//up  
if (j - 1 >= 0 && i < 3) {
int[][] temp = new int[3][3];
for (k = 0; k < 3; ++k) 
for (l = 0; l < 3; ++l) 
temp[k][l] = node.num[k][l];
temp[i][j-1] = 0;
temp[i][j] = node.num[i][j-1];
Node upNode = new Node(temp, currentDepth, node);
addOpenTable(upNode, node);
}

//down  
if (j + 1 < 3 && i < 3) {
int[][] temp = new int[3][3];
for (k = 0; k < 3; ++k) 
for (l = 0; l < 3; ++l)
temp[k][l] = node.num[k][l];
temp[i][j+1] = 0;
temp[i][j] = node.num[i][j+1];
Node downNode = new Node(temp, currentDepth, node);
addOpenTable(downNode, node);
}
}

public static void main(String[] args) {

Scanner cin = new Scanner(System.in);

//read initial situation from the console  
System.out.println("Please input the start situation:");
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
init[i][j] = cin.nextInt();

//read objective situation from the console  
System.out.println("Please input the end situation: ");
for (int i = 0; i < 3; ++i)
for (int j = 0; j < 3; ++j)
obj[i][j] = cin.nextInt();

initNode = new Node(init, 0, null);
objNode = new Node(obj, 0, null);

open.add(initNode);
while (!open.isEmpty()) {
//choose a node from open table based on the function of A*  
++currentDepth;
if (currentDepth == 80)  //if the recursive depth is up to 80 then exit  
break;
Node extendedNode = getNodeFromOpen();
close.add(extendedNode);
computeExtendedNodes(extendedNode);
}

System.out.println("Oops! Can't find the right path from start to end!");
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值