这是我们讲的传说中的一项措施A×算法。事实上,类上传之前似小件,下面我们分析一下它去

毕竟,在游戏程序,我们从移动一个点到另一个点。和得到的轨迹的最短距离,类别似这样的算法以及几个。运营效率几乎是相同的,最根本无法跟踪

首先,从一点移动到还有一点。最快就是直接走过去了,就像小男生爱上小女生。最好的办法就是直接走到她面前说:我爱你

只是理想状态。差点儿是没有的,弯路那是必定的经过,有曲线。事实上更美……

那么弯路该怎么走呢,是不是先去背景看下毛主席,再去三亚晒个太阳,再回来告诉她外面的世界好美,不。不,不……

再怎么弯的曲线,越接近直接。越好,所以步骤是:

1.向周围4个或8个方向,全部不是边界的点,记录这些点到目标的距离。从開始到这个点的距离。上一个到这里的点

2.依据两个距离和最小为标准,依次“递归”全部的点直到目标点

3.反向得到路径,就是近期的曲线路径

问:会不会到达同一个点,存在不同的距离

答:是,可是依据近期距离标准递推下去,更远距离的将被丢弃

问:递归为什么加引號

答:用队列实现堆栈,也算是递归,可是不会耗尽线程堆栈

为了,方便在推箱子中检測能否打到某个点,我改动下代码实现不记录上一个点,加速运行

只是后来就没有使用这个功能。主要代码例如以下:

alpha.cpp

// ****************************************************************************************************
// 文件: alpha.cpp
// 凝视:
// A*寻路算法模块, 推断两点之间是否通行, 并得到路径和各节点的权值
// 扩展不保存路径提速, 不使用Dijkstra, 參见http://www.2cto.com/kf/201104/87378.html
// ****************************************************************************************************
//#include <stdlib.h>
#include <malloc.h> #define __LATTICE_DLL_INC_ // DLL内部编译
#include "api.h" // 创建一个场景, 并初始化
V32API PSCENE __stdcall AlphaInit(long dwSizeX, long dwSizeY, long dwMaxCost, UINT dwFlags)
{
PSCENE ps = (PSCENE)malloc(sizeof(SCENE));
if(ps == NULL)
{
return NULL;
}
V32Clear32(ps, 0, sizeof(SCENE)); // memset, 自己主动计算DWORD数量 ps->NodeCount = dwSizeX * dwSizeY; // 节点数量
ps->Nodes = (PNODE)malloc(ps->NodeCount * sizeof(NODE));
if(ps->Nodes == NULL)
{
AlphaExit(ps, 0xFFFFFFFF);
return NULL;
} ps->Matrix = (PBYTE)malloc(ps->NodeCount * sizeof(BYTE)); // 场景矩阵
if(ps->Matrix == NULL)
{
AlphaExit(ps, 0xFFFFFFFF);
return NULL;
} ps->Steps = (PSTEP)malloc(ps->NodeCount * sizeof(STEP));
if(ps->Steps == NULL)
{
AlphaExit(ps, 0xFFFFFFFF);
return NULL;
} if(dwMaxCost <= 0)
{
dwMaxCost = dwSizeX * dwSizeY; // 相邻格子逐个走遍
}
ps->MaxCost = dwMaxCost * CDC_PROP_NEAR; // 最大消耗(距离值)
ps->SizeY = dwSizeY;
ps->SizeX = dwSizeX;
ps->Flags = dwFlags;
return ps;
} // 编辑场景数据
V32API int __stdcall AlphaEdit(PSCENE pScene, long dwPosX, long dwPosY, void *lpValue)
{
PBYTE p;
if(dwPosX < 0 && dwPosY < 0)
{
// 读取
p = pScene->Scene;
if(p == NULL) p = pScene->Matrix;
*(PBYTE)lpValue = p[dwPosY * pScene->SizeX + dwPosX];
return 2;
}
if(dwPosX < 0 || dwPosY < 0)
{
// 使用外部数据指针
pScene->Scene = (PBYTE)lpValue;
return 3;
}
// 设置字节数值
if(dwPosX >= pScene->SizeX || dwPosY >= pScene->SizeY)
{
//memcpy(pScene->Matrix, lpValue, pScene->NodeCount);
return 0;
}
p = pScene->Scene;
if(p == NULL) p = pScene->Matrix;
if(lpValue == NULL)
{
return p[dwPosY * pScene->SizeX + dwPosX]; // 读取
}else
{
p[dwPosY * pScene->SizeX + dwPosX] = *(PBYTE)lpValue; // 写入
}
return 1;
} inline long AlphaCalc(PSTAR pStar1, PSTAR pStar2)
{
// 直接使用坐标差和取代三角函数开方
if(pStar1->X > pStar2->X)
{
if(pStar1->Y > pStar2->Y)
return (pStar1->X - pStar2->X) + (pStar1->Y - pStar2->Y);
else
return (pStar1->X - pStar2->X) + (pStar2->Y - pStar1->Y);
}else
{
if(pStar1->Y > pStar2->Y)
return (pStar2->X - pStar1->X) + (pStar1->Y - pStar2->Y);
else
return (pStar2->X - pStar1->X) + (pStar2->Y - pStar1->Y);
}
//return dX + dY;
} inline void AlphaNode(PSCENE pScene, long dwIndex, long dwPrevId, long dwCost, long dwLast, long dwPosX, long dwPosY)
{
// 開始和循环各调用一次。dwIndex在调用之后自加。初始为0
if(dwIndex >= pScene->NodeCount)
return;
//pScene->Nodes[dwIndex].Star = *pStar; // 是否会创建暂时结构体??
pScene->Nodes[dwIndex].Star.X = dwPosX;
pScene->Nodes[dwIndex].Star.Y = dwPosY;
pScene->Nodes[dwIndex].Prev = dwPrevId;
if(dwPrevId != -1)
pScene->Nodes[dwIndex].Step = pScene->Nodes[dwPrevId].Step + 1;
else
pScene->Nodes[dwIndex].Step = 1;
pScene->Nodes[dwIndex].Cost = dwCost;
pScene->Nodes[dwIndex].Last = dwLast * 10; // 每次dwLen又一次计算得到格子数
pScene->Nodes[dwIndex].Flags = SNF_PROP_READY;
return;
} inline BYTE fnAlphaUnit(PSCENE pScene, PSTAR ps)
{
BYTE *pUnit = pScene->Scene;
if(pUnit == NULL) pUnit = pScene->Matrix;
return pUnit[ps->Y * pScene->SizeX + ps->X];
} inline PSTEP fnAlphaStep(PSCENE pScene, PSTAR ps)
{
return &pScene->Steps[ps->Y * pScene->SizeX + ps->X];
} // 寻路指定场景
V32API int __stdcall AlphaStar(PSCENE pScene, PSTAR lpStart, PSTAR lpTarget, long *pdwStep)
{
PSTEP pStep; long lCurCost, nMaxCost; // 暂存消耗,最大列表
long i, j; // temp & looping var
STAR tps, cps; // test pos, current pos long dwValue;
long dwIndex = 0;
long dwNode = 0; // 当前Node数
long dwLoop;
long dwLen; // 与终点距离 // check for memory address accessable
if(lpStart == NULL || lpTarget == NULL)
{
return 0; // 始末坐标无效
} dwLen = AlphaCalc(lpStart, lpTarget); // dwLen = ΔX + ΔY
if(dwLen == 0)
{
return -1; // 始末坐标同样
}
// zero step memory(cell prop list)
V32Clear32(pScene->Steps, 0, pScene->NodeCount * sizeof(STEP));
// 加入第一个点
dwNode = 0;
AlphaNode(pScene, dwNode, -1, 0, dwLen, lpStart->X, lpStart->Y);
dwNode++; // enter loop - check around cells
while(1)
{
nMaxCost = pScene->MaxCost; // 不可能比这个大
dwIndex = -1;
for(dwLoop = 0; dwLoop < dwNode; dwLoop++)
{
if(pScene->Nodes[dwLoop].Flags != SNF_PROP_ERROR)
{
//找未关闭中最小路程和的点
lCurCost = pScene->Nodes[dwLoop].Cost + pScene->Nodes[dwLoop].Last;
if(lCurCost < nMaxCost)
{
nMaxCost = lCurCost; // 调整最大距离
dwIndex = dwLoop; // 保存节点序号
//break; // 全部节点都要计算
}
}
}
if(dwIndex == -1)
{
return -2; // there is no path exist!
}
cps.X = pScene->Nodes[dwIndex].Star.X;
cps.Y = pScene->Nodes[dwIndex].Star.Y;
if((cps.X == lpTarget->X)&&(cps.Y == lpTarget->Y))
{
break; // 当前点已是终点, 跳出while循环
}
//sprintf(szText, "select best cell:[%d,%d] for check:", cps.X, cps.Y);
for(i = -1; i <= 1; i++)
{
for(j = -1; j <= 1; j++)
{
//if(i == 0 && j == 0) continue; // 同意走对角线,仅仅要两个不同一时候为零(即不是自身)
if(i == 0 && j == 0) continue;
if(i != 0 && j != 0) continue; // 禁止走对角线,必有且仅仅有一个为零{[(i & j) == 0]&&[(i | j) != 0]}
tps.X = cps.X + i;
tps.Y = cps.Y + j;
if(tps.X < 0) continue; // 左边越界
if(tps.X >= pScene->SizeX) continue; // 右边越界
if(tps.Y < 0) continue; // 顶边越界
if(tps.Y >= pScene->SizeY) continue; // 底边越界
// 该点坐标在矩阵范围内
if(fnAlphaUnit(pScene, &tps) & (BYTE)pScene->Flags)
{
continue; // 消除特殊位以后仍然不可通行(独立程序: 仅同意空格或目标)
}
pStep = fnAlphaStep(pScene, &tps);
switch(pStep->Flags){
case SSF_PROP_UNKNOW: // it'v not been check
dwValue = pScene->Nodes[dwIndex].Cost;
//if(i * j != 0)
// dwValue += CDC_PROP_AWAY; // 横纵坐标都是非零, 对角
//else
dwValue += CDC_PROP_NEAR; // 不论什么一个坐标为零, 相邻
dwLen = AlphaCalc(&tps, lpTarget); //dwLen = ΔX + ΔY
AlphaNode(pScene, dwNode, dwIndex, dwValue, dwLen, tps.X, tps.Y);
pStep->Flags = SSF_PROP_OPENED; // open it
pStep->Index = dwNode++;
// sprintf(szText, "add cell:[%d,%d] for check:", tps.X, tps.Y);
break;
case SSF_PROP_OPENED: // this cell is valid
dwValue = pStep->Index;
dwLen = pScene->Nodes[dwIndex].Cost;
dwLen += CDC_PROP_NEAR; // 仅仅能相邻
if(dwLen < pScene->Nodes[dwValue].Cost)
{
pScene->Nodes[dwValue].Cost = dwLen;
pScene->Nodes[dwValue].Prev = dwIndex;
pScene->Nodes[dwValue].Step = pScene->Nodes[dwIndex].Step + 1; //change level
}
//sprintf(szText, "change pID for cell:[%d,%d] to %d.", tps.X, tps.Y, nID);
break;
default:
//end if(lpOGrid[tps.X][tps.Y].State..
break;
}
//end if((lpCell..
//end if((tps.X..
//end if(((i..
} //next j
} //next i
// it will continue if any path and not at target
pStep = fnAlphaStep(pScene, &cps);
pScene->Nodes[dwIndex].Flags = SNF_PROP_ERROR;
pStep->Flags = SSF_PROP_CLOSED; // close it
//sprintf(szText, "close cell:[%d,%d] ok.", cps.X, cps.Y);
}
// 函数malloc()和realloc()时间消耗大,用空间换取时间
dwValue = pScene->Nodes[dwIndex].Cost + pScene->Nodes[dwIndex].Last;
if(pdwStep == NULL)
{
// 不须要结果详情
return dwValue; // return cost to get here
}
//sprintf(szText, "best path found in cost %d.", dwValue);
pScene->StarCount = pScene->Nodes[dwIndex].Step;
SafeFree(pScene->Stars); // release old path
pScene->Stars = (PSTAR)malloc(pScene->StarCount * sizeof(STAR));
if(pScene->Stars == NULL)
{
return -3; // Out of memory
}
// ...
dwLoop = pScene->StarCount;
*pdwStep = dwLoop; // set the steps
while(dwLoop > 0) // it can also base on dwIndex
{
dwLoop--;
//pScene->m_pStarPath[dwLoop].X = pScene->Nodes[dwIndex].Star.X;
//pScene->m_pStarPath[dwLoop].Y = pScene->Nodes[dwIndex].Star.Y;
pScene->Stars[dwLoop] = pScene->Nodes[dwIndex].Star;
dwIndex = pScene->Nodes[dwIndex].Prev; // parent id
//sprintf(szText, "the %d cell:[%d,%d] added to path.", i, lpRoad[i].X, lpRoad[i].Y);
}
return dwValue; // return cost to get here
} V32API int __stdcall AlphaData(PSCENE pScene, UINT dwPropId, long dwIndex)
{
VAR v;
v.pValue = (void*)pScene;
v.dwValue += dwPropId;
if(dwIndex < 0)
{
return (int)*v.plValue; // 直接定位成员
}
v.dwValue = *v.pdwValue;
v.dwValue += dwIndex;
return (int)*v.plValue;
} // 销毁一个场景, 释放资源
V32API int __stdcall AlphaExit(PSCENE pScene, UINT dwFlags)
{
if(pScene)
{
SafeFree(pScene->Stars);
pScene->StarCount = 0;
SafeFree(pScene->Steps);
pScene->Scene = NULL; // 外部数据指针
SafeFree(pScene->Matrix);
SafeFree(pScene->Nodes);
pScene->NodeCount = 0;
free(pScene);
//pScene = NULL;
}
return 1;
}

当中V32API是一个宏定义。在v32/api.h中因此依赖V32.dll

这是我的一个基础类库的基类,包含经常使用的C语言函数和C++封装类,另一些宏定义

函数大多是内联汇编的裸函数。宏定义通常是高速释放内存用的,如

#define SafeDelete(p)		if(p){delete p; p = NULL;}

C++仅仅是封装C函数为类,同一时候扩展了C++特效。例如,智能指针,请参阅相关的头

版权声明:本文博客原创文章。博客,未经同意,不得转载。

原因好消息: PSP游戏自己主动算法设计(两)的更多相关文章

  1. 最大子段和的DP算法设计及其效率测试

    表情包形象取自番剧<猫咪日常> 那我也整一个 曾几何时,笔者是个对算法这个概念漠不关心的人,由衷地感觉它就是一种和奥数一样华而不实的存在,即便不使用任何算法的思想我一样能写出能跑的程序 直 ...

  2. 【技术文档】《算法设计与分析导论》R.C.T.Lee等·第7章 动态规划

    由于种种原因(看这一章间隔的时间太长,弄不清动态规划.分治.递归是什么关系),导致这章内容看了三遍才基本看懂动态规划是什么.动态规划适合解决可分阶段的组合优化问题,但它又不同于贪心算法,动态规划所解决 ...

  3. 游戏AI的综合设计

    原地址:http://www.cnblogs.com/cocoaleaves/archive/2009/03/23/1419346.html 学校的MSTC要出杂志,第一期做游戏专题,我写了一下AI, ...

  4. Python数据结构与算法设计(总结篇)

    的确,正如偶像Bruce Eckel所说,"Life is short, you need Python"! 如果你正在考虑学Java还是Python的话,那就别想了,选Pytho ...

  5. 算法设计与分析——n后问题(回溯法+位运算)

    一.问题描述 在n×n格的国际象棋上摆放n个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法. 二.算法设计 解n后问题的回溯算法描述如下: #include ...

  6. 算法设计与分析 - AC 题目 - 第 5 弹(重复第 2 弹)

    PTA-算法设计与分析-AC原题 - 最大子列和问题 (20分) 给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+, ..., Nj },其中 ≤i ...

  7. 算法设计与分析 - AC 题目 - 第 2 弹

    PTA-算法设计与分析-AC原题7-1 最大子列和问题 (20分)给定K个整数组成的序列{ N1, N2, ..., NK },“连续子列”被定义为{ Ni, Ni+1, ..., Nj },其中 1 ...

  8. OOP: One pont of view of OOP与基于算法设计的区别

    ..摘自<C++网络编程 卷1:运用ACE和模式消除复杂性> <C++ Network Programming Volume 1 Mastering Complexity with ...

  9. Python数据结构与算法设计总结篇

    1.Python数据结构篇 数据结构篇主要是阅读[Problem Solving with Python]( http://interactivepython.org/courselib/static ...

随机推荐

  1. JS window.open()财产

    一. Window 对象 Window 对象是 JavaScript 顶级对象层次. Window 对象表示一个浏览器窗口或帧. Window 在对象 <body> 或 <frame ...

  2. php编码规范个人小结

    1.原生态代码或者类的头上,注明作者,关键算法计算过程 例如 /** *@author zengmoumou *功能:根据列表ip,取得ip对应的运营商,省,市,县 */ 2.变量尽量用英文单词的组合 ...

  3. TCP拥塞控制 (1)

    Basic: TCP,传输控制协定,它是目前最广泛使用的网络传输协议.SMTP.SSH.FTP.HTTP等因特网底层协议均是TCP. TCP面向连接,提供端到端的数据可靠传输.连接时三次握手.断开是四 ...

  4. asp.net访问网络路径方法(模拟用户登录)

    public class IdentityScope : IDisposable { // obtains user token [DllImport("advapi32.dll" ...

  5. Android Java 与 C++ 恒调用,路径、文件名、延长的最大长度

    /****************************************************************************  ********************* ...

  6. atitit.404错误调查过程汇总

    atitit.404错误调查过程汇总 #----------jsp  head  errorPage="" del zeu ok le. #------resin server. ...

  7. 在AcGIS随着大数据的生成DEM

    在ArcGIS产生DEM时间.数据来源是经常有的高程点.轮廓线,该高程点.等高线密集,可能有几千万.甚至亿高程点.轮廓线. 如果您使用这些矢量数据生成TIN.不能实现的,由于生成TIN时,支持的最大结 ...

  8. hdu 2454 Degree Sequence of Graph G (推断简单图)

    ///已知各点的度,推断是否为一个简单图 #include<stdio.h> #include<algorithm> #include<string.h> usin ...

  9. RH133读书 笔记(4) - Lab 4 System Services

    Lab 4 System Services Goal: Develop skills using system administration tools and setting up and admi ...

  10. Android学习路径(十)怎么会Action Bar堆放在布局

    默认情况下.action bar出如今activity窗体的顶部.稍微降低了activity布局的总空间. 假设你想隐藏或者显示action bar.在这堂用户体验的课程中,你能够通过调用hide() ...