算法老师给了一份关于九宫拼图的算法过程用C++写的,让我们自己封装,成为一个有图形界面的工程,我接触过android,c++的mfc,Java的图形界面JUI,网页的css、html、javascript,Unity3D;但感觉最熟悉的还是利用android来写比较熟悉,可能是各种组件之间的操作不久前才完成了一个app的原因吧,所以我选择安卓。老师给了两周的时间,全凭自愿吧。我觉得我可以尝试一下。

  首先需要吧老师给的C++算法代码转换成Java代码,老师给的代码如下:

 /*****************************/
/* EIGHT DIGIT PROBLEM */
/* 唐国峰 2012年4月23日 */
/*****************************/ // 预编译命令
#include "iostream"
#include "stdlib.h"
using namespace std; //棋盘大小
#define size 3 //定义二维数组来存储数据表示某一个特定状态
typedef int status[size][size]; //定义状态图中的节点数据结构,即节点的状态信息等
typedef struct Node
{
status data; //节点所存储的状态
struct Node *parent; //指向节点的父亲节点
struct SpringLink *child; //指向节点的后继节点
struct Node *next; //指向链表的后一个节点
int f_value; //由初始状态经由当前节点至目标状态的总耗散值
int g_value; //由初始状态经到当前节点实际耗散值
int h_value; //由当前节点到目标状态的预计耗散值
}NNode, *PNode; //定义表述指向当前节点的扩展节点的链表
typedef struct SpringLink
{
struct Node *pointData; //指向节点的指针
struct SpringLink *next; //指向当前节点的其他扩展节点
}SPLink, *PSPLink; //声明OPEN表和CLOSED表
PNode open;
PNode closed; //计算棋盘状态的逆序数
int InverseNumber(status a)
{
int i, j, sum=;
int data_chang[size*size]={}; //将二维数组转换成一维数组,以方便求逆序数
for(i=;i<size;i++)
{
for(j=;j<size;j++)
{
data_chang[i*size+j]=a[i][j];
}
} //计算序列中除零外的逆序数
for(i=;i<=size*size;i++)
{
if(data_chang[i]!=)
{
//要比较多少次,从最后一个元素开始比较
for(j=i;j>=;j--)
{
//当后一个数比前一个数小时
if(data_chang[i]<data_chang[j])
{
sum++;
}
}
}
}
return sum;
} //判断是否存在解决方案
bool hasSolution(status startStatus,status targetStatus)
{
int startInverseNumber=InverseNumber(startStatus);
int tatgetInverseNumber=InverseNumber(targetStatus); //判断初始状态和目标状态除零外的序列逆序数奇偶性,相同则可求值,不同则不可求
if( (startInverseNumber%) != (tatgetInverseNumber%) )
{
return false;
}
else
{
return true;
}
} //初始化一个空链表
void initLink(PNode &Head)
{
Head = (PNode)malloc(sizeof(NNode));
Head->next = NULL;
} //判断链表是否为空
bool isEmpty(PNode Head)
{
if(Head->next == NULL)
{
return true;
}
else
{
return false;
}
} //从链表中拿出一个数据
void popNode(PNode &Head , PNode &FNode)
{
if(isEmpty(Head))
{
FNode = NULL;
return;
}
FNode = Head->next;
Head->next = Head->next->next;
FNode->next = NULL;
} //向节点的最终后继节点链表中添加新的子节点
void addSpringNode(PNode &Head , PNode newData)
{
PSPLink newNode = (PSPLink)malloc(sizeof(SPLink));
newNode->pointData = newData; newNode->next = Head->child;
Head->child = newNode;
} //释放状态图中存放节点后继节点地址的空间
void freeSpringLink(PSPLink &Head)
{
PSPLink tmm; while(Head != NULL)
{
tmm = Head;
Head = Head->next;
free(tmm);
}
} //释放open表与closed表中的资源
void freeLink(PNode &Head)
{
PNode tmn; tmn = Head;
Head = Head->next;
free(tmn); while(Head != NULL)
{
//首先释放存放节点后继节点地址的空间
freeSpringLink(Head->child);
tmn = Head;
Head = Head->next;
free(tmn);
}
} //向普通链表中添加一个节点
void addNode(PNode &Head , PNode &newNode)
{
newNode->next = Head->next;
Head->next = newNode;
} //向非递减排列的链表中添加一个节点
void addAscNode(PNode &Head , PNode &newNode)
{
PNode P;
PNode Q; P = Head->next;
Q = Head;
while(P != NULL && P->f_value < newNode->f_value)
{
Q = P;
P = P->next;
}
//上面判断好位置之后,下面就是简单的插入节点了
newNode->next = Q->next;
Q->next = newNode;
} //计算节点到目标状态的预计耗散值
int computeh_value(PNode theNode,status targetStatus)
{
int num = ;
for(int i = ; i < ; i++)
{
for(int j = ; j < ; j++)
{
if(theNode->data[i][j] != targetStatus[i][j])
{
num++;
}
}
}
return num;
} //计算节点的f,g,h值
void computeAllValue(PNode &theNode , PNode parentNode, status targetStatus)
{
if(parentNode == NULL)
{
theNode->g_value = ;
}
else
{
theNode->g_value = parentNode->g_value + ;
} theNode->h_value = computeh_value(theNode,targetStatus);
theNode->f_value = theNode->g_value + theNode->h_value;
} //初始化函数,进行算法初始条件的设置
void initial(status startStatus,status targetStatus)
{
//初始化open以及closed表
initLink(open);
initLink(closed); //初始化起始节点,令初始节点的父节点为空节点
PNode NULLNode = NULL;
PNode StartNode = (PNode)malloc(sizeof(NNode));
for(int i = ; i < ; i++)
{
for(int j = ; j < ; j++)
{
StartNode->data[i][j] = startStatus[i][j];
}
}
StartNode->parent = NULL;
StartNode->child = NULL;
StartNode->next = NULL;
computeAllValue(StartNode, NULLNode,targetStatus); //起始节点进入OPEN表
addAscNode(open , StartNode);
} //将B节点的状态赋值给A节点
void statusAEB(PNode &ANode , PNode BNode)
{
for(int i = ; i < ; i++)
{
for(int j = ; j < ; j++)
{
ANode->data[i][j] = BNode->data[i][j];
}
}
} //两个节点是否有相同的状态
bool hasSameStatus(PNode ANode , PNode BNode)
{
for(int i = ; i < size ; i++)
{
for(int j = ; j < size ; j++)
{
if(ANode->data[i][j] != BNode->data[i][j])
return false;
}
}
return true;
} //节点与其祖先节点是否有相同的状态
bool hasAnceSameStatus(PNode OrigiNode , PNode AnceNode)
{
while(AnceNode != NULL)
{
if(hasSameStatus(OrigiNode , AnceNode))
return true;
AnceNode = AnceNode->parent;
}
return false;
} //取得方格中空的格子的位置
void getPosition(PNode theNode , int &row , int &col)
{
for(int i = ; i < size ; i++)
{
for(int j = ; j < size ; j++)
{
if(theNode->data[i][j] == )
{
row = i;
col = j;
return;
}
}
}
} //交换两个数字的值
void changeAB(int &a , int &b)
{
int c;
c = b;
b = a;
a = c;
} //检查相应的状态是否在某一个链表中
bool inLink(PNode spciNode , PNode theLink , PNode &theNodeLink , PNode &preNode)
{
preNode = theLink;
theLink = theLink->next; while(theLink != NULL)
{
if(hasSameStatus(spciNode , theLink))
{
theNodeLink = theLink;
return true;
}
preNode = theLink;
theLink = theLink->next;
}
return false;
} //产生节点的后继节点链表
void SpringLink(PNode theNode , PNode &spring, status targetStatus)
{
int row;
int col; getPosition(theNode , row , col); //空的格子右边的格子向左移动
if(col != )
{
PNode rlNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(rlNewNode, theNode);
changeAB(rlNewNode->data[row][col], rlNewNode->data[row][col + ]);
if(hasAnceSameStatus(rlNewNode, theNode->parent))
{
free(rlNewNode);//与父辈相同,丢弃本节点
}
else
{
rlNewNode->parent = theNode;
rlNewNode->child = NULL;
rlNewNode->next = NULL;
computeAllValue(rlNewNode, theNode, targetStatus);
//将本节点加入后继节点链表
addNode(spring, rlNewNode);
}
}
//空的格子左边的格子向右移动
if(col != )
{
PNode lrNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(lrNewNode, theNode);
changeAB(lrNewNode->data[row][col], lrNewNode->data[row][col - ]);
if(hasAnceSameStatus(lrNewNode, theNode->parent))
{
free(lrNewNode);//与父辈相同,丢弃本节点
}
else
{
lrNewNode->parent = theNode;
lrNewNode->child = NULL;
lrNewNode->next = NULL;
computeAllValue(lrNewNode, theNode, targetStatus);
//将本节点加入后继节点链表
addNode(spring , lrNewNode);
}
}
//空的格子上边的格子向下移动
if(row != )
{
PNode udNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(udNewNode , theNode);
changeAB(udNewNode->data[row][col], udNewNode->data[row - ][col]);
if(hasAnceSameStatus(udNewNode, theNode->parent))
{
free(udNewNode);//与父辈相同,丢弃本节点
}
else
{
udNewNode->parent = theNode;
udNewNode->child = NULL;
udNewNode->next = NULL;
computeAllValue(udNewNode, theNode, targetStatus);
//将本节点加入后继节点链表
addNode(spring, udNewNode);
}
}
//空的格子下边的格子向上移动
if(row != )
{
PNode duNewNode = (PNode)malloc(sizeof(NNode));
statusAEB(duNewNode, theNode);
changeAB(duNewNode->data[row][col], duNewNode->data[row + ][col]);
if(hasAnceSameStatus(duNewNode, theNode->parent))
{
free(duNewNode);//与父辈相同,丢弃本节点
}
else
{
duNewNode->parent = theNode;
duNewNode->child = NULL;
duNewNode->next = NULL;
computeAllValue(duNewNode, theNode, targetStatus);
//将本节点加入后继节点链表
addNode(spring , duNewNode);
}
}
} //输出给定节点的状态
void outputStatus(PNode stat)
{
for(int i = ; i < ; i++)
{
for(int j = ; j < ; j++)
{
cout << stat->data[i][j] << " ";
}
cout << endl;
}
} //输出最佳的路径
void outputBestRoad(PNode goal)
{
int deepnum = goal->g_value; if(goal->parent != NULL)
{
outputBestRoad(goal->parent);
}
cout << "第" << deepnum-- << "步的状态:" << endl;
outputStatus(goal);
} void AStar(status startStatus,status targetStatus)
{
PNode tmpNode; //指向从open表中拿出并放到closed表中的节点的指针
PNode spring; //tmpNode的后继节点链
PNode tmpLNode; //tmpNode的某一个后继节点
PNode tmpChartNode;
PNode thePreNode; //指向将要从closed表中移到open表中的节点的前一个节点的指针
bool getGoal = false; //标识是否达到目标状态
long numcount = ; //记录从open表中拿出节点的序号 initial(startStatus,targetStatus); //对函数进行初始化
initLink(spring); //对后继链表的初始化
tmpChartNode = NULL; cout << "从OPEN表中拿出的节点的状态及相应的值" << endl;
while(!isEmpty(open))
{
//从OPEN表中拿出f值最小的元素,并将拿出的元素放入CLOSED表中
popNode(open, tmpNode);
addNode(closed, tmpNode); cout << "第" << numcount++ << "个状态是:" << endl;
outputStatus(tmpNode);
cout << "其f值为:" << tmpNode->f_value << endl;
cout << "其g值为:" << tmpNode->g_value << endl;
cout << "其h值为:" << tmpNode->h_value << endl; //如果拿出的元素是目标状态则跳出循环
if(computeh_value(tmpNode, targetStatus) == )
{
getGoal = true;
break;
} //产生当前检测节点的后继(与祖先不同)节点列表,产生的后继节点的parent属性指向当前检测的节点
SpringLink(tmpNode, spring, targetStatus); //遍历检测节点的后继节点链表
while(!isEmpty(spring))
{
popNode(spring , tmpLNode);
//状态在OPEN表中已经存在,thePreNode参数在这里并不起作用
if(inLink(tmpLNode , open , tmpChartNode , thePreNode))
{
addSpringNode(tmpNode , tmpChartNode);
if(tmpLNode->g_value < tmpChartNode->g_value)
{
tmpChartNode->parent = tmpLNode->parent;
tmpChartNode->g_value = tmpLNode->g_value;
tmpChartNode->f_value = tmpLNode->f_value;
}
free(tmpLNode);
}
//状态在CLOSED表中已经存在
else if(inLink(tmpLNode, closed, tmpChartNode, thePreNode))
{
addSpringNode(tmpNode, tmpChartNode);
if(tmpLNode->g_value < tmpChartNode->g_value)
{
PNode commu;
tmpChartNode->parent = tmpLNode->parent;
tmpChartNode->g_value = tmpLNode->g_value;
tmpChartNode->f_value = tmpLNode->f_value;
freeSpringLink(tmpChartNode->child);
tmpChartNode->child = NULL;
popNode(thePreNode, commu);
addAscNode(open, commu);
}
free(tmpLNode);
}
//新的状态即此状态既不在OPEN表中也不在CLOSED表中
else
{
addSpringNode(tmpNode, tmpLNode);
addAscNode(open, tmpLNode);
}
}
} //目标可达的话,输出最佳的路径
if(getGoal)
{
cout << endl;
cout << "路径长度为:" << tmpNode->g_value << endl;
outputBestRoad(tmpNode);
} //释放节点所占的内存
freeLink(open);
freeLink(closed);
} int main()
{ //开始状态和目标状态
status startStatus = { , , , , , , , , };//2, 8, 3, 1, 6, 4, 7, 0, 5};
status targetStatus = {, , , , , , , , }; if(hasSolution(startStatus,targetStatus))
{
AStar(startStatus,targetStatus);
}
else
{
cout << "从当前输入的初始状态无法经过有限步数变换至您期望的目标状态!" << endl;
}
system("pause");
}

Android实现九宫拼图过程记录的更多相关文章

  1. Ubuntu15.10 编译VLC Android(安卓)过程记录

    持续更新中... 最后一次修改于 2016-03-20 15:33:45 1.必要库的安装 除基本编译环境(gcc.g++等外),需要额外安装如下的库(用于下载必要的依赖文件) (1)JDK 推荐安装 ...

  2. 【转】android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)

    原文网址:http://www.cnblogs.com/zdz8207/archive/2012/11/27/android-ndk-install.html android 最新 NDK r8 在w ...

  3. android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创)

      android 最新 NDK r8 在window下开发环境搭建 安装配置与使用 详细图文讲解,完整实际配置过程记录(原创) 一直想搞NDK开发却一直给其他事情耽搁了,参考了些网上的资料今天终于把 ...

  4. Android应用打包安装过程具体解释

    Android应用打包安装过程(Run as Android Application ): 1,过程:Android Project --> Compilation and Packaging ...

  5. Android 8 声音调整过程

    记录Android 8声音调整过程. frameworks\base\services\core\java\com\android\server\policy\PhoneWindowManager.j ...

  6. Android 6.0启动过程具体解析

    在之前的一篇文章中.从概念上学习了Andoird系统的启动过程.Android系统启动过程学习 而在这篇文章中,我们将从代码角度细致学习Android系统的启动过程,同一时候,学习Android启动过 ...

  7. Lenovo k860i 移植Android 4.4 cm11进度记录【上篇已完结】

    2014.5.16 为了验证一下下载的CM11的源码有没有问题,决定编译一下cm官方支持的机器,手上正好有台nexus7 2012,就拿它为例测试一下在mac os x平台的整个编译过程. 1. 最开 ...

  8. 升级Windows 10 正式版过程记录与经验

    升级Windows 10 正式版过程记录与经验 [多图预警]共50张,约4.6MB 系统概要: 预装Windows 8.1中文版 64位 C盘Users 文件夹已经挪动到D盘,并在原处建立了符号链接. ...

  9. 双系统Ubuntu分区扩容过程记录

    本人电脑上安装了Win10 + Ubuntu 12.04双系统.前段时间因为在Ubuntu上做项目要安装一个比较大的软件,导致Ubuntu根分区的空间不够了.于是,从硬盘又分出来一部分空间,分给Ubu ...

随机推荐

  1. Appium(十):元素定位(加强版)

    1. 元素定位 写完上一篇元素定位的博客,发现实用性基本为零.这几天真的烦死我了,一直在找资料,还去看了一遍appium官网文档.最后结合着selenium的定位方法,测试出几种可行的元素定位方法. ...

  2. EF Core 中处理 1对1 关系

    最近在开发记录感想功能的时候用到了1对1的数据关系,具体情况是这样的,有这样两个1对1的类型 public class Item { public int Id { get; set; } publi ...

  3. oc:定时删除ES日志数据释放空间

    修改方法: 1.直接编辑修改 查看当前logging-curator配置,了解当前定时删除大的策略. oc edit configmap/logging-curator 打开后,可以直接编辑保存. 2 ...

  4. IT兄弟连 HTML5教程 CSS3属性特效 动画-animation

    CSS3属性中有关于制作动画的三个属性:Transform,Transition,Animation.前面已经介绍过Transform和Transition了,这里我们来学习Animation动画.通 ...

  5. 【解决】Failed to restart network.service: Unit network.service not found.

    问题:使用systemctl restart network 或 service network restart 命令重启网卡失败. 分析:原因其实也很简单,命令用错了,造成了找不到相应的网卡服务. ...

  6. C#实现地图坐标系的转换(WGS-84、GCJ-02、BD-09)

     WGS-84坐标系:全球定位系统使用,GPS.北斗等 GCJ-02坐标系:中国地区使用,由WGS-84偏移而来 BD-09坐标系:百度专用,由GCJ-02偏移而来 (PS:源于项目需求,本来是想读图 ...

  7. mysql字符集与比较规则

    MySQL有4个级别的字符集和比较规则,分别是: 服务器级别 数据库级别 表级别 列级别 查看服务器级别命令: mysql> SHOW VARIABLES LIKE 'character_set ...

  8. iOS开发WKWebView 返回H5上级页面

    #pragma mark ---- 点击事件 -(void)leftTapClick:(UITapGestureRecognizer *)sender{ //判断是否能返回到H5上级页面 if (se ...

  9. PHP计算二维数组指定元素的和

    array_sum(array_column($arr, 'num')); //计算二维数组指定元素的和 $arr = [ [ 'id'=>1, 'num'=>3, ], [ 'id'=& ...

  10. 快速查看本地IP地址

    1. 新建Windows批处理文件(*.bat) @echo off echo 本机IP ipconfig|find "IPv4" echo. echo 电脑名 hostname ...