设计形式中迷宫的实现,用于学习创建型模式
设计模式中迷宫的实现,用于学习创建型模式
使用创建型模式,仅需要做少量更改:
设计模式一书相信不少人看过。其中创建型模式一节通过一个创建迷宫的例子阐述了工厂模式、抽象工厂模式等创建型模式。对于初学者而言,书中讲解并未实现具体代码,对于几种设计模式的优势不能深刻的体会。出于学习的目的我实现了这个迷宫,并且尽量保持原书中的类结构,用于体会创建型模式的优点。代码并不难,详见注释。本源码中仅实现了抽象工厂模式,其他模式详见设计模式一书。注意启动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; else std::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; }