AStar(?)ができた

経路探索はこれでばっちり。
特にこのページを参考にした。
http://www5f.biglobe.ne.jp/~kenmo/program/SLG/astar/astar.html
またスタックの実装はWarpRogueの書き方を多く参考にした。

//CPathF.h
#ifndef __C_PATHFINDER_H_INC__
#define __C_PATHFINDER_H_INC__

#include <iostream>
#include <vector>

using namespace std;

class CNode {
public:
	int x, y, cost, heur;
	class CNode *parent;
	CNode(int x = 0, int y = 0, int c = 0, int heur = 0, class CNode *par = NULL)
	{
		this->x = x;
		this->y = y;
		this->cost = c;
		this->heur = heur;
		parent = par;
	}
	int GetScore()
	{
		return cost + heur;
	}
	void Print()
	{
		cout.width(2);
		cout << "[" << x << ',' << y << "] ";
	}
};

class CPathFinder
{
private:
	enum {
		NODECNT = 2048,
	};
	CNode forge_node[NODECNT];
	CNode forge_open[NODECNT];
	CNode *node_total_ptr;
	CNode *open_sta_ptr;
	enum {
		BLO_NONE,
		BLO_BLOCK,
	};
	vector<vector<int> > blocker;
	vector<vector<int> > closed_set;
	int sx, sy, gx, gy;
	int hgt, wid;
	bool is_ok_xy(int x, int y)
	{
		if (x < 0 || y < 0 || x >= wid || y >= hgt)
			return false;
		return true;
	}
	CNode *open_pop();
	void open_push(CNode *newitem);
	void push_adj_nodes(CNode *node);
	CNode *total_push(CNode *node);
	int iabs(int x)
	{
		if (x < 0) 
			return -x;
		return x;
	}
	int idistxyxy(int x1, int y1, int x2, int y2);
	enum {
		DIR_NONE,
		DIR_UL,
		DIR_U,
		DIR_UR,
		DIR_R,
		DIR_DR,
		DIR_D,
		DIR_DL,
		DIR_L,
		N_DIR,
	};
	int xxd[N_DIR];
	int yyd[N_DIR];
public:
	void Alloc_mapetc();
	CPathFinder(int sx, int sy, int gx, int gy, int wid = 256, int hgt = 256)
	{
		this->sx = sx;
		this->sy = sy;
		this->gx = gx;
		this->gy = gy;
		this->wid = wid;
		this->hgt = hgt;
		node_total_ptr = forge_node;
		open_sta_ptr = forge_open;
		Alloc_mapetc();
	}
	void SetBlocker_xy(int x, int y)
	{
		if (is_ok_xy(x,y))
		{
			blocker[y][x] = 1;
		}
	}
	void SetStart_xy(int x, int y)
	{
		sx = x;
		sy = y;
	}
	void SetGoal_xy(int x, int y)
	{
		gx = x;
		gy = y;
	}
	CNode *calc_path();
	bool is_block_xy(int x, int y)
	{
		if (!is_ok_xy(x,y))
			return false;
		if (blocker[y][x] == BLO_NONE)
			return false;
		return true;
	}
};


#endif //__C_PATHFINDER_H_INC__
//CPathF.cpp
#include "CPathF.h"

void CPathFinder::Alloc_mapetc()
{
	for(int i=0;i<hgt;i++)
	{
		vector<int> a;
		a.clear();
		for(int j=0;j<wid;j++)
		{
			a.push_back(0);
		}
		closed_set.push_back(a);
		blocker.push_back(a);
	}
	const int tmpxxdi[N_DIR] = {0,-1, 0, 1, 1, 1, 0,-1,-1};
	const int tmpyydi[N_DIR] = {0,-1,-1,-1, 0, 1, 1, 1, 0};
	for(int i=0;i<N_DIR;i++)
	{
		xxd[i] = tmpxxdi[i];
		yyd[i] = tmpyydi[i];
	}
}

CNode *CPathFinder::calc_path()
{
	int loopcnt = 800;
	
	CNode tmpstart(sx, sy, 0, idistxyxy(sx,sy,gx,gy));
	
	open_push(&tmpstart);

	closed_set[sy][sx] = 1;

	CNode *node = open_pop();
	
	while(loopcnt--)
	{
		if (node == NULL) break;
		
		if (node->x == gx && node->y == gy)
		{
			return node->parent;
		}
		
		node = total_push(node);
		
		push_adj_nodes(node);
		
		node = open_pop();
	}
	
	return NULL;
}

CNode *CPathFinder::total_push(CNode *node)
{
	CNode *rval;
	*node_total_ptr = *node;
	rval = node_total_ptr;
	node_total_ptr++;
	return rval;
}

CNode *CPathFinder::open_pop()
{
	if (open_sta_ptr == forge_open)
	{
		return NULL;
	}
	open_sta_ptr--;
	return open_sta_ptr;
}

void CPathFinder::open_push(CNode *newitem)
{
	*open_sta_ptr = *newitem;
	
	CNode *node = open_sta_ptr;
	
	open_sta_ptr++;
	
	int node_score = node->GetScore();
	
	while(node != forge_open)
	{
		CNode *node_below;
		
		node_below = node - 1;
		int node_below_score = node_below->GetScore();
		
		if (node_below_score < node_score)
		{
			//swap
			CNode tmp = *node;
			*node = *node_below;
			*node_below = tmp;
			
			node--;
		}
		else
		{
			break;
		}
	}
}

void CPathFinder::push_adj_nodes(CNode *node)
{
	for(int d=DIR_UL;d<N_DIR;d++)
	{
		CNode adj_node;
		int xm = xxd[d], ym = yyd[d];

		adj_node.x = node->x + xm;
		adj_node.y = node->y + ym;
		adj_node.cost = node->cost + 1;
		adj_node.heur = idistxyxy(adj_node.x, adj_node.y, gx, gy);
		
		if (!is_ok_xy(adj_node.x, adj_node.y))
		{
			continue;
		}
		if (closed_set[adj_node.y][adj_node.x])
		{
			continue;
		}
		if (is_block_xy(adj_node.x, adj_node.y))
		{
			continue;
		}
		//斜め移動でスキマを通り抜けない
		if ((ym && is_block_xy(node->x, adj_node.y)) && (xm && is_block_xy(adj_node.x, node->y)))
		{
			continue;
		}
		closed_set[adj_node.y][adj_node.x] = 1;
		adj_node.parent = node;
		open_push(&adj_node);
	}
}

int CPathFinder::idistxyxy(int x1, int y1, int x2, int y2)
{
	int r1 = iabs(x1-x2), r2 = iabs(y1-y2);
	if (r1 > r2)
	{
		return r1;
	}
	return r2;
}

使い方の例

#include <iostream>
#include <vector>

#include "CPathF.h"

using namespace std;

#define HGT 20
char *map[HGT+1] = {
	"##########",
	"#...#.#..#",
	"#.#.#.#..#",
	"#G#......#",
	"#.#.####.#",
	"#........#",
	"#..#####.#",
	"#.#.#....#",
	"#..#..####",
	"####.#...#",
	"#....#..S#",
	"#....#...#",
	"#........#",
	"##########",
	0,
};

enum {
	M_NONE,
	M_WALL,
	M_START,
	M_GOAL,
	M_STEP,
};

vector<vector<int> > X_all; //ベクタのベクタ

void view()
{
	for (unsigned int i= 0; i<X_all.size(); i++){
		for (unsigned int c= 0; c<X_all[i].size(); c++){
			char ch = '#';
			int masu = X_all[i][c];
			if (masu >= '0' && masu <= '9')
			{
				ch = (char) masu;
			}
			else
			{
			switch(masu)
			{
			case M_NONE: ch = '.'; break;
			case M_WALL: ch = '#'; break;
			case M_START: ch = '@'; break;
			case M_GOAL: ch = '>'; break;
			case M_STEP: ch = 'a'; break;
			}
			}
			cout << ch;
		}
		cout << endl;
	}
}

int main()
{
	int iSutaX = 1, iSutaY = 1;
	int iGoalX = 2, iGoalY = 2;
	int MWidth = 2;
	int MHeight = 2;

	for (int i = 0; ; i++)
	{
		MHeight = i;
		if (!map[i]) break;
		vector<int> vectorX;
		vectorX.clear();
		int c;
		for (c = 0; ; c++)
		{
			if (!map[i][c]) break;
			int X = M_NONE;
			switch(map[i][c])
			{
			case '#':
				X = M_WALL;
				break;
			case 'S':
				iSutaX = c;
				iSutaY = i;
				X = M_START;
				break;
			case 'G':
				iGoalX = c;
				iGoalY = i;
				X = M_GOAL;
				break;
			default:
				X = M_NONE;
				break;
			}
			vectorX.push_back(X);
		}
		if (c > MWidth)
		{
			MWidth = c;
		}
		X_all.push_back(vectorX);
	}
	cout << endl;

	CPathFinder pf(iSutaX,iSutaY,iGoalX,iGoalY,MWidth,MHeight);
	for(int i=0;i<MHeight;i++)
	{
		for(int j=0;j<MWidth;j++)
		{
			if (X_all[i][j] == M_WALL)
			{
				pf.SetBlocker_xy(j,i);
			}
		}
	}
	CNode *miti = pf.calc_path();

	if (!miti)
	{
		cout << "miti is NULL." << endl;
	}
	else
	{
		cout << "miti done." << endl;
		char cnt = '0';
		for(CNode *ptr=miti; ptr != NULL ;ptr = ptr->parent)
		{
			ptr->Print();
			if (X_all[ptr->y][ptr->x] == M_NONE)
			{
				X_all[ptr->y][ptr->x] = cnt;
			}
			cnt++;
			if (cnt > '9') cnt = '0';
		}
		cout << "its miti." << endl;
	}
	
	view();
}

保証はないけどすきにつかってね。
const 付けろのツッコミはいつでもウェルカム、
あなたのそのconst付けろを心から応援するものです。