前两天突然想做一个android拼图游戏的小程序玩一下,csdn博客上发现已经有人写过相关的程序,大致看了一下发现程序写的挺好的,我截取了其中的主要的代码试了一下,程序的界面如下:android程序http://pan.baidu.com/s/1kT5fA2j直接下载。
玩了一下被虐了,走了一会发现并不是想象那么好拼。擦,要不让计算机帮我算吧,算出最短的步骤给我,嘿嘿。
先把计算机算出来的结果,贴出来,待会给出程序。
1、result=31132441332424113242(1 2 3 4 代表左右上下)
2、翻译过来为:上左左上右 下下左上上 右下右下左 左上右下右
操作一下:
结果对了。
下面贴出程序:计算的工程是在PC上算的,计算量比较大,android要等好久,先贴Java程序:
1. AnswerUtil.java
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
public class AnswerUtil {
private int deltax[]={-1,1,0,0};
private int deltay[]={0,0,-1,1};
private String aimStr="123456780";
private String orangeData;
private int lineItems;
private DataItem dataItem;
private List<DataItem> queue =new ArrayList<DataItem>();
public AnswerUtil(String list,int n) {
orangeData=list;
lineItems=n;
queue.clear();
queue.add(new DataItem(orangeData, null,0,0));
}
public void getAnswer()
{
int queueindex=0;
while (queueindex<queue.size())
{
dataItem=queue.get(queueindex);
if(queueindex%1000==0)
System.out.println("queueindex="+queueindex);
int zero_xy=dataItem.getData().indexOf("0");
if(zero_xy==8)
{
if(dataItem.getData().equals(aimStr))
{
//find the answer
System.out.println("the ans pos="+queueindex);
printPath(queueindex);
break;
}
}
int zero_x=zero_xy%lineItems;
int zero_y=zero_xy/lineItems;
int new_x,new_y;
for(int i=0;i<4;i++)
{
new_x=zero_x+deltax[i];
new_y=zero_y+deltay[i];
if(new_x>=0&&new_x<lineItems&&new_y>=0&&new_y<lineItems)
{
String str=swap(dataItem.getData(), zero_xy, new_y*lineItems+new_x);
if(!isExist(str))
{
DataItem item=new DataItem(str, dataItem.getData(), i+1,queueindex);
queue.add(item);
}
}
}
queueindex++;
}
}
public String swap(String data,int old_xy,int new_xy)
{
String str="";
char[] array=data.toCharArray();
char tmp=array[old_xy];
array[old_xy]=array[new_xy];
array[new_xy]=tmp;
for(int i=0;i<array.length;i++)
str+=array[i];
return str;
}
public int getZeroXY(String str)
{
return str.indexOf("0");
}
private void printPath(int pos)
{
if(pos==0)
return ;
printPath(queue.get(pos).getParentPos());
System.out.print(queue.get(pos).getPtoC());
}
private boolean isExist(String str)
{
for(int i=0;i<queue.size();i++)
{
if(queue.get(i).getData().equals(str))
return true;
}
return false;
}
public void test()
{
String str=swap(orangeData, orangeData.indexOf("0"), orangeData.indexOf("2"));
}
public class DataItem
{
private int mParentPos;
private int mPtoC;//1 2 3 4 代表左右上下
private String mParent;
private String mData;
public DataItem(String data,String parent,int ptoc,int ppos) {
mData=data;
mParent=parent;
mPtoC=ptoc;
mParentPos=ppos;
}
public int getPtoC() {
return mPtoC;
}
public void setPtoC(int mPtoC) {
this.mPtoC = mPtoC;
}
public String getParent() {
return mParent;
}
public void setParent(String mParent) {
this.mParent = mParent;
}
public String getData() {
return mData;
}
public void setData(String mData) {
this.mData = mData;
}
public int getParentPos() {
return mParentPos;
}
public void setParentPos(int mParentPos) {
this.mParentPos = mParentPos;
}
}
}
2、Puzzle.java
public class Puzzle {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String str="573146820";
AnswerUtil answer=new AnswerUtil(str, 3);
answer.getAnswer();
}
}
将原图分成9块,分别编号为1234567890,所以一个打乱的编号比573146820,只要按照一定规则变换到原始的有序顺序就解决了问题。
主要的思想不是很难,主要是利用9宫格的状态图变换来进行计算的,具体的算法步奏如下:
1、将第一初始的状态push进队列queue,这里用List不用queue的目的是为了找到目标后可以递归回退回来找到路径,就是为了模拟queue但是数据不出队用的。
2、循环从队列取数据,先判断如果是目标状态就打印路径并返回,如果不是就从这个状态能变换到的状态都压入队列。
3、队列指针向后移动,知道队列为空。
计算的结果的速度可能要等一会,计算量有点大。下面再贴一下C++的代码,本来想用C++来提高计算速度的,结果不随人愿啊,比Java还慢受不了,可能还是代码有点问题,希望懂C++的可以看一下,具体的问题,有能提高效率的地方,大家可以积极留言。
#include <list>
#include <string>
#include <iostream>
using namespace std;
class DataItem
{
public:
int mPtoC;//1 2 3 4 代表左右上下
list<DataItem>::iterator *mParent;
string mData;
DataItem(string data,list<DataItem>::iterator *parent,int ptoc)
{
mData=data;
mParent=parent;
mPtoC=ptoc;
}
};
list<DataItem> datas;
string swap(string str,int x,int y);
int isExist(string str);
void printPath(list<DataItem>::iterator *idx);
int main()
{
int deltax[]={-1,1,0,0};
int deltay[]={0,0,-1,1};
string originalstr="573146820";
string aimstr="123456780";
DataItem item(originalstr,NULL,0);
list<DataItem>::iterator idx;
int lineItems=3;
int count=0;
datas.clear();
datas.push_back(item);
idx=datas.begin();
cout<<"calulator the result.please waiting ..."<<endl;
while(idx!=datas.end())
{
int zero_xy=idx->mData.find('0');
if(count++%1000==0)
cout<<count<<endl;
if(zero_xy==8)
{
if(idx->mData==aimstr)
{
//find the answer
cout<<"the ans pos="<<idx->mParent;
printPath(&idx);
break;
}
}
int zero_x=zero_xy%lineItems;
int zero_y=zero_xy/lineItems;
int new_x,new_y;
for(int i=0;i<4;i++)
{
new_x=zero_x+deltax[i];
new_y=zero_y+deltay[i];
if(new_x>=0&&new_x<lineItems&&new_y>=0&&new_y<lineItems)
{
string str=swap(idx->mData,zero_xy, new_y*lineItems+new_x);;
if(!isExist(str))
{
DataItem tmp(str,&idx,i+1);
datas.push_back(tmp);
}
}
}
idx++;
}
//cout<<aimstr[1]<<endl;
return 0;
}
string swap(string str,int x,int y)
{
string str1=str;
char tmp=str1[x];
str1[x]=str1[y];
str1[y]=tmp;
return str1;
}
int isExist(string str)
{
list<DataItem>::iterator i;
for(i=datas.begin();i!=datas.end();i++)
{
if(i->mData==str)
return 1;
}
return 0;
}
void printPath(list<DataItem>::iterator *idx)
{
if(*idx==datas.begin())
return;
cout<<(*idx)->mPtoC;
printPath((*idx)->mParent);
}
代码有点乱,仓促之间写的,还望海涵。估计是用了STL造成的,估计直接用数组去改进一下,可能能提高速度。