【原创】火星寻路程序

这个程序的作用是,任意加载一幅图像,程序将自动识别路线,设置一个目标,Agent会自动让开障碍物,采用A*,Agent之间有碰撞检测功能。不会发生重叠。此技术可以实现汽车的自动导航,以及火星登陆车的自动导航

作者:小白 小蔡 小唐 (按拼音排列)

例如:载入这副图像

程序将自动识别这副迷宫,白色为可通路,黑色为障碍,然后设置一个机器人,机器人将能自动导航

又如:载入一幅火星表面图

程序分析为

相关程序如下

CActor.h

-----------------------------------------------------------

#pragma once
#include "stdafx.h"
#include "CParam.h"
#include "CMap.h"
#include "CConMap.h"
#include "utils.h"


//-----------------Hash---------------------------------
//hash散列函数
inline size_t myHash_value(const Pos& pos)
{
 return size_t(100*pos.x+pos.y);
}

//hash比较仿函数
struct Myless
{
 bool operator()(const Pos& p1,const Pos& p2)const
 {  
  return myHash_value(p1)<myHash_value(p2);
 } 
};

//自定义hash类
template<class _Kty>
class MyHash

public: 
 enum
  { // parameters for hash table
  bucket_size = 2, // 0 < bucket_size
  min_buckets = 8}; // min_buckets = 2 ^^ N, 0 < N 

 size_t operator()(const _Kty& _Keyval) const
  { // hash _Keyval to size_t value
      return ((size_t)myHash_value(_Keyval));   
  }

 bool operator()(const _Kty& _Keyval1, const _Kty& _Keyval2) const
  { // test if _Keyval1 ordered before _Keyval2  
   return myHash_value(_Keyval1)<myHash_value(_Keyval2);
  } 
};
//--------------------------------------------------------
//用于open表比较的仿函数(优先级队列)
struct NodeCmp
{
 bool operator()(AStarNode* node1,AStarNode* node2)
 {
  return node1->f_Cost > node2->f_Cost;
 }
};

//搜索者类
class CActor
{
public:
 int ID;           //唯一标识符
 bool m_IsSearch;    //标志是否正在寻路 
 Pos m_NowPos;       //当前位置
 Pos m_TargetPos;    //目的地  

 //构造函数
 CActor(int id, const Pos& startPos,CMap* pMap):ID(id),m_NowPos(startPos),
        m_TargetPos(startPos),m_Map(pMap),m_IsSearch(false) {}
 ~CActor(); //析构函数

 void run();       //寻路执行函数 
 void setTarget(const Pos& target);
private:
 CMap* m_Map;         //地图指针(用于寻路)
 deque<Pos> m_Path;   //返回的路径
 
 int m_StartTimeCount;//启动计数器
 int m_WaitTimeCount; //被阻塞时的等待时间
 Pos m_OldTargetPos;  //正在执行的目的地
 
 //搜索状态枚举(0-尝试绕过,1-等一会,2-找条新路,3-一直等待, 4-等待开始)
 enum STATE {TryRound=0,WaitAwhile=1,TryAntoherPath=2,WaitAlong=3,WaitStart=4};
 STATE m_State; //搜索状态

 CConMap m_NodeCon;    //A*节点容器(容纳open,closed表中节点) 
 priority_queue<AStarNode*,vector<AStarNode*>,NodeCmp> m_Open;  //open表(存储节点指针)
 
 AStarNode* astar(const Pos& startPos,const Pos& endPos,int MaxClosed);  //AStar执行函数

 void createPath(AStarNode* pNode,deque<Pos>& path); //生成路径
 //构造节点
    AStarNode* createNode(const Pos& pos,const Pos& targetPos,char flag,int g,AStarNode* parentNode);   
 void expandNode(AStarNode* node,const Pos& targetPos); //扩展节点
 //对当前扩展的节点进行处理
 void dealNode(const Pos& pos,const Pos& targetPos,int g,AStarNode* parentNode);
 bool judgeAccess(const Pos& pos); //判断该点是否可走
};

CConMap.h

------------------------------------------------------------------------------------------

#pragma once
#include "stdafx.h"
#include "CParam.h"
#include "utils.h"


class CConMap

 
public:
 typedef Pos   POSITION;
 typedef AStarNode NODE;
 void createCon(const int& width, const int& height)
 {
  m_iWidth = width;
  m_iHeight= height;
  m_iCount = 0;
  m_Con = new NODE [width*height];
 }

 void insert(std::pair<POSITION,NODE>& Elem);
 NODE* find(const POSITION& pos);
 
 int  size() {return m_iCount;}
 void clear()
 {
  m_iCount = 0;
  delete[] m_Con;
 }
 bool empty(){return m_iCount == 0;}
 
private:
 NODE* m_Con; //一个容器
 int  m_iCount; //容器的大小
 int  m_iWidth;
 int  m_iHeight;
};

CControl.h

--------------------------------------------------------------------------

#pragma once
#include "utils.h "
#include "stdafx.h"
#include "CSearch.h"
//#include "CDraw.h"
 

//           CControl 类
//  主要进行读取键盘鼠标等输入操作
//
class CDraw;
class CSearch;

class CControl
{
public:
 CControl(CSearch* search):m_Search(search), m_Pos(0,0),
  m_MapPos(0,0),m_State(STATE::Wait),m_SelectID(-1),m_IsSearch(false) { }  //构造函数
 ~CControl(){}          //析造函数 

 RECT getDrawArea( ) const;                      //获取控制区域
 void setDrawArea(int x,int y ,int w,int h);       //设置控制区域
 void setDrawArea(const RECT& _rect);             //设置控制区域

 void readMeasage(HWND hwnd,UINT msg,   WPARAM wparam,    LPARAM lparam);  //读取消息 

 bool m_IsSearch;  //显示寻路 

 friend class CDraw; //友元
private:
    bool checkMousePos(int _x,int _y) ;    //鼠标位置合法性检查,并转化为地图坐标方式
    bool checkMousePos(const Pos& pos);    //鼠标位置合法性检查,并转化为地图坐标方式
 void transToMapPos();  //把鼠标坐标转化为地图坐标
  
 RECT     rect ;            //控制区域,区域之外不捕获鼠标输入
 Pos      m_Pos;            //鼠标坐标
    Pos      m_MapPos;         //地图坐标
 CSearch*  m_Search;         //保存search指针
   
 enum STATE {Wait=0,ChangeMap=1,AddActor=2,SelectActor=3}; //状态枚举
 STATE     m_State;             //当前状态
 int       m_SelectID;          //被选中搜索者的ID, -1表示未选中 
 vector<CActor>::iterator  m_SelectIter; //被选中的搜索者
 
};

CDraw.h

----------------------------------------------------------------------

#pragma once
#include "utils.h "
#include "stdafx.h"
#include "search.h"
#include "CParam.h"
#include "CControl.h"
#include "DirectFunction.h"

//           DirectDraw 类
//  主要进行显示
//

class CDraw
{
public:
    CDraw (HWND hwnd,CSearch* search,CControl* control);                         //构造函数
 ~ CDraw( );                                //析构函数

 void drawBlock()   ;               //绘制地图上的障碍物

 RECT getDrawArea( ) const;                             //获取显示区域
 void setDrawArea(int x,int y ,int w,int h);  //显示区域的设定(地图)
 
 void display ( )   ;                                  //显示函数
 void drawActor( )  ;                                  //画搜索者
 void drawAim ( )   ;                                  //画出目的地
 void displayOnScreen()     ;                          //显示到屏幕上 
 void displayCoordinate( ) ;                          //显示坐标函数
 void displayMessage();                               //显示消息
 void displayBackGround(BITMAP_FILE& map);                           //显示背景

private: 
 void drawRect (RECT rect,COLORREF color );          //绘制矩形
 void drawRect (int x,int y ,int w,int h,COLORREF color=_RGB32BIT(0,0, 0, 0) );          //绘制矩形
 void drawBoardLine(int x,int y ,int w,int h, int penWidth=1, int penStyle=PS_SOLID,COLORREF color=_RGB32BIT(0,0, 0, 0)) ;     //画边线框
 void createMapByBitMap(set<Pos>& blockCon);

 int m_Wide          ;                      // 地图宽                  
 int m_Hight         ;                      // 地图高
 int m_BeginX        ;                      // 开始点X
 int m_BeginY        ;                      // 开始点Y
    int m_SpaceH        ;                      // 高间距
 int m_SpaceW        ;                      // 宽间距

    RECT rect           ;                      //绘制区域(此处有点数据冗余但是使用较为方便)
 RECT rw             ;                      //窗口模式大小

 BITMAP_FILE           bitmap      ;         // 位图
 BITMAP_FILE           themap      ;         // 位图
    LPDIRECTDRAW7         lpdd       ;          //Direct对象
 LPDIRECTDRAWSURFACE7  lpddsprimary ;          //主显示表面
 LPDIRECTDRAWSURFACE7  lpddsback    ;          //后备
 LPDIRECTDRAWPALETTE   lpddpal      ;          // 指向调色板信息
 LPDIRECTDRAWCLIPPER   lpddclipper  ;          // 裁剪器
 PALETTEENTRY          palette[256] ;         // 调色板
 PALETTEENTRY          save_palette[256];      // 保存调色板
 DDSURFACEDESC2        ddsd   ;               // Direct信息结构
 DDBLTFX               ddbltfx;              // 填充结构
 DDSCAPS2              ddscaps;              // 绘制表面信息结构
 HRESULT               ddrval ;              // Direct调用返回结果
 DWORD                 m_StartClockCount ;    // 用来计时
    HWND                  m_WindowHandle;       // 全局函数句柄
 
 char buffer[80];
 CSearch* m_Search;
 CControl* m_Control;
 
};

CMap.h

---------------------------------------------------------------

#pragma once
#include "stdafx.h"
#include "utils.h"
#include "CParam.h"


//地图类
class CMap
{
public: 
 
 CMap():m_Width(0),m_Height(0) {}; 
 ~CMap(); //析构函数

    void loadMap(set<Pos>& blockCon,vector<Pos>& actorPos);  //载入地图
 void saveMap();    //保存地图

 int  width()const {return m_Width;}    //返回地图宽度
 int  height()const {return m_Height;}  //返回地图高度

 bool isBlock(const Pos& pos)const {return m_Map[pos.y][pos.x]==m_Block;} //坐标pos是否为障碍物
 bool isAccess(const Pos& pos)const {return m_Map[pos.y][pos.x]==m_Access;} //坐标pos是否为通路
 bool isActor(const Pos& pos)const {return m_Map[pos.y][pos.x]==m_Actor;}  //坐标pos是否有搜索者

 void setBlock(const Pos& pos) {m_Map[pos.y][pos.x] = m_Block;}   //修改节点为障碍物
 void setAccess(const Pos& pos) {m_Map[pos.y][pos.x] = m_Access;} //修改节点为通路
 void setActor(const Pos& pos) {m_Map[pos.y][pos.x] = m_Actor;}   //在节点上添加物品 
private:
 char**  m_Map;   //地图信息 ('0'--障碍物,'1'--通路,'2'--有搜索者)
 char m_Block;    //障碍物字符
 char m_Access;   //通路字符
 char m_Actor;    //搜索者字符

 int  m_Width;      //地图宽度
 int  m_Height;     //地图高度   
}; 


CParam.h

------------------------------------------------------------------------

#pragma once
#include "stdafx.h"

//参数类,用于载入配置信息
class CParam
{
public:
 CParam(); //构造函数
 
    static string loadMapName; //载入地图的文件名
 static string saveMapName; //保存地图的文件名 
    //--------------------------------------------------
    static int oneBiasCost;    //斜走一步开销
    static int oneNoBiasCost;  //横竖走一步开销
    static int waitTime;       //被挡住时等待次数
    static int permitDisdance; //允许的最优点到目的地的最大距离
    static int tryRoundBlock;  //尝试绕开的障碍物最大个数
    static int tryStartTimes;  //启动计数器的最大值
 static int startConSize;
 static int startProHCost;

 static int RStepBegin; //红色的起始阀值
 static int GStepBegin; //绿色的起始阀值
 static int BStepBegin; //蓝色的起始阀值

 static int RStepEnd; //红色的结束阀值
 static int GStepEnd; //绿色的结束阀值
 static int BStepEnd; //蓝色的结束阀值
 //--------------------------------------------------
 static int displayX    ; //屏幕上显示的地图起点X
 static int displayY    ; //屏幕上显示的地图起点Y
 static int displayWidth; //屏幕显示的地图宽度
 static int displayHight; //屏幕显示的地图高度
 //-------------------------------------------------

 static bool bDisOppo;    //是否显示反色
};

CSearch.h

________________________________________________________

#pragma once
#include "stdafx.h"
#include "utils.h"
#include "CMap.h"
#include "CActor.h"

class CDraw;

//搜索类,由用户使用
class CSearch

public: 
 typedef vector<CActor>::iterator VI;
    CSearch(); //构造函数  

 void addActor(const Pos& startPos); //添加搜索者
 void delActor(const VI actor);      //删除搜索者
 bool setTargetPos(const VI actor,const Pos& targetPos);   //设置搜索者目标点 
 void changeMap(const Pos& pos);  //修改地图 
 bool runOneTimes(); //执行搜索一次

 friend class CDraw;  //友元
 friend class CControl;

private: 
 vector<CActor> m_ActorCon;  //搜索者容器
 CMap  m_Map;                //地图
 set<Pos> m_BlockCon;        //障碍物容器

    bool locateActor(const Pos& pos,VI& select); //定位搜索者 
};


DirectFunction.h

___________________________________________________________

#pragma once
#include "utils.h "
#include "stdafx.h"
#include "search.h"

//显示文字
int Draw_Text_GDI( LPDIRECTDRAWSURFACE7& lpdds,char *text, int x,int y, COLORREF color);
//画直线
void Draw_Line ( LPDIRECTDRAWSURFACE7& lpdds,int Ax,int Ay, int Bx,int By, int penWidth=1,int penStyle=PS_SOLID,COLORREF color=_RGB32BIT(0,0, 0, 0));
// 初始化内存为0  ,必须是引用
#define DDRAW_INIT_STRUCT(ddstruct) { memset(&ddstruct,0,sizeof(ddstruct)); ddstruct.dwSize=sizeof(ddstruct); }
//切换图像
bool Flip_Bitmap(UCHAR *image, int bytes_per_line, int height);
//载入图像
bool Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename);
//卸载图像
bool Unload_Bitmap_File(BITMAP_FILE_PTR bitmap);

resource.h

______________________________________________________

//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by 瓜西西AStar.rc
//

// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE        102
#define _APS_NEXT_COMMAND_VALUE         40001
#define _APS_NEXT_CONTROL_VALUE         1001
#define _APS_NEXT_SYMED_VALUE           101
#endif
#endif

stdafx.h

_________________________________________________________

#pragma once

#define WIN32_LEAN_AND_MEAN
#define INITGUID

//---------该处添加所需库文件
#include <vector>
#include <queue>
#include <hash_map>
#include <set>
#include <string>
#include <fstream>
#include <iostream>

#include <windows.h>  
#include <windowsx.h>
#include <mmsystem.h>
#include <conio.h>
#include <stdlib.h>
#include <malloc.h>
#include <memory.h>
#include <string>
#include <stdarg.h>
#include <stdio.h>
#include <math.h>
#include <fcntl.h>
#include <ddraw.h>
#include <io.h>

using namespace std;

utils.h


________________________________________________________________

#pragma once
#include "stdafx.h"

//----------------全局常量
const int SCREEN_WIDTH=800 ;
const int SCREEN_HEIGHT=600;
const int SCREEN_BPP   =32;

//---------------全局变量
static int       window_closed      ;    // 跟踪窗口是否销毁
static HINSTANCE hinstance_app      ;    //全局函数实例
static HWND      main_windows_hwnd  ;    //全局窗口句柄
//---------------定义类型别名
typedef unsigned short USHORT;
typedef unsigned short WORD;
typedef unsigned char  UCHAR;
typedef unsigned char  BYTE;

//--------------------宏定义
#define WINDOW_CLASS_NAME "WINCLASS1"
#define BITMAP_ID            0x4D42          //位图格式标志
#define KEYDOWN(vk_code) ((GetAsyncKeyState(vk_code) & 0x8000) ? 1 : 0)
#define KEYUP(vk_code)   ((GetAsyncKeyState(vk_code) & 0x8000) ? 0 : 1)

//图像颜色编码方式
#define _RGB16BIT555(r,g,b) ((b & 31) + ((g & 31) << 5) + ((r & 31) << 10)) // 16色位图 5. 5 .5 1位a
#define _RGB16BIT565(r,g,b) ((b & 31) + ((g & 63) << 5) + ((r & 31) << 11))// 16色位图 5.6.5 绿色多一位
#define _RGB32BIT(a,r,g,b) ((b) + ((g) << 8) + ((r) << 16) + ((a) << 24))  // 32色位图 8.8.8 8位a


//------------该处添加所需全局结构
//坐标结构
struct Pos
{
 int x;
 int y;
 Pos():x(0),y(0){}
 Pos(int _x,int _y):x(_x),y(_y) {}
 
 
 bool operator==(const Pos& rhs)   //相等判断  
 {
  return (x==rhs.x && y==rhs.y);
 }
 
 friend bool operator <(const Pos& pos1,const Pos& pos2)
 {
  if(pos2.y > pos1.y)
   return true;
  if(pos1.y > pos2.y)
   return false;  
  if(pos2.x > pos1.x)
   return true;
  return false;
 }
};

//位图结构
typedef struct BITMAP_FILE_TAG
{
        BITMAPFILEHEADER bitmapfileheader;  //位图文件头信息
        BITMAPINFOHEADER bitmapinfoheader;  // 调色板信息
        PALETTEENTRY     palette[256];      // 储存调色板v
        UCHAR            *buffer;           // 指向位图数据指针
} BITMAP_FILE, *BITMAP_FILE_PTR;

//A*节点结构
struct AStarNode
{
 Pos pos;           //坐标   
 int f_Cost;        //总开销
 int g_Cost;        //实际开销
 int h_Cost;        //估价开销
 char flag;         //状态标志('o'--在open表中,'c'--在closed表中)  
 AStarNode* parent; //父节点

 enum {INFINITY = 2147483646};
 AStarNode(){g_Cost = INFINITY;}   
 AStarNode(const Pos& _pos, char _flag, AStarNode* _parent)
  :pos(_pos),flag(_flag),parent(_parent) {}
 
 
 //重载运算符
 bool operator==(AStarNode& node) {return pos==node.pos;}
 bool operator <(AStarNode& node) {return f_Cost < node.f_Cost;}
};

CActor.cpp

_____________________________________________________________

#include "CActor.h"


//析构函数
CActor::~CActor()
{
    while(!m_Open.empty()) //清空open
  m_Open.pop();
 //m_NodeCon.clear();     //清空节点容器
}

//寻路执行函数(执行一步)
void CActor::run()

 Pos aim; 

 while (1)
 {  
  if(m_Path.empty() || !(m_OldTargetPos == m_TargetPos)) //执行队列为空或目标地改变时
  {
   m_Path.clear();
   m_WaitTimeCount = 0;
   m_OldTargetPos = m_TargetPos;  
   AStarNode* node = astar(m_NowPos,m_TargetPos,200000); //调用Astar
   
   if(node->h_Cost < CParam::permitDisdance)
   {
    m_Path.clear();
    m_OldTargetPos = m_TargetPos;
    createPath(node,m_Path);      //生成执行队列
    
    m_NodeCon.clear();      //清空节点容器
     
   }
   else
   {
    if (m_NodeCon.size() > CParam::startConSize && node->h_Cost < CParam::startProHCost)
    {
     if (m_StartTimeCount++ > CParam::tryStartTimes)
     {
      createPath(node,m_Path);      //生成执行队列
      m_NodeCon.clear();      //清空节点容器
      break;
     }
     else
     {
      m_NodeCon.clear();      //清空节点容器
      m_State = STATE::WaitStart;
      break;
     }

    }//end if (m_NodeCon.size() > 200 && m_Open.empty() && node->h_Cost < 50)
    m_State = STATE::WaitStart;
    m_NodeCon.clear();      //清空节点容器
    break;

   }//end if(node->h_Cost < CParam::permitDisdance)
      
  } //if(m_Path.empty() || !(m_OldTargetPos == m_TargetPos)) //执行队列为空或目标地改变时
  
  if (m_Path.empty())
  {
   break;
  }

  if (m_State != STATE::WaitAlong)
  { 
   m_State = STATE::TryRound;
  }
  aim = m_Path.front();

  //如果能够继续下一步
  if (m_Map->isAccess(aim))
  {   
   //执行下一步
   m_State = STATE::TryAntoherPath;
   m_Path.pop_front(); 
   m_Map->setActor(aim);
   m_Map->setAccess(m_NowPos);
   m_WaitTimeCount = 0;
   m_NowPos = aim;   
   break;
  }   
  
  //尝试绕开
  if(m_State==STATE::TryRound)
  {
   bool success = false;
   for(unsigned int i=1;i < m_Path.size() && i <= CParam::tryRoundBlock;i++)
   {
                if(m_Map->isAccess(m_Path[i]))
    {
     AStarNode* node = astar(m_NowPos,m_Path[i],10);
     if(node->pos == m_Path[i])
     {
      success = true;
      deque<Pos> path;
      createPath(node,path);  //生成绕开路径
      m_NodeCon.clear();      //清空节点容器
       
      m_Path.erase(m_Path.begin(),m_Path.begin()+i);//删除障碍物路径
      path.pop_back();
      m_Path.insert(m_Path.begin(),path.begin(),path.end()); //插入绕开路径
      break;
     }
     m_NodeCon.clear();
     break;
    }
    
   }
   if(success==true)
    continue;
   m_State = STATE::WaitAwhile;
  }

        //等待一会
        if(m_State == STATE::WaitAwhile)
  {
   if(m_WaitTimeCount++ <= CParam::waitTime)
    break;
   m_State = STATE::TryAntoherPath;
   m_WaitTimeCount = 0;
  }
           
  //搜索新路径
  if(m_State == STATE::TryAntoherPath)
  {
   AStarNode* node = astar(m_NowPos,m_TargetPos,200000);
   if(node->h_Cost < CParam::permitDisdance)
   {
    m_Path.clear();
    m_OldTargetPos = m_TargetPos;
    createPath(node,m_Path);  //生成新路径
    m_State = STATE::TryRound;
    
    m_NodeCon.clear();      //清空节点容器
     
    continue;
   }
   
   m_NodeCon.clear();      //清空节点容器
   m_State = STATE::WaitAlong;
  }

        //一直等待
  if(m_State == STATE::WaitAlong)
   break;  
    
 }

 if (m_Path.empty()&&m_State != STATE::WaitStart)
 {  
  m_IsSearch = false;
  return;
 }
 
}


//生成路径
void CActor::createPath(AStarNode* pNode,deque<Pos>& path)
{  
 while(pNode->parent!=NULL)
 {
  path.push_front(pNode->pos);
  pNode = pNode->parent;
 }
}

//AStar执行函数(起点,终点,closed表上限)
AStarNode* CActor::astar(const Pos& startPos,const Pos& endPos,int closedMax)
{  
 
 AStarNode* pNode;
 AStarNode* bestNode; //最优节点
 int closedCount = 0; //closed表元素个数计数器

 m_NodeCon.createCon (m_Map->width(),m_Map->height());
 //把出发点入节点容器
 bestNode = createNode(startPos,endPos,'o',0,NULL);  
 m_Open.push(bestNode);  //出发节点入open表 

 while(1)
 {
  //超过closed表上限或open表为空
  if(closedCount > closedMax || m_Open.empty())
  {   
   while(!m_Open.empty())  //清空open
     m_Open.pop();
   return bestNode;
  }

  pNode = m_Open.top(); //取出f值最小的节点,放入closed表
  pNode->flag = 'c';
  closedCount++; //closed计数器加1
  m_Open.pop();

  if(pNode->h_Cost < bestNode->h_Cost)
  {
   bestNode = pNode; //记录最优节点
  }

  if(pNode->pos == endPos)  //已到目标点
  {   
   while(!m_Open.empty())  //清空open
    m_Open.pop();
   return bestNode;
  }
        expandNode(pNode,endPos);    //扩展该节点  
 } 
}

//构造节点(返回节点容器中该节点地址)
AStarNode* CActor::createNode(const Pos& pos,const Pos& targetPos,char flag,int g,AStarNode* parentNode)
{
 AStarNode newNode(pos,'o',parentNode); 
 newNode.g_Cost = g;
 newNode.h_Cost = CParam::oneNoBiasCost*(abs(pos.x-targetPos.x) + abs(pos.y-targetPos.y)); //
 newNode.f_Cost = g + newNode.h_Cost;
 m_NodeCon.insert(pair<Pos,AStarNode>(pos,newNode));

 return m_NodeCon.find(pos);
}


//扩展节点(按8叉方式)
void CActor::expandNode(AStarNode* node,const Pos& targetPos)
{
 int _x = node->pos.x; //该节点坐标
 int _y = node->pos.y;
 int _g = node->g_Cost;
 Pos pos;
 int gCost;
  
 //左上
 pos.x = _x-1;
 pos.y = _y-1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //上
 pos.x = _x;
 pos.y = _y-1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneNoBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //右上
 pos.x = _x+1;
 pos.y = _y-1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //左
 pos.x = _x-1;
 pos.y = _y;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneNoBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //右
 pos.x = _x+1;
 pos.y = _y;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneNoBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //左下
 pos.x = _x-1;
 pos.y = _y+1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //下
 pos.x = _x;
 pos.y = _y+1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneNoBiasCost;
  dealNode(pos,targetPos,gCost,node);
 }
 //右下
 pos.x = _x+1;
 pos.y = _y+1;
 if(judgeAccess(pos)==true)
 {
  gCost = _g + CParam::oneBiasCost;
  dealNode(pos,targetPos,gCost,node);
 } 
}

//对当前扩展的节点进行处理
void CActor::dealNode(const Pos& pos,const Pos& targetPos,int g,AStarNode* parentNode)
{
 AStarNode* iter;
 iter = m_NodeCon.find(pos); //在节点容器中查找
 AStarNode* node;

 if(iter != NULL)
 {
  node = iter;
  if(node->g_Cost > g)
  {
   node->g_Cost = g;
   node->parent = parentNode;
   if(node->flag=='c')
   {
    node->flag = 'o';
    m_Open.push(node); //在closed表中就放入open
   }
  }  
  return;
 }

    //不在节点容器中就构造新节点
 node = createNode(pos,targetPos,'o',g,parentNode); 
 m_Open.push(node);

 return;
}

//判断该点是否可走
bool CActor::judgeAccess(const Pos& pos)
{
 if(pos.x<0 || pos.x>=m_Map->width())
  return false;
 if(pos.y<0 || pos.y>=m_Map->height())
  return false;
 return m_Map->isAccess(pos);
}


void CActor::setTarget(const Pos& target)
{
 m_StartTimeCount = 0;
 m_WaitTimeCount  = 0;
 m_TargetPos = target;
}

CConMap.cpp

______________________________________

#include "CConMap.h"

//插入函数
void CConMap::insert(std::pair<POSITION,NODE>& Elem)
{
 ++m_iCount;
 m_Con[Elem.first.x + Elem.first.y*m_iWidth] = Elem.second;
}

//查找函数
CConMap::NODE* CConMap::find(const POSITION& pos)
{
 if ( pos.x >= 0 && pos.x < m_iWidth && pos.y >= 0 && pos.y < m_iHeight)
  if (m_Con[pos.x  + pos.y*m_iWidth].g_Cost == AStarNode::INFINITY)
  {
   return NULL;
  }
  else
  {
   return &m_Con[pos.x  + pos.y*m_iWidth];
  }
 else
  return NULL;
}

CControl.cpp

_____________________________________________

#include "CControl.h"


void CControl::readMeasage(HWND hwnd,UINT msg,   WPARAM wparam,    LPARAM lparam)
{
 if (KEYDOWN(VK_ESCAPE))
 {
    PostMessage(hwnd,WM_CLOSE,0,0);
 }

 switch(msg)
 { 
 case WM_MOUSEMOVE:
  {  
   m_Pos.x=LOWORD(lparam)+4;
   m_Pos.y=HIWORD(lparam)+20;
  } break;  
 case WM_LBUTTONDOWN:
  {
   if(checkMousePos(m_Pos)==false)
    break;   

   switch(m_State)
   {
   case STATE::AddActor: //添加搜索者
    if(m_Search->m_Map.isAccess(m_MapPos))
     m_Search->addActor(m_MapPos);
    break;

   case STATE::ChangeMap: //修改地图    
    m_Search->changeMap(m_MapPos);  
    break;

   case STATE::SelectActor: //设置搜索者目的地
    m_Search->setTargetPos(m_SelectIter,m_MapPos);
    if(!m_Search->m_Map.isActor(m_MapPos))
     break;         

   default:  //定位搜索者
    if(m_Search->locateActor(m_MapPos,m_SelectIter)==true)
       {
     m_SelectID = m_SelectIter->ID;
     m_State = STATE::SelectActor;     
          }        
   }   
  }break;
 case WM_RBUTTONDOWN:
  {
   m_State = STATE::Wait;
  }break;
 case WM_CHAR:
  {
   switch(wparam)
   {    
   case 'a':
   case 'A'://按A键添加搜索者
    m_State = STATE::AddActor;
    break;
   case 'c':
   case 'C'://按C键修改地图
    m_State = STATE::ChangeMap;
    break; 
    
   case 'd':
   case 'D'://按D键删除搜索者
    if(m_State==STATE::SelectActor)
    {
     m_Search->delActor(m_SelectIter);
     m_State = STATE::Wait;
     m_SelectID = -1;
    }
    break;
   case 'o':
   case 'O'://按o键显示反色
    CParam::bDisOppo = !CParam::bDisOppo;
   break;

   case 's':
   case 'S'://按S键保存地图
    m_Search->m_Map.saveMap();
    break;

   case 'z':
   case 'Z'://单步执行
    m_Search->runOneTimes();
    break;
   case 'x':
   case 'X'://连续执行(再按次取消)    
    m_IsSearch = !m_IsSearch; 
    break;
   case 'h':
   case 'H':
    MessageBox(hwnd, "作者:西南科技大学  白礼彬 蔡孝府  唐坤 ",
             "关于作者",     MB_OK );
   default:
    break;
   }
  }break;
 default:
  break;
    }
}

//获取控制区域
RECT CControl::getDrawArea( ) const
{
 return rect;
}

//设置控制区域
void CControl::setDrawArea(const RECT& _rect)
{
 rect=_rect;
}

//设置控制区域
void CControl::setDrawArea(int x,int y ,int w,int h)
{
 rect.left=x;
 rect.top=y;
 rect.right=w+rect.left;
 rect.bottom=h+rect.top;
}

//鼠标位置合法性检查
bool CControl::checkMousePos(int _x,int _y)
{
 if(_y>rect.bottom)
 { return false;}
 if(_y<rect.top)
   { return false;}
 if(_x<rect.right)
    { return false;}
 if(_x>rect.right)
 { return false;}

 transToMapPos();
 return true;
}

//鼠标位置合法性检查
bool CControl::checkMousePos(const Pos& pos)
{
 if( pos.y>rect.bottom )
 { return false;}
 if( pos.y<rect.top )
    { return false;}
   if( pos.x<rect.left )
    { return false;}
 if( pos.x>rect.right )
 { return false;}

 transToMapPos(); 
 return true;
}

//把鼠标坐标转化为地图坐标
void CControl::transToMapPos()
{
 int perXGridPixel = (rect.right-rect.left)/m_Search->m_Map.width();//每横格所占象素
 int perYGridPixel = (rect.bottom-rect.top)/m_Search->m_Map.height();//每竖格所占象素
 m_MapPos.x = (m_Pos.x-rect.left)/perXGridPixel;
 m_MapPos.y = (m_Pos.y-rect.top)/perYGridPixel;
}


CDraw.cpp

_____________________________________________________

#include "CDraw.h"

 //构造函数
 CDraw::CDraw(HWND hwnd,CSearch* search,CControl* control):m_WindowHandle(hwnd),lpdd (NULL), lpddsprimary (NULL), lpddsback(NULL),
                    lpddpal(NULL), lpddclipper(NULL), m_StartClockCount (0),
     m_BeginX(CParam::displayX),m_BeginY(CParam::displayY),m_Wide(CParam::displayWidth), m_Hight(CParam::displayHight),
     m_Search(search),m_Control(control)
     

 window_closed=1;
 //创建Direct7接口对象并且对其进行测试
 if (FAILED(DirectDrawCreateEx(NULL, (void **)&lpdd, IID_IDirectDraw7, NULL)))
 {  return ; }
 //设置显示模式到全屏
 if (FAILED(lpdd->SetCooperativeLevel(m_WindowHandle,
                                    DDSCL_NORMAL    //窗口模式但有问题
     //DDSCL_FULLSCREEN | DDSCL_ALLOWMODEX |  DDSCL_EXCLUSIVE | DDSCL_ALLOWREBOOT
                 )))
 {   return ;  }

 // 创建主显示表面
 DDRAW_INIT_STRUCT(ddsd)  ;                                  //清空内存    
    ddsd.dwFlags =  DDSD_CAPS ;                                // 初始有效区域
 ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE ;            // 申请主显示表面 
 if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsprimary, NULL)))
 { exit(0) ;}

 // 创建从显示表面
 GetWindowRect(m_WindowHandle,&rw); 
 DDRAW_INIT_STRUCT(ddsd)  ; 
 ddsd.dwFlags =  DDSD_CAPS |DDSD_WIDTH | DDSD_HEIGHT ;  
 ddsd.ddsCaps.dwCaps = DDSCAPS_VIDEOMEMORY ;
 ddsd.dwHeight = rw.bottom-rw.top;
 ddsd.dwWidth = rw.right-rw.left;
 if (FAILED(lpdd->CreateSurface(&ddsd, &lpddsback, NULL)))
 { exit(0) ;} 

 
 LPDIRECTDRAWCLIPPER clip=NULL;
 if(FAILED(lpdd->CreateClipper(0, &clip, NULL)))
  return ;
 if(FAILED(clip->SetHWnd(0, m_WindowHandle)))
  return ;
 if(lpddsprimary->SetClipper(clip))
  return ;

 if(clip!=NULL)
  clip->Release();
  
 //direct显示区域
 //SendMessage(m_WindowHandle,WM_SYSCOMMAND,SC_MINIMIZE,0);
 //初始化地图
 setDrawArea(m_BeginX,m_BeginY,m_Wide, m_Hight);
 //载入地图
 if (!Load_Bitmap_File( &bitmap,"bitmap24.bmp"))
 { return ;}
 if (!Load_Bitmap_File( &themap,"bitmap24.bmp"))
 { return ;}
 /*if (!Load_Bitmap_File( &themap,"map.bmp"))
 { return ;}*/
 createMapByBitMap(m_Search->m_BlockCon);

 //设置显示模式为800*600*24 SCREEN_WIDTH*SCREEN_HEIGHT* SCREEN_BPP
// if (FAILED(lpdd->SetDisplayMode( SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP,0,0)))
// {  return ;   }

}

//析构函数
CDraw::~CDraw()
{  
 //卸载图片资源
 Unload_Bitmap_File(&bitmap);

 if (lpddsprimary)                   // 释放主显示表面
 {
  lpddsprimary->Release();
  lpddsprimary = NULL;
 }

 if (lpddsback)                   // 释放主显示表面
 {
  lpddsback->Release();
  lpddsback = NULL;
 }

 if (lpdd)                         // 释放direct接口
 {
  lpdd->Release();
  lpdd = NULL;
 }
}

//显示区域的设定(地图)
void CDraw::setDrawArea (int x,int y,int w,int h )
{
 m_BeginX=x;
 m_BeginY=y;
 m_Wide  =w;
 m_Hight  =h; 

 //初始化间距
 m_SpaceW = m_Wide/( m_Search->m_Map.width()  ); 
 m_SpaceH = m_Hight/( m_Search->m_Map.height() );

 //显示地图区域
 rect.left = m_BeginX ;          
 rect.top  = m_BeginY ;
 rect.bottom = rect.top + m_Hight;
 rect.right  = rect.left + m_Wide;

 //更新Ccontrol中显示区域
 m_Control->rect=rect;
}

//获取显示区域
RECT CDraw::getDrawArea( )  const
{
 return rect;
}
 //显示函数
void CDraw::display()
{
 if( window_closed==0)
 { return ;}
 if(CParam::bDisOppo==true)
 {
  displayBackGround(themap);
 }
 else
 {
  displayBackGround(bitmap);
 }
 
  drawActor(  );
  displayCoordinate( ); 
  displayMessage();
  drawAim(); 
  displayOnScreen();
}

   //显示到屏幕上 
void CDraw::displayOnScreen()
{
 //纵线
 Draw_Line( lpddsback, rect.left ,rect.top ,rect.left  ,rect.bottom  );
 Draw_Line( lpddsback, rect.left+m_Search->m_Map.width()*m_SpaceW ,rect.top ,
  rect.left+m_Search->m_Map.width()*m_SpaceW  ,rect.bottom  );

 //横线
 Draw_Line( lpddsback, rect.left ,rect.top+m_Search->m_Map.height()*m_SpaceH,rect.right  ,rect.top+m_Search->m_Map.height()*m_SpaceH  );
 Draw_Line( lpddsback, rect.left,rect.top ,rect.right ,rect.top  );

/*
 //纵线
 for(int n=m_Search->m_Map.width() ; n>0 ;n--)
 {
  Draw_Line( lpddsback, rect.left+m_SpaceW*n ,rect.top ,rect.left+m_SpaceW*n  ,rect.bottom  );
 } 
 //横线
 for(int n=m_Search->m_Map.height(); n>0 ;n--)
 { 
  Draw_Line( lpddsback, rect.left  ,rect.top+m_SpaceH*n , rect.right   ,rect.top+m_SpaceH*n );
 } 
*/
 /*
 if(FAILED(lpddsprimary->Flip(NULL, DDFLIP_WAIT) ))
 { return ;} 
   
 DDRAW_INIT_STRUCT(ddbltfx);
 if (FAILED(lpddsback->Blt(&rw,lpddsprimary ,NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
 {  return ;} 

 DDRAW_INIT_STRUCT(ddbltfx);
 ddbltfx.dwFillColor =_RGB32BIT(0,0, 0, 0);                          //将全屏归0
 if (FAILED(lpddsback->Blt(NULL, NULL,  NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
 {  return ;}
 */
 GetWindowRect(m_WindowHandle,&rw);

 if (FAILED(lpddsprimary->Blt(&rw, lpddsback, NULL, DDBLT_WAIT,NULL)))
 { return ;} 

 DDBLTFX ddbltfx;
 ddbltfx.dwSize =sizeof(ddbltfx);
 ddbltfx.dwFillColor =0x0;

 if (FAILED(lpddsback->Blt(NULL, NULL,  NULL, DDBLT_COLORFILL , &ddbltfx)))
 {  return ;}
}

//绘制地图上的障碍物
void CDraw::drawBlock()

 if(m_Search->m_BlockCon.empty())
 { return ;}

 DDRAW_INIT_STRUCT(ddbltfx);
 ddbltfx.dwFillColor = _RGB32BIT(0,0, 0, 255); 
 if (FAILED(lpddsback->Blt(&rect, NULL,  NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
 {  return ;}    
 
 RECT rectTemp;
 set<Pos>::iterator iter=m_Search->m_BlockCon.begin();
 for( ;iter!=m_Search->m_BlockCon.end();iter++)
 {
  rectTemp.left = (*iter).x *m_SpaceW     +rect.left;   
  rectTemp.top  = (*iter).y*m_SpaceH      +rect.top ; 
  rectTemp.right= rectTemp.left + m_SpaceW  ;                
  rectTemp.bottom=rectTemp.top  + m_SpaceH  ;   
  drawRect(rectTemp,_RGB32BIT(0,128,0, 0))  ;
 }
}

 //显示消息
void CDraw::displayMessage()
{
 Draw_Text_GDI(lpddsback,"H键----关于作者",600,50,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"Esc键----退出",600,100,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"A键----添加搜索者",600,125,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"C键----修改地图",600,150,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"D键----删除搜索者",600,175,RGB(255,0,0)) ; 
 Draw_Text_GDI(lpddsback,"X键----执行/取消 搜索连续",600,200,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"Z键----执行/取消 单步搜索",600,225,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"鼠标左键----选择定位",600,250,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"鼠标右键----取消操作",600,270,RGB(255,0,0)) ;
 Draw_Text_GDI(lpddsback,"搜索者",620,300,RGB(0,255,0)) ;
 Draw_Text_GDI(lpddsback,"目的地",620,320,RGB(255,220,0 )) ;
}

//显示鼠标位置
void CDraw::displayCoordinate()
{  
 sprintf(buffer,"坐标: %d", m_Control->m_Pos.x ); 
 Draw_Text_GDI(lpddsback,buffer,700,100,RGB(255,0,0));

 sprintf(buffer,"坐标: %d", m_Control->m_Pos.y ); 
 Draw_Text_GDI(lpddsback,buffer,700,150,RGB(255,0,0));   
}

//显示搜索者
void CDraw::drawActor(  )
{
 if(m_Search->m_ActorCon.empty())
 { return ;}

 RECT rectTemp;
 vector<CActor>::iterator iter =m_Search->m_ActorCon.begin();
 for( ;iter!=m_Search->m_ActorCon.end();iter++)
 {
  rectTemp.left = (*iter).m_NowPos.x * m_SpaceW +rect.left-3; 
  rectTemp.top  = (*iter).m_NowPos.y * m_SpaceH +rect.top-3; 
  rectTemp.right= rectTemp.left + m_SpaceW+3 ;                
  rectTemp.bottom=rectTemp.top  + m_SpaceH+3 ;  
  drawRect(rectTemp,_RGB32BIT(0,0,255 , 0));

  //显示人标号(ID)
 // sprintf(buffer,"%d", (*iter).ID ); 
 // Draw_Text_GDI( lpddsback,buffer , rectTemp.left , rectTemp.top ,RGB(255,0,0));

  //画边框
 // if((*iter).ID ==m_Control->m_SelectID)
 // {
 //  drawBoardLine( (*iter).m_NowPos.x*m_SpaceW +rect.left,(*iter).m_NowPos.y*m_SpaceH +rect.top ,
 //               m_SpaceW,m_SpaceH,3,PS_SOLID,RGB (255,100,255));
 // }
 }
}

 //画出目的地
void CDraw::drawAim()
{
 RECT rectTemp;
 vector<CActor>::iterator iter =m_Search->m_ActorCon.begin();
 for( ;iter!=m_Search->m_ActorCon.end();iter++)
 {
  if((*iter).m_TargetPos==(*iter).m_NowPos) //防止目的地与所在地重合
   continue;
  rectTemp.left = (*iter).m_TargetPos.x * m_SpaceW +rect.left -3;   
  rectTemp.top  = (*iter).m_TargetPos.y * m_SpaceH +rect.top -3; 
  rectTemp.right= rectTemp.left + m_SpaceW +3 ;                
  rectTemp.bottom=rectTemp.top  + m_SpaceH +3;  
  drawRect(rectTemp,_RGB32BIT(0,255,220,0 ));

  //显示人标号(ID)
  /*sprintf(buffer,"%d", (*iter).ID ); 
  Draw_Text_GDI( lpddsback,buffer , rectTemp.left , rectTemp.top ,RGB(255,0,0));
  */
 }
}
 //画边线框
void CDraw::drawBoardLine(int x,int y ,int w,int h, int penWidth,int penStyle,COLORREF color)
{  
 Draw_Line( lpddsback, x   ,y   ,x+w  ,y   ,penWidth ,penStyle ,color );
 Draw_Line( lpddsback, x+w ,y   ,x+w  ,y+h ,penWidth ,penStyle ,color );
 Draw_Line( lpddsback, x   ,y+h ,x+w  ,y+h ,penWidth ,penStyle ,color );
 Draw_Line( lpddsback, x   ,y   ,x    ,y+h ,penWidth ,penStyle , color ); //RGB (255,128,0)
}

 //绘制矩形
void CDraw::drawRect(int x,int y ,int w,int h,COLORREF color )
{
 RECT rectTemp;
 rectTemp.left=x;
 rectTemp.right=y;
 rectTemp.bottom=x+w;
 rectTemp.top=y+h;

 DDRAW_INIT_STRUCT(ddbltfx);
 ddbltfx.dwFillColor = color;
 if (FAILED(lpddsback->Blt(&rectTemp, NULL,  NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
  {  return ;} 
}

 //绘制矩形
void CDraw::drawRect( RECT rectTemp,COLORREF color )
{
 DDRAW_INIT_STRUCT(ddbltfx);
 ddbltfx.dwFillColor = color; 
 if (FAILED(lpddsback->Blt(&rectTemp, NULL,  NULL, DDBLT_COLORFILL | DDBLT_WAIT, &ddbltfx)))
  {  return ;} 
}

//显示背景
void CDraw::displayBackGround(BITMAP_FILE& map)
{
 lpddsback->Lock(NULL,&ddsd, DDLOCK_SURFACEMEMORYPTR | DDLOCK_WAIT,NULL);
 DWORD *primary_buffer = (DWORD *)ddsd.lpSurface;      

 for (int index_y = 0; index_y < SCREEN_HEIGHT; index_y++)
 {
  for (int index_x = 0; index_x < SCREEN_WIDTH; index_x++)
  {
   UCHAR blue  = (map.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 0]),
      green = (map.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 1]),
      red   = (map.buffer[index_y*SCREEN_WIDTH*3 + index_x*3 + 2]);
   DWORD pixel = _RGB32BIT(0,red,green,blue);
    primary_buffer[index_x + (index_y*ddsd.lPitch >> 2)] = pixel;
   }
  }
 if (FAILED(lpddsback->Unlock(NULL)))
 { return ;}
}

void CDraw::createMapByBitMap(set<Pos>& blockCon)
{
 
 int iWidth = m_Search->m_Map.width();
 int iHeight= m_Search->m_Map.height();
 Pos pos;
 for (int index_y = 0; index_y < iHeight; index_y++)
 {
  for (int index_x = 0; index_x < iWidth; index_x++)
  {
   UCHAR blue  = (bitmap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 0]),
      green = (bitmap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 1]),
      red   = (bitmap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 2]);
   
   pos.x = index_x;
   pos.y = index_y;
   //无障碍
   if ( blue >= CParam::BStepBegin && blue <= CParam::BStepEnd
    && green >= CParam::GStepBegin && green<= CParam::GStepEnd
    && red   >= CParam::RStepBegin && red  <= CParam::RStepEnd)
   {
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 0] = 255;
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 1] = 255;
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 2] = 255;
    m_Search->m_Map.setAccess( pos );
   
   }
   //有障碍
   else
   {
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 0] = 0;
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 1] = 0;
    themap.buffer[(index_y+50)*SCREEN_WIDTH*3 + (index_x+50)*3 + 2] = 0;
    m_Search->m_Map.setBlock (pos);
    //blockCon.insert(pos);    //保存障碍物坐标
   }
  }
 }//end of for

 
}

CMap.cpp

__________________________________________________

#include "stdafx.h"
#include "CParam.h"
#include "CMap.h"
//析构函数
CMap::~CMap()
{
 if(m_Map)
 {
  for(int i=0;i<m_Height;i++)
   delete[] m_Map[i];  //释放空间
  delete[] m_Map;
 } 
}

//载入地图(初始化障碍物容器,搜索者坐标容器) 
void CMap::loadMap(set<Pos>& blockCon,vector<Pos>& actorPos)
{
 ifstream file(CParam::loadMapName.c_str()); 
 actorPos.clear();
 blockCon.clear();
 if(!file)
  exit(1);

 char tmp[50];
 file>>m_Width>>m_Height; //读入地图宽,高
 file>>tmp>>m_Block;      //读入障碍物字符
 file>>tmp>>m_Access;     //读入通路字符
 file>>tmp>>m_Actor;      //读入搜索者字符 
 
 //建立地图 
 m_Map = new char* [m_Height];
 Pos pos;
 for(int i=0;i<m_Height;i++)
 {
  m_Map[i] = new char[m_Width+1];  
  
  /*file>>m_Map[i];  
  for(int j=0;j<m_Width;j++)
  {
   pos.x = j;
   pos.y = i;
   if(isBlock(pos))
    blockCon.insert(pos);    //保存障碍物坐标
    
   if(isActor(pos))
    actorPos.push_back(pos); //保存搜索者坐标
  }*/
 }
}

//保存地图
void CMap::saveMap()
{
 //ofstream debug("debug.txt");
 //debug<<CParam::loadMapName<<endl;
 //debug<<CParam::saveMapName<<endl;
 //debug<<CParam::oneBiasCost;

 //ofstream file(CParam::saveMapName);  //??
 ofstream file("savemap.map");

 if(!file)
  exit(1); 

 file<<m_Width<<" "<<m_Height<<endl; //导出地图宽,高
 file<<"Block: "<<m_Block<<endl;
 file<<"Block: "<<m_Access<<endl;
 file<<"Block: "<<m_Actor<<endl<<endl;

 //导出地图
 for(int i=0;i<m_Height;i++)
 {
  file<<m_Map[i]<<endl;
 }  
}

CParam.cpp

______________________________________________

#include "CParam.h"

string CParam::loadMapName; //载入地图的文件名
string CParam::saveMapName; //保存地图的文件名

int CParam::oneBiasCost = 0;  
int CParam::oneNoBiasCost = 0;
int CParam::waitTime = 0;  
int CParam::permitDisdance = 0;   
int CParam::tryRoundBlock = 0;
int CParam::tryStartTimes = 0;
int CParam::startConSize = 0;
int CParam::startProHCost = 0;

int CParam::RStepBegin = 0;
int CParam::GStepBegin = 0;
int CParam::BStepBegin = 0;

int CParam::RStepEnd = 0;
int CParam::GStepEnd = 0;
int CParam::BStepEnd = 0;

int CParam::displayHight =0;
int CParam::displayWidth =0;
int CParam::displayX     =0;
int CParam::displayY     =0;
bool CParam::bDisOppo    = false;
char* paramFileName      = "param.ini"; //配置文件名

//构造函数
CParam::CParam()
{
    ifstream file(paramFileName);
 if(!file)
  exit(1);

 //ofstream debug("debug.txt"); 

 char tmp[30];
 file>>tmp>>loadMapName; 
 file>>tmp>>saveMapName; 
 
 //debug<<CParam::saveMapName.c_str();

 file>>tmp>>oneBiasCost;
 file>>tmp>>oneNoBiasCost;
 file>>tmp>>waitTime;
 file>>tmp>>permitDisdance;
 file>>tmp>>tryRoundBlock;
 file>>tmp>>tryStartTimes;
 file>>tmp>>startConSize;
 file>>tmp>>startProHCost;

 //读入RGB的阀值
 file>>tmp>>RStepBegin;
 file>>tmp>>GStepBegin;
 file>>tmp>>BStepBegin;

 file>>tmp>>RStepEnd;
 file>>tmp>>GStepEnd;
 file>>tmp>>BStepEnd;

 file>>tmp>> displayX    ; //读入屏幕上显示的地图起点X
 file>>tmp>> displayY     ; //读入屏幕上显示的地图起点Y
 file>>tmp>> displayWidth  ; //读入屏幕显示的地图宽度
 file>>tmp>> displayHight ; //读入屏幕显示的地图高度
}


CSearch.cpp

__________________________________________________________

#include "CSearch.h"

//构造函数
CSearch::CSearch()
{
 vector<Pos> actorPos;
 m_Map.loadMap(m_BlockCon,actorPos); //载入地图

 //初始化搜索者
 for(int i=0;i<actorPos.size();i++)
 {
  addActor(actorPos[i]);
  setTargetPos(m_ActorCon.begin()+i,Pos(80,80));
 }  
}

//添加搜索者
void CSearch::addActor(const Pos& startPos)
{
 int ID;
 if (m_ActorCon.empty()) 
  ID = 0; 
 else 
  ID = m_ActorCon.back().ID + 1; 
 
 m_ActorCon.push_back(CActor(ID,startPos,&m_Map));
 m_Map.setActor(startPos); 
}

//删除搜索者
void CSearch::delActor(const VI actor)
{
 m_Map.setAccess(actor->m_NowPos);
 m_ActorCon.erase(actor);
}

//设置搜索者目标点
bool CSearch::setTargetPos(const VI actor,const Pos& targetPos)

 if(m_Map.isAccess(targetPos)==false)
  return false;
 
 actor->setTarget(targetPos);
 actor->m_IsSearch = true;
 return true;  
}


//修改地图
void CSearch::changeMap(const Pos& pos)

 if(m_Map.isAccess(pos)==true)
 {
  m_Map.setBlock(pos);    //把通路改为障碍物
  m_BlockCon.insert(pos); //插入障碍物容器
  return;
 }
     
 if(m_Map.isBlock(pos)==true)
 {  
  m_Map.setAccess(pos);  //把障碍物改为通路      
  m_BlockCon.erase(pos); //从障碍物容器中删除  
  return;
 }
}

//执行一次搜索方法
bool CSearch::runOneTimes()
{
 VI iter;
 bool bRet = false;
 for (iter = m_ActorCon.begin(); iter != m_ActorCon.end(); ++iter)
 {
  if(iter->m_IsSearch==true)
  {
   bRet = true;
   iter->run();   
  }
 }
 //Sleep(10);
 return bRet;
}

//定位搜索者并返回搜索者的迭代器
bool CSearch::locateActor(const Pos& pos,VI& selectIter)
{
  VI iter;
  for (iter = m_ActorCon.begin(); iter != m_ActorCon.end();++iter)
  {
   if (abs(iter->m_NowPos.x-pos.x) < 5 && abs(iter->m_NowPos.y-pos.y) < 5)
   
   {
    selectIter = iter;
    return true;
   }
  } 
  return false; //未定位到
}

DirectFunction.cpp

_____________________________________________

#include "DirectFunction.h"

//显示文字
int Draw_Text_GDI( LPDIRECTDRAWSURFACE7& lpdds,char *text, int x,int y, COLORREF color)

 HDC hdc;
  if (FAILED(lpdds->GetDC(&hdc) ) )
 {  return 0;  }

 SetTextColor(hdc,color);
 SetBkMode(hdc, TRANSPARENT);
 TextOut(hdc,x,y,text,strlen(text));

 if(lpdds)                        //释放dc
 { lpdds->ReleaseDC(hdc);   }
 return(1);
}

//画直线
void Draw_Line ( LPDIRECTDRAWSURFACE7& lpdds,int Ax,int Ay, int Bx,int By, int penWidth ,int penStyle ,COLORREF color )
{
 HDC hdc;
  if (FAILED(lpdds->GetDC(&hdc) ) )
 {  return  ;  }
   
 HPEN hpen=CreatePen( penStyle,penWidth,color );
 SelectObject(hdc,  hpen);
   
 MoveToEx(hdc,Ax,Ay,NULL);
 LineTo(hdc,Bx,By);

 DeleteObject( hpen);

 if(lpdds)                        //释放dc
 { lpdds->ReleaseDC(hdc);   }
}
/*
//载入图像
bool Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
  int    file_handle;          // 文件句柄 
 UCHAR   *temp_buffer = NULL; 
 OFSTRUCT file_data;           //文件数据信息
 
 //一下一段代码读取文件信息
 if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
 {   return(0);}
 _lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
 if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
 {
  _lclose(file_handle);
  return(0);
   }

 //一下一段代码读取位图信息
 // 载入文件位图文件头
 _lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
 // 位图数据
 _lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);
 
 if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 ||
    bitmap->bitmapinfoheader.biBitCount==24)
   {
    if (bitmap->buffer)
  {   delete [](bitmap->buffer);}
    if (!(bitmap->buffer = (UCHAR *)new UCHAR[bitmap->bitmapinfoheader.biSizeImage] ))
    { 
     _lclose(file_handle);
     return(0);
    }
    _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);
   }
 else
 {   return(0);   }
 
 _lclose(file_handle);
 
 Flip_Bitmap(bitmap->buffer,
   bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),
            bitmap->bitmapinfoheader.biHeight);
 
 return(1);
}

//卸载图像
bool Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
 if (bitmap->buffer)
   {
    delete[]bitmap->buffer;
    bitmap->buffer = NULL;
   }
   return(1);

}

//获取位图信息
bool Flip_Bitmap(UCHAR *image, int bytes_per_line, int height)
{
 UCHAR *buffer;
 int index;     // looping index
 
 if (!(buffer = (UCHAR *)new UCHAR[bytes_per_line*height] ) )
 {  return(0);}

 // 拷贝位图到工作区
 memcpy(buffer,image,bytes_per_line*height);
 for (index=0; index < height; index++)
 {
  memcpy(&image[((height-1) - index)*bytes_per_line],
           &buffer[index*bytes_per_line], bytes_per_line);
 }
 delete []buffer;
 return (1);
}

*/


bool Load_Bitmap_File(BITMAP_FILE_PTR bitmap, char *filename)
{
int file_handle,  // 文件句柄 
    index;           //文件数据信息

UCHAR   *temp_buffer = NULL; // used to convert 24 bit images to 16 bit
OFSTRUCT file_data;          // the file data information
if ((file_handle = OpenFile(filename,&file_data,OF_READ))==-1)
   return(0);
_lread(file_handle, &bitmap->bitmapfileheader,sizeof(BITMAPFILEHEADER));
if (bitmap->bitmapfileheader.bfType!=BITMAP_ID)
   {
    _lclose(file_handle);
    return(0);
   }

 //下一段代码读取位图信息
// 载入文件位图文件头
_lread(file_handle, &bitmap->bitmapinfoheader,sizeof(BITMAPINFOHEADER));
if (bitmap->bitmapinfoheader.biBitCount == 8)
{
 _lread(file_handle, &bitmap->palette,256*sizeof(PALETTEENTRY) );
   for (index=0; index <256; index++)
   {
    int temp_color                = bitmap->palette[index].peRed;
       bitmap->palette[index].peRed  = bitmap->palette[index].peBlue;
       bitmap->palette[index].peBlue = temp_color;   
       bitmap->palette[index].peFlags = PC_NOCOLLAPSE;
       }
    }
_lseek(file_handle,-(int)(bitmap->bitmapinfoheader.biSizeImage),SEEK_END);


if (bitmap->bitmapinfoheader.biBitCount==8 || bitmap->bitmapinfoheader.biBitCount==16 ||
    bitmap->bitmapinfoheader.biBitCount==24)
   {
 
 // if (bitmap->buffer)
 //{   delete [](bitmap->buffer);}

   if (!(bitmap->buffer = new UCHAR[bitmap->bitmapinfoheader.biSizeImage] ))
      {
    _lclose(file_handle);
    return(0);
   }

   _lread(file_handle,bitmap->buffer,bitmap->bitmapinfoheader.biSizeImage);

   }
else
   {   return(0);   }

_lclose(file_handle);

 Flip_Bitmap(bitmap->buffer,
    bitmap->bitmapinfoheader.biWidth*(bitmap->bitmapinfoheader.biBitCount/8),
    bitmap->bitmapinfoheader.biHeight);

return(1);

}

//卸载图像///

bool Unload_Bitmap_File(BITMAP_FILE_PTR bitmap)
{
 if (bitmap->buffer)
   {
    delete [](bitmap->buffer);
    bitmap->buffer = NULL;
   }
   return(1);
}


//获取位图信息///

bool Flip_Bitmap( UCHAR *image, int bytes_per_line, int height)
{
 UCHAR *buffer;
 int index;    

 buffer =  new UCHAR[bytes_per_line*height] ; 
 memcpy(buffer,image,bytes_per_line*height);

 for (index=0; index < height; index++)
 { 
  memcpy(&image[((height-1) - index)*bytes_per_line],&buffer[index*bytes_per_line], bytes_per_line);
 }
 delete []buffer;
 return(1);
}


main.cpp

_________________________________________________

#pragma once
#include "CParam.h"
#include "CDraw.h"
#include "CControl.h"
#include "CSearch.h"
#include "resource.h"
bool bDisplay = true;

CParam param;

CSearch* pSearch = new CSearch();
CControl control(pSearch);

LRESULT CALLBACK WindowProc(HWND hwnd,  UINT msg,   WPARAM wparam,    LPARAM lparam)
{
PAINTSTRUCT  ps;  
HDC    hdc; 
char buffer[80];  

control.readMeasage ( hwnd,  msg,  wparam,  lparam);
switch(msg)
 { 
 case WM_CREATE:
        {
   return(0);
  } break;  
 case WM_PAINT:
  {
   hdc = BeginPaint(hwnd,&ps); 
   EndPaint(hwnd,&ps);
   return(0);
  } break;

 case WM_DESTROY:
  { 
   bDisplay = false;
   delete pSearch; //释放内存
   PostQuitMessage(0);
   return(0);
  } break;
 default:break;
    }

return (DefWindowProc(hwnd, msg, wparam, lparam));

}
// 主函数

int WINAPI WinMain( HINSTANCE hinstance,
     HINSTANCE hprevinstance,
     LPSTR lpcmdline,
     int ncmdshow)
{

WNDCLASSEX winclass; // this will hold the class we create
MSG     msg;   // generic message
HWND       hwnd;
winclass.cbSize         = sizeof(WNDCLASSEX);
winclass.style   = CS_DBLCLKS | CS_OWNDC |  CS_HREDRAW | CS_VREDRAW;
winclass.lpfnWndProc = WindowProc;
winclass.cbClsExtra  = 0;
winclass.cbWndExtra  = 0;
winclass.hInstance  = hinstance;
winclass.hIcon   = LoadCursor(hinstance, "CICON" );
winclass.hCursor  = LoadCursor(NULL, IDC_ARROW);
winclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
winclass.lpszMenuName = NULL;
winclass.lpszClassName = WINDOW_CLASS_NAME;
winclass.hIconSm        = LoadIcon(NULL, IDI_APPLICATION);

hinstance_app = hinstance;                //保存全局实例

if (!RegisterClassEx(&winclass))
 return(0);

if (!(hwnd = CreateWindowEx(NULL,               
                            WINDOW_CLASS_NAME,
          "瓜西西A*",
       // WS_POPUP | WS_VISIBLE,        
       WS_OVERLAPPED |WS_VISIBLE|  WS_SYSMENU ,
           0,0, 
          SCREEN_WIDTH,SCREEN_HEIGHT,        
          NULL, 
          NULL, 
          hinstance,
          NULL))) 
return(0);


main_windows_hwnd = hwnd ;
CDraw draw(hwnd, pSearch,&control);
control.setDrawArea(draw.getDrawArea() );


  while(TRUE)
  { 
   if (PeekMessage(&msg,NULL,0,0,PM_NOREMOVE))
   {  
     if(!GetMessage(&msg, NULL, 0, 0 )) return int(msg.wParam);
    TranslateMessage(&msg);
    DispatchMessage(&msg);
   }
   if(control.m_IsSearch ==true)
   { 
   if(!pSearch->runOneTimes())
   {
    Sleep(100);
   }
   }
  
 if (bDisplay == true)
 {
  draw.display(); 
 }
  }
  return(msg.wParam);
 
}

param.ini

______________________________________________

loadMapName: loadmap.map
saveMapName: savemap.map

oneBiasCost: 7
oneNoBiasCost: 5
waitTime: 5
permitDisdance: 150
tryRoundBlock: 5
tryStartTimes: 3
startConSize: 1000
startProHCost: 250

RStepBegin: 150
GStepBegin: 80
BStepBegin: 20

RStepBegin: 230
GStepBegin: 230
BStepBegin: 230

displayX: 50
displayY: 50
displayWidth: 500
displayHight: 500

loadmap.map

______________________________________________

500 500
Block: 0
Block: 1
Block: 2

2222222222222222222222222222222222222222111111111122222222222222222222222222222222222222221111111111
2222222222222222222222222222211111111111111111111122222222222222222222222222222222222222222111111111
2222200002211110000011111110000011111100000000111122222000022111100000111111100000111111000000001111
2220001100211100111001111100222001111001111110011122200011002111001110011111002220011110011111100111
2220111110011101111100111002222200110011111111011122201111100111011111001110022222001100111111110111
2220111111000111111110010022222220010111111111111122201111110001111111100100222222200101111111111111
2220111110010100101011000222222222010110000011111122201111100101001010110002222222220101100000111111
2222222200110101101011111222222222010100122001111122222222001101011010111112222222220101001220011111
2222222001110100100000111222222122010101222200111122222220011101001000001112222221220101012222001111
1111110011110110111111000222222211010112122220011111111100111101101111110002222222110101121222200111
1111100111110100111111010222222222010112222222011111111001111101001111110102222222220101122222220111
1111001111010011111110010022222220010011222220011111110011110100111111100100222222200100112222200111
1110011111011001111100111002222200111001222100111111100111110110011111001110022222001110012221001111
1110111111011100111001111100222001111100111001111111101111110111001110011111002220011111001110011111
1110000000011110000011111110000011111110000011111111100000000111100000111111100000111111100000111111
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
2222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222222
0110000000000000000000000000000000000000000000111101100000000000000000000000000000000000000000000000
0111111111111110111111110111110111111111111110111101100000000000000000000000000000000000000000001111
0111111111111110111111110111110111111111111110111101100000000000000000000000000000000000000000001111
0110000000000110110110110110110000111000000110111101100000000000000000000000000000000000000000001111
0111111111110111110110111110111110111110110110111101100000000000000000000000000000000000000000001111
0111111111110111110110111110111110111110110110111101100000000000000000000000000000000000000000001111
0000000110000000000110000000001110000110110110111101100000000000000000000000000000000000000000001111
0111110110111110110110110111111111111110111110111101100000000000000000000000000000000000000000001111
0111110110111110110110110111111111111110111110111101100000000000000000000000000000000000000000001111
0110110110110110110110111110000000000000000110111101100000000000000000000000000000000000000000001111
0110110110110110110110111110110111110111110110111101100000000000000000000000000000000000000000001111
0110110110110110110110111110110111110111110110111101100000000000000000000000000000000000000000001111
0110110110110110110110110000110110110110110110111101100000000000000000000000000000000000000000001111
0110111110110110110110111111110110111110110110111101100000000000000000000000000000000000000000001111
0110111110110110110110111111110110111110110110111101100000000000000000000000000000000000000000001111
0110000000110110110110000000000110000000110110111100000000000000000000000000000000000000000000001111
0111111110110111110111111111111111110111110110111100100000000000000000000000000000000000000000001111
0111111110110111110111111111111111110111110110110001100000000000000000000000000000000000000000001111
0000000110110000000110000000000000110110000000000001100000000000000000000000000000000000000000001111
0111110110111111110110111110111110110111111110111101111101101111111101101111101111101101111111101111
0111110110111111110110111110111110110111111110111101111101101111111101101111101111101101111111101111
0110110000000001110110110000110110000000110110111101111101101111111101101111101111101101111111101111
0110111111111111110110110111110111111110110110111101111101101111111101101111101111101101111111101111
0110111111111111110110110111110111111110110110111101111101101111111101101111101111101101111111101111
0110000000000000000110110110000000000110000110111101111101101111111101101111101111101101111111101111
0110111111111111110111110110111111110111111110111101111101101111111101101111101111101101111111101111
0110111111111111110111110110111111110111111110111101111101101111111101101111101111101101111111101111
0110000110000000110000000110110000110000000110111101111101101111111101101111101111101101111111101111
0111111110111111111111111110111110111111111111111101111101101111111101101111101111101101111111101111
0111111110111111111111111110111110111111111111111101111101101111111101101111101111101101111111101111
0000000000000000000000000000000000000000000000111101111101101111111101101111101111101101111111101111
2222222222222222222222222222222222222222111111111101111101101111111101101111101111101101111111101111
2222222222222222222222222222222222222222211111111101111101101111111101101111101111101101111111101111
2222200002211110000011111110000011111100000000111101111101101111111101101111101111101101111111101111
2220001100211100111001111100222001111001111110011101111101101111111101101111101111101101111111101111
2220111110011101111100111002222200110011111111011101111101101111111101101111101111101101111111101111
2220111111000111111110010022222220010111111111111101111101101111111101101111101111101101111111101111
2220111110010100101011000222222222010110000011111101111101101111111101101111101111101101111111101111
2222222200110101101011111222222222010100122001111101111101101111111101101111101111101101111111111111
2222222001110100100000111222222122010101222200111101111101101111111111111111101111101111111111111111
1111110011110110111111000222222211010112122220011101111101101111111111111111111111111111111111111111
1111100111110100111111010222222222010112222222011101111101101111111111111111111111111111111111111111
1111001111010011111110010022222220010011222220011101111101101111111111111111111111111111111111111111
1110011111011001111100111002222200111001222100111101111101101111111111111111111111111111111111111111
1110111111011100111001111100222001111100111001111101111101101111111111111111111111111111111111111111
1110000000011110000011111110000011111110000011111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
0110000000000000000000000000000000000000000000111111111111111111111111111111111111111111111111111111
0111111111111110111111110111110111111111111110111111111111111111111111111111111111111111111111111111
0111111111111110111111110111110111111111111110111111111111111111111111111111111111111111111111111111
0110000000000110110110110110110000111000000110111111111111111111111111111111111111111111111111111111
0111111111110111110110111110111110111110110110111111111111111111111111111111111111111111111111111111
0111111111110111110110111110111110111110110110111111111111111111111111111111111111111111111111111111
0000000110000000000110000000001110000110110110111111111111111111111111111111111111111111111111111111
0111110110111110110110110111111111111110111110111111111111111111111111111111111111111111111111111111
0111110110111110110110110111111111111110111110111111111111111111111111111111111111111111111111111111
0110110110110110110110111110000000000000000110111111111111111111111111111111111111111111111111111111
0110110110110110110110111110110111110111110110111111111111111111111111111111111111111111111111111111
0110110110110110110110111110110111110111110110111111111111111111111111111111111111111111111111111111
0110110110110110110110110000110110110110110110111111111111111111111111111111111111111111111111111111
0110111110110110110110111111110110111110110110111111111111111111111111111111111111111111111111111111
0110111110110110110110111111110110111110110110111111111111111111111111111111111111111111111111111111
0110000000110110110110000000000110000000110110111111111111111111111111111111111111111111111111111111
0111111110110111110111111111111111110111110110111111111111111111111111111111111111111111111111111111
0111111110110111110111111111111111110111110110111111111111111111111111111111111111111111111111111111
0000000110110000000110000000000000110110000000001111111111111111111111111111111111111111111111111111
0111110110111111110110111110111110110111111110111111111111111111111111111111111111111111111111111111
0111110110111111110110111110111110110111111110111111111111111111111111111111111111111111111111111111
0110110000000001110110110000110110000000110110111111111111111111111111111111111111111111111111111111
0110111111111111110110110111110111111110110110111111111111111111111111111111111111111111111111111111
0110111111111111110110110111110111111110110110111111111111111111111111111111111111111111111111111111
0110000000000000000110110110000000000110000110111101111111101111111111111111111111111111111111111111
0110111111111111110111110110111111110111111110111101111111101111111111111111111111111111111111111111
0110111111111111110111110110111111110111111110111101111111101111111111111111111111111111111111111111
0110000110000000110000000110110000110000000110111101111111101111111111111111111111111111111111111111
0111111110111111111111111110111110111111111111111101111111101111111111111111111111111111111111111111
0111111110111111111111111110111110111111111111111101111111101111111111111111111111111111111111111111
0000000000000000000000000000000000000000000000111101111111101111111111111111111111111111111111111111


  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值