设计模式中迷宫的实现,用于学习创建型模式

来源:互联网 发布:tgp网络出口不稳定 编辑:程序博客网 时间:2024/06/03 18:28

    设计模式一书相信不少人看过。其中创建型模式一节通过一个创建迷宫的例子阐述了工厂模式、抽象工厂模式等创建型模式。对于初学者而言,书中讲解并未实现具体代码,对于几种设计模式的优势不能深刻的体会。出于学习的目的我实现了这个迷宫,并且尽量保持原书中的类结构,用于体会创建型模式的优点。代码并不难,详见注释。本源码中仅实现了抽象工厂模式,其他模式详见设计模式一书。注意启动RTTI,下图为运行效果。


    以下源码为不使用创建型模式的实现。

#include <iostream>#include <Windows.h>#include <string.h>enum Direction{North,South,West,East};class Coor//在数组中的坐标{public:   Coor(int v=0,int h=0):vertical(v),horizontal(h){}   int vertical;   int horizontal;};class MapSite{public:virtual void Enter()=0;};class Wall:public MapSite{public:virtual void Enter(){   std::cout<<"this is a Wall!"<<std::endl;}};class Room:public MapSite{public:Room(Coor r){m_linenumber=r.horizontal;m_rownumber=r.vertical;}MapSite* GetSide(Direction d) const{    return m_sides[d];}void SetSide(Direction d,MapSite* m){    m_sides[d]=m;}virtual void Enter(){   std::cout<<"You entered the room "<<m_rownumber<<","<<m_linenumber<<std::endl;}private:MapSite* m_sides[4];int m_linenumber;int m_rownumber;};class Door:public MapSite{public:Door(Room* r1= 0,Room* r2= 0,bool b=true){   m_room1=r1;   m_room2=r2;   m_isOpen=b;}virtual void Enter(){if(m_isOpen==true)std::cout<<"you went through the door."<<std::endl;elsestd::cout<<"the door is closed."<<std::endl;}Room* OtherSideFrom(Room* r){  if(r==m_room1)  return m_room2;  else  return m_room1;}void setIsOpen(bool b){   m_isOpen=b;}bool getIsOpen(){   return m_isOpen;}private:Room* m_room1;Room* m_room2;bool m_isOpen;};class Person//迷宫中的人{public:Coor getPlace(){return m_place;}void setPlace(Coor place){  m_place=place;}private:Coor m_place;};class Maze//迷宫{public:Maze(int height=3,int width=3,Coor Place=Coor(0,0)){  m_height=height;  m_width=width;  m_rooms=new Room**[height];  memset(m_rooms,0,height*sizeof(Room**));  m_p.setPlace(Place);}void addRoom(Room* r,int h,int w){  if(w<0||w>=m_width||h<0||h>=m_height)          return ;  else  {  if (m_rooms[h]==NULL)  m_rooms[h]=new Room*[m_width];  m_rooms[h][w]=r;  }}Room* getRoom(int h,int w){   return m_rooms[h][w];}void pGoWest()//向左走{MapSite* m=m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]->GetSide(West);m->Enter();if(typeid(*m)==typeid(Room)){m_p.setPlace(Coor(m_p.getPlace().vertical,m_p.getPlace().horizontal-1));}else if(typeid(*m)==typeid(Door)){Door* r=dynamic_cast<Door*>(m);if(r->getIsOpen()==true){Room* ar=r->OtherSideFrom(m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]);    m_p.setPlace(Coor(m_p.getPlace().vertical,m_p.getPlace().horizontal-1));    ar->Enter();}}return ;}void pGoEast()//向右走{MapSite* m=m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]->GetSide(East);m->Enter(); if(typeid(*m)==typeid(Room)){m_p.setPlace(Coor(m_p.getPlace().vertical,m_p.getPlace().horizontal+1));}else if(typeid(*m)==typeid(Door)){Door* r=dynamic_cast<Door*>(m);if(r->getIsOpen()==true){   Room* ar=r->OtherSideFrom(m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]);    m_p.setPlace(Coor(m_p.getPlace().vertical,m_p.getPlace().horizontal+1));    ar->Enter();}}return ;}void pGoNorth()//向上走{MapSite* m=m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]->GetSide(North);m->Enter(); if(typeid(*m)==typeid(Room)){m_p.setPlace(Coor(m_p.getPlace().vertical+1,m_p.getPlace().horizontal));}else if(typeid(*m)==typeid(Door)){Door* r=dynamic_cast<Door*>(m);if(r->getIsOpen()==true){   Room* ar=r->OtherSideFrom(m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]);    m_p.setPlace(Coor(m_p.getPlace().vertical-1,m_p.getPlace().horizontal));    ar->Enter();}}return ;}void pGoSouth()//向下走{MapSite* m=m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]->GetSide(South);m->Enter(); if(typeid(*m)==typeid(Room)){m_p.setPlace(Coor(m_p.getPlace().vertical+1,m_p.getPlace().horizontal));}else if(typeid(*m)==typeid(Door)){Door* r=dynamic_cast<Door*>(m);if(r->getIsOpen()==true){   Room* ar=r->OtherSideFrom(m_rooms[m_p.getPlace().vertical][m_p.getPlace().horizontal]);    m_p.setPlace(Coor(m_p.getPlace().vertical+1,m_p.getPlace().horizontal));    ar->Enter();}}return ;}void PrintMaze()//打印当前迷宫状态{   HANDLE hconsole;       hconsole=GetStdHandle(STD_OUTPUT_HANDLE);       SetConsoleTextAttribute(hconsole,MAKEWORD(7,0));   for(int i=0;i<m_height;i++)   {   for(int j=0;j<m_width;j++)   {   if(m_p.getPlace().vertical==i&&m_p.getPlace().horizontal==j)   {      SetConsoleTextAttribute(hconsole,MAKEWORD(4,0));  printf("%c ",'P');  continue;   }   if(m_rooms[i][j]==NULL)   {      SetConsoleTextAttribute(hconsole,MAKEWORD(7,0));   }   else      SetConsoleTextAttribute(hconsole,MAKEWORD(3,0));   printf("%d ",j);   }   printf("\n");   }}private:int m_height;int m_width;Room*** m_rooms;//二位数组,每个元素是一个指向Room的指针。Person m_p;};class MazeGame{public:void CreateMaze();void startGame();private:Maze *m_maze;};void MazeGame::startGame(){m_maze->PrintMaze();char c;while(std::cin.get(c)){    if(c=='w'){m_maze->pGoNorth();m_maze->PrintMaze();}if(c=='s'){m_maze->pGoSouth();m_maze->PrintMaze();}if(c=='a'){m_maze->pGoWest();m_maze->PrintMaze();}if(c=='d'){m_maze->pGoEast();m_maze->PrintMaze();}}}void MazeGame::CreateMaze(){Maze* aMaze=new Maze(2,5);Room* r1=new Room(Coor(0,0));Room* r2=new Room(Coor(0,1));Room* r3=new Room(Coor(0,2));Room* r4=new Room(Coor(0,3));Room* r5=new Room(Coor(0,4));Room* r6=new Room(Coor(1,0));Room* r7=new Room(Coor(1,1));Room* r8=new Room(Coor(1,2));Room* r9=new Room(Coor(1,3));Room* r10=new Room(Coor(1,4));Door* door1=new Door(r1,r2);Door* door2=new Door(r2,r3);Door* door3=new Door(r3,r4,false);Door* door4=new Door(r4,r5);Door* door10=new Door(r6,r7);Door* door11=new Door(r7,r8);Door* door12=new Door(r8,r9);Door* door13=new Door(r9,r10,false);Door* door5=new Door(r1,r6,false);Door* door6=new Door(r2,r7);Door* door7=new Door(r3,r8,false);Door* door8=new Door(r4,r9);Door* door9=new Door(r5,r10);aMaze->addRoom(r1,0,0);aMaze->addRoom(r2,0,1);aMaze->addRoom(r3,0,2);aMaze->addRoom(r4,0,3);aMaze->addRoom(r5,0,4);aMaze->addRoom(r6,1,0);aMaze->addRoom(r7,1,1);aMaze->addRoom(r8,1,2);    aMaze->addRoom(r9,1,3);aMaze->addRoom(r10,1,4);r1->SetSide(North,new Wall);r1->SetSide(South,door5);r1->SetSide(West,new Wall);r1->SetSide(East,door1);r2->SetSide(North,new Wall);r2->SetSide(South,door6);r2->SetSide(West,door1);r2->SetSide(East,door2);r3->SetSide(North,new Wall);r3->SetSide(South,door7);r3->SetSide(West,door2);r3->SetSide(East,door3);r4->SetSide(North,new Wall);r4->SetSide(South,door8);r4->SetSide(West,door3);r4->SetSide(East,door4);r5->SetSide(North,new Wall);r5->SetSide(South,door9);r5->SetSide(West,door4);r5->SetSide(East,new Wall);r6->SetSide(North,door5);r6->SetSide(South,new Wall);r6->SetSide(West,new Wall);r6->SetSide(East,door10);r7->SetSide(North,door6);r7->SetSide(South,new Wall);r7->SetSide(West,door10);r7->SetSide(East,door11);r8->SetSide(North,door7);r8->SetSide(South,new Wall);r8->SetSide(West,door11);r8->SetSide(East,door12);r9->SetSide(North,door8);r9->SetSide(South,new Wall);r9->SetSide(West,door12);r9->SetSide(East,door13);r10->SetSide(North,door9);r10->SetSide(South,new Wall);r10->SetSide(West,door13);r10->SetSide(East,new Wall);    m_maze=aMaze;}int main(){  std::cout<<"按wsad进行操作,ctrl+z退出。\n";  MazeGame ng;  ng.CreateMaze();  ng.startGame();  return 0;}

使用创建型模式,仅需要做少量更改:

class MazeFactory{public:MazeFactory(){};   virtual Maze* MakeMaze(int height,int width,Coor coor) const   {     return new Maze(height,width,coor);   }   virtual Wall* MakeWall() const   {     return new Wall;   }   virtual Room* MakeRoom(Coor coor) const   {     return new Room(coor);   }   virtual Door* MakeDoor(Room* r1,Room* r2,bool b) const   {     return new Door(r1,r2,b);   }};

void MazeGame::CreateMaze(MazeFactory& factory){Maze* aMaze=factory.MakeMaze(2,5,Coor(0,0));Room* r1=factory.MakeRoom(Coor(0,0));Room* r2=factory.MakeRoom(Coor(0,1));Room* r3=factory.MakeRoom(Coor(0,2));Room* r4=factory.MakeRoom(Coor(0,3));Room* r5=factory.MakeRoom(Coor(0,4));Room* r6=factory.MakeRoom(Coor(1,0));Room* r7=factory.MakeRoom(Coor(1,1));Room* r8=factory.MakeRoom(Coor(1,2));Room* r9=factory.MakeRoom(Coor(1,3));Room* r10=factory.MakeRoom(Coor(1,4));Door* door1=factory.MakeDoor(r1,r2,true);Door* door2=factory.MakeDoor(r2,r3,true);Door* door3=factory.MakeDoor(r3,r4,false);Door* door4=factory.MakeDoor(r4,r5,true);Door* door10=factory.MakeDoor(r6,r7,true);Door* door11=factory.MakeDoor(r7,r8,true);Door* door12=factory.MakeDoor(r8,r9,true);Door* door13=factory.MakeDoor(r9,r10,false);Door* door5=factory.MakeDoor(r1,r6,false);Door* door6=factory.MakeDoor(r2,r7,true);Door* door7=factory.MakeDoor(r3,r8,false);Door* door8=factory.MakeDoor(r4,r9,true);Door* door9=factory.MakeDoor(r5,r10,true);aMaze->addRoom(r1,0,0);aMaze->addRoom(r2,0,1);aMaze->addRoom(r3,0,2);aMaze->addRoom(r4,0,3);aMaze->addRoom(r5,0,4);aMaze->addRoom(r6,1,0);aMaze->addRoom(r7,1,1);aMaze->addRoom(r8,1,2);        aMaze->addRoom(r9,1,3);aMaze->addRoom(r10,1,4);r1->SetSide(North,factory.MakeWall());r1->SetSide(South,door5);r1->SetSide(West,factory.MakeWall());r1->SetSide(East,door1);r2->SetSide(North,factory.MakeWall());r2->SetSide(South,door6);r2->SetSide(West,door1);r2->SetSide(East,door2);r3->SetSide(North,factory.MakeWall());r3->SetSide(South,door7);r3->SetSide(West,door2);r3->SetSide(East,door3);r4->SetSide(North,factory.MakeWall());r4->SetSide(South,door8);r4->SetSide(West,door3);r4->SetSide(East,door4);r5->SetSide(North,factory.MakeWall());r5->SetSide(South,door9);r5->SetSide(West,door4);r5->SetSide(East,factory.MakeWall());r6->SetSide(North,door5);r6->SetSide(South,factory.MakeWall());r6->SetSide(West,factory.MakeWall());r6->SetSide(East,door10);r7->SetSide(North,door6);r7->SetSide(South,factory.MakeWall());r7->SetSide(West,door10);r7->SetSide(East,door11);r8->SetSide(North,door7);r8->SetSide(South,factory.MakeWall());r8->SetSide(West,door11);r8->SetSide(East,door12);r9->SetSide(North,door8);r9->SetSide(South,factory.MakeWall());r9->SetSide(West,door12);r9->SetSide(East,door13);r10->SetSide(North,door9);r10->SetSide(South,factory.MakeWall());r10->SetSide(West,door13);r10->SetSide(East,factory.MakeWall());    m_maze=aMaze;}


原创粉丝点击