Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- #include <conio.h>
- #include <windows.h>
- #define a first
- #define b second
- #define mp make_pair
- #define mp4(i , j , k , l) mp(mp(i , j) , mp(k , l))
- /// cksh.h
- void SetColor(int f,int b)
- { SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),b*16+f); }
- void gotoxy(int xpos, int ypos)
- {
- COORD scrn;
- HANDLE hOuput = GetStdHandle(STD_OUTPUT_HANDLE);
- scrn.X = ypos,scrn.Y = xpos;
- SetConsoleCursorPosition(hOuput,scrn);
- }
- void show()
- {
- HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO cci;
- cci.bVisible = TRUE,cci.dwSize = 25;
- SetConsoleCursorInfo(hcon, &cci);
- }
- void hide()
- {
- HANDLE hcon = GetStdHandle(STD_OUTPUT_HANDLE);
- CONSOLE_CURSOR_INFO cci;
- cci.bVisible = FALSE,cci.dwSize = 25;
- SetConsoleCursorInfo(hcon, &cci);
- }
- void clrscr() { system("CLS"); }
- int getkey()
- {
- int ch=getch();
- if(ch==224)
- {
- ch=getch();
- if(ch==72)return 0; //up
- if(ch==75)return 1; //left
- if(ch==77)return 2; //right
- if(ch==80)return 3; //down
- }
- return -1;
- }
- /// PIC_MAKER
- using namespace std;
- typedef pair<int,int> PII;
- const char U = ' ' , V = '#';
- const int HMAX = 10000 , WMAX = 5000;
- const int BCOL = 15; ///地板顏色
- const int WCOL = 4; ///牆壁顏色
- const int SCOL = 10; ///自己顏色
- const int MCOL = 2; ///moving wall顏色
- const int TOP = 1; ///地圖從第幾行開始印
- const int BLANK = 2; ///間距
- int BLOOD = 50; ///初始血量
- const int BAG = 5; ///血包數量(<=6)
- const int SDLAY = 10; ///動畫速度
- const int INF = 10000000 , m[4][2]={{-1,0},{0,-1},{0,1},{1,0}}; ///上 左 右 下
- int H = 23,W = 39;
- int pit_base = 1 , pit_range = 1; ///最少幾個洞,範圍
- int pc_speed = 80; ///電腦移速,越大越快
- char p[HMAX][WMAX];
- int step[HMAX][WMAX];
- int from[HMAX][WMAX];
- deque<int> way;
- deque<PII> Q;
- int minstep_solve , minstep_blood;
- const int BLCOL = 9;
- map<PII , int> blood_bag;
- class DJset
- {
- public:
- int par[100000];
- int rank[100000];
- void djinit(int n)
- {
- for(int i=0;i<n;i++)
- {
- par[i]=i;
- rank[i]=0;
- }
- }
- int djfind(int x)
- {
- if(par[x]==x)return x;
- return par[x]=djfind(par[x]);
- }
- void unite(int x,int y)
- {
- x=djfind(x);
- y=djfind(y);
- if(x==y)return;
- if(rank[x]<rank[y])par[x]=y;
- else
- {
- par[y]=x;
- if(rank[x]==rank[y])rank[x]++;
- }
- }
- bool same(int x,int y)
- {
- return djfind(x)==djfind(y);
- }
- };
- class N{
- public:
- int x , y , blood , dis , bag;
- N (int x_ , int y_ , int blood_ , int dis_ , int bag_){
- x = x_ , y = y_ , blood = blood_ , dis = dis_ , bag = bag_;
- }
- };
- int goodsolverByblood(map<PII , int> blood , int initblood){
- way.clear();
- assert(blood.size() <= 6); // too much
- const int lim = max(H , W) + 1 , bloodlim = 130;
- PII dis[bloodlim][H + 1][W + 1];
- PII pa[bloodlim][H + 1][W + 1];
- memset(dis , 0x3f3f3f3f , sizeof dis);
- int val[20] , j = 0;
- for(map<PII , int>::iterator i = blood.begin() ; i != blood.end() ; i ++ , j ++)
- val[j] = i->b , blood[i->a] = j;
- queue<N> qu;
- // int x , y , blood , dis , bag;
- qu.push(N(1 , 0 , initblood , 0 , 0));
- while(qu.size()){
- N now = qu.front(); qu.pop();
- if(now.blood == 0) continue;
- else {
- if(now.x == H - 2 && now.y == W - 1) break;
- for(int i = 0 ; i < 4 ; i ++){
- int qx = now.x + m[i][0] , qy = now.y + m[i][1];
- if(qx >= 0 && qx < H && qy >= 0 && qy < W && p[qx][qy] == ' '){
- int tmpb = 0 , nbag;
- if(blood.find(mp(qx , qy)) != blood.end()){
- tmpb = blood[mp(qx , qy)];
- if(now.bag & (1 << tmpb) != 0) tmpb = 0 , nbag = now.bag;
- else nbag = now.bag | (1 << tmpb) , tmpb = val[tmpb];
- }
- else tmpb = 0 , nbag = now.bag;
- if(dis[nbag][qx][qy].a > now.dis + 1){
- dis[nbag][qx][qy] = mp(now.dis + 1 , now.blood - 1 + tmpb);
- pa[nbag][qx][qy] = mp(now.bag , i);
- qu.push(N(qx , qy , dis[nbag][qx][qy].b , dis[nbag][qx][qy].a , nbag));
- }
- }
- }
- }
- }
- int ans = INF , po = -1;
- PII now = mp(H - 2 , W - 1);
- for(int i = 0 ; i < bloodlim ; i++) if(dis[i][H - 2][W - 1].a < ans)
- ans = dis[i][H - 2][W - 1].a , po = i;
- if(ans == INF) return -1;
- stack<int> cc;
- while(true){
- PII dir = pa[po][now.a][now.b];
- cc.push(dir.b);
- now.a -= m[dir.b][0] , now.b -= m[dir.b][1];
- po = dir.a;
- if(now == mp(1 , 0)) break;
- }
- while(cc.size()) way.push_back(cc.top()) , cc.pop();
- return 0;
- }
- void solve()
- {
- way.clear();
- for(int i=0;i<H;i++)for(int j=0;j<W;j++)step[i][j]=INF;
- PII A=mp(1,1),B;
- step[1][1]=0;
- from[1][1]=0;
- Q.push_back(A);
- while(!Q.empty())
- {
- A=Q.front();Q.pop_front();
- for(int i=0;i<4;i++)
- {
- B=mp(A.a+m[i][0],A.b+m[i][1]);
- if(p[B.a][B.b]==V)continue;
- if(step[A.a][A.b]+1>=step[B.a][B.b])continue;
- from[B.a][B.b]=i;
- step[B.a][B.b]=step[A.a][A.b]+1;
- Q.push_back(B);
- }
- }
- PII now=mp(H-2,W-2);
- while(!(now.a==1&&now.b==1))
- {
- way.push_front(from[now.a][now.b]);
- int w=3-from[now.a][now.b];
- now.a+=m[w][0];
- now.b+=m[w][1];
- }
- way.push_front(2);
- way.push_back(2);
- }
- ///以下為小工具系列===========================================
- bool inside(int x,int y)
- {
- if(x<0||x>=H)return false;
- if(y<0||y>=W)return false;
- return true;
- }
- void print_box(int x, int y,int col)
- {
- SetColor(0,col);
- gotoxy(x+TOP,y*2);
- printf(" ");
- SetColor(15,0);
- }
- void print_Nbox(int x, int y, int n, int col)
- {
- SetColor(15,col);
- gotoxy(x+TOP,y*2);
- if(n>=10)printf("%d",n);
- else printf("0%d",n);
- SetColor(15,0);
- }
- void show_bar()
- {
- printf("===================================迷宮===================================\n");
- }
- void show_maze()
- {
- for(int i=0;i<H;i++)
- {
- for(int j=0;j<W;j++)
- {
- if(p[i][j]==U)print_box(i,j,BCOL);
- if(p[i][j]==V)print_box(i,j,WCOL);
- }
- printf("\n");
- }
- SetColor(15,0);
- }
- void show_info(int s,int b)
- {
- gotoxy(H+TOP,0);
- cout << " " << endl;
- gotoxy(H+TOP,0);
- //assert(b >= 10);
- if(b!=0)printf("當前血量: %d\n",b);
- printf("使用步數: %d",s);
- }
- void setHW(int _a,int _b,int _M)
- {
- H=rand()%_M+_a,W=rand()%_M+_b;
- if(!(H%2))H++;
- if(!(W%2))W++;
- }
- int decide(int x,int y,int w)
- {
- vector<PII> v;
- int xx,yy;
- for(int i=0;i<4;i++)
- {
- if(i == 3 - w) continue;
- xx=x+m[i][0],yy=y+m[i][1];
- if(xx >= 0 && xx < H && yy >= 0 && yy < W && p[xx][yy]==U)
- v.push_back(mp(xx + yy , i));
- }
- if(v.empty()) return 3 - w;
- else {
- sort(v.begin() , v.end());
- int tmp = rand() % (int)v.size();
- if(tmp != 0 && rand() % 11 < 1) tmp --;
- return v[tmp].b;
- }
- }
- void wait_for_enter()
- {
- while(true)
- {
- if(kbhit())
- {
- char c=getch();
- if(c==13)return;
- }
- }
- }
- void finish_game(int winner,int s)
- {
- clrscr();
- show_bar();
- if(winner==0)
- {
- puts("\n\n\t\t\tThank you for playing");
- printf("\n\n\t\t\t銘謝惠顧 你輸了");
- puts("\n\n\t\t\t遊戲結束\n\n");
- wait_for_enter();
- return;
- }
- if(winner==1)printf("\n\t\tYOU WIN :)\n");
- if(winner==2)printf("\n\t\tPC WINS :P\n");
- if(s!=-1)printf("\n\n\t\t\t您一共花了%d步\n",s);
- if(s==way.size())SetColor(2,0),puts("\n\n\t\t\t你使用了最短路徑!!"),SetColor(15,0);
- else SetColor(15,0),printf("\n\n\t\t\t這不是最短路徑(%d步)...\n",way.size()),SetColor(15,0);
- puts("\n\n\t\t\tThank you for playing");
- puts("\n\n\t\t\t遊戲結束\n\n");
- puts("\n\n\t\t\tPRESS ENTER TO CONTINUE\n\n");
- wait_for_enter();
- }
- ///生成===========================================
- void prim_build(bool anim)
- {
- if(anim)show_maze();
- vector<PII> wall;
- for(int i=0;i<H;i++)for(int j=0;j<W;j++)p[i][j]=V;
- p[1][1]=U;
- wall.push_back(make_pair(1,2));
- wall.push_back(make_pair(2,1));
- while(wall.size())
- {
- if(anim)Sleep(SDLAY);
- int randpos=rand()%wall.size();
- PII now=wall[randpos];
- wall.erase(wall.begin()+randpos);
- int count=0;
- for(int i=0;i<4;i++)if(p[now.a+m[i][0]][now.b+m[i][1]]==U)++count;
- if(count>1)continue;
- p[now.a][now.b]=U;
- if(anim)print_box(now.a,now.b,BCOL);
- for(int i=0;i<4;i++)
- {
- int newx=now.a+m[i][0],newy=now.b+m[i][1];
- if(p[newx][newy]==U)continue;
- if(newx>=(H-1)||newx<1)continue;
- if(newy>=(W-1)||newy<1)continue;
- wall.push_back(make_pair(newx,newy));
- }
- }
- p[1][0]=U;p[1][1]=U;p[H-2][W-1]=U;p[H-2][W-2]=U;
- if(anim)Sleep(SDLAY);
- if(anim)print_box(1,0,BCOL),print_box(1,1,BCOL),print_box(H-2,W-1,BCOL),print_box(H-2,W-2,BCOL);
- solve() , minstep_solve = way.size();
- }
- void kruskal_build(bool anim)
- {
- if(anim)show_maze();
- DJset djset;
- djset.djinit(H*W);
- vector<PII> wall;
- for(int i=0;i<H;i++)
- {
- for(int j=0;j<W;j++)
- {
- if(anim)Sleep(SDLAY);
- if(i%2==1&&j%2==1)
- {
- p[i][j]=U;
- if(anim)print_box(i,j,BCOL);
- }
- else
- {
- //p[i][j]=V;
- if(i==0||i==(H-1))continue;
- if(j==0||j==(W-1))continue;
- if((i%2)==(j%2))continue;
- wall.push_back(make_pair(i,j));
- }
- }
- }
- while(wall.size())
- {
- if(anim)Sleep(SDLAY);
- int randpos=rand()%wall.size();
- PII now=wall[randpos];
- wall.erase(wall.begin()+randpos);
- for(int i=0;i<4;i++)
- {
- int ax=now.a+m[i][0],ay=now.b+m[i][1];
- int bx=now.a-m[i][0],by=now.b-m[i][1];
- if(p[now.a][now.b]==U)continue;
- if(p[ax][ay]==V)continue;
- int PA=ax*W+ay,PB=bx*W+by;
- if(djset.same(PA,PB))continue;
- else
- {
- djset.unite(PA,PB);
- p[now.a][now.b]=U;
- if(anim)print_box(now.a,now.b,BCOL);
- }
- }
- }
- p[1][0]=U;p[1][1]=U;p[H-2][W-1]=U;p[H-2][W-2]=U;
- if(anim)Sleep(SDLAY);
- if(anim)print_box(1,0,BCOL),print_box(1,1,BCOL),print_box(H-2,W-1,BCOL),print_box(H-2,W-2,BCOL);
- solve() , minstep_solve = way.size();
- }
- void haha_build(bool anim, int hole){
- if(anim)show_maze();
- typedef pair<PII , PII> PIIII;
- priority_queue<PIIII> qu , ho;
- for(int i = 1 ; i < H - 1 ; i ++){
- for(int j = 1 ; j < W - 1 ; j ++){
- p[i][j] = U;
- if(anim){
- print_box(i,j,BCOL);
- Sleep(SDLAY);
- }
- }
- }
- for(int i = 2 ; i < W - 1 ; i += 2)
- qu.push(mp4(rand() , 3 , 0 , i)) , qu.push(mp4(rand() , 0 , H - 1 , i));
- for(int i = 2 ; i < H - 1 ; i += 2)
- qu.push(mp4(rand() , 2 , i , 0)) , qu.push(mp4(rand() , 1 , i , W - 1));
- while(qu.size()){
- int dir = qu.top().a.b , ran = qu.top().a.a;
- PII now = qu.top().b , ld = mp(m[dir][0] , m[dir][1]) , rd = mp(m[dir][0] , m[dir][1]);
- qu.pop();
- ld.a += (dir == 1 || dir == 2) ? -1 : 0;
- ld.b += (dir == 0 || dir == 3) ? -1 : 0;
- rd.a += (dir == 1 || dir == 2) ? 1 : 0;
- rd.b += (dir == 0 || dir == 3) ? 1 : 0;
- int x = now.a + m[dir][0] , y = now.b + m[dir][1];
- int lx = x + ld.a , ly = y + ld.b;
- int rx = x + rd.a , ry = y + rd.b;
- int qx = now.a + m[dir][0] * 2 , qy = now.b + m[dir][1] * 2;
- if(p[x][y] == U && p[qx][qy] == U && p[lx][ly] == U && p[rx][ry] == U){
- if(x % 2 == 0 && y % 2 == 0){
- for(int i = 0 ; i < 4 ; i ++)
- qu.push(mp4(rand() , i , x , y));
- }
- else{
- qu.push(mp4(ran , dir , x , y));
- ho.push(mp4(rand() , -1 , x , y));
- }
- p[x][y] = V;
- if(anim){
- print_box(x,y,WCOL);
- Sleep(SDLAY);
- }
- }
- }
- p[1][0] = U; p[1][1] = U; p[H - 2][W - 1] = U; p[H - 2][W - 2] = U;
- if(anim)Sleep(SDLAY);
- if(anim)print_box(1,0,BCOL),print_box(1,1,BCOL),print_box(H-2,W-1,BCOL),print_box(H-2,W-2,BCOL);
- while(ho.size() && hole > 0) hole -- , p[ho.top().b.a][ho.top().b.b] = U , ho.pop();
- solve() , minstep_solve = way.size();
- }
- void set_blood_bag(int sum){
- do
- {
- blood_bag.clear();
- while(sum --){
- int x = rand() % H , y = rand() % W;
- while(p[x][y] == V || blood_bag.find(mp(x , y)) != blood_bag.end())
- x = rand() % H , y = rand() % W;
- blood_bag[mp(x , y)] = rand()%20+20+1;
- }
- }while(goodsolverByblood(blood_bag, BLOOD)==-1);
- minstep_blood = way.size();
- }
- void show_blood_bag()
- {
- for(int i=0;i<H;i++)
- {
- for(int j=0;j<W;j++)
- {
- if(blood_bag.find(mp(i,j))!=blood_bag.end())print_Nbox(i,j,blood_bag[mp(i,j)],BLCOL);
- }
- }
- }
- ///以下為遊戲模式系列===========================================
- void user_play()
- {
- int nx=TOP,ny=0,s=0;
- hide();
- clrscr();
- show_bar();
- show_maze();
- show_info(s,0);
- print_box(nx,ny,SCOL);
- while(!(nx==(H-2)&&ny==(W-1)))
- {
- if(kbhit())
- {
- int w=getkey();
- if(w==-1)return;
- if(nx+m[w][0] >= 0 && nx+m[w][0] < H && ny+m[w][1] >= 0 && ny+m[w][1] < W &&
- p[nx+m[w][0]][ny+m[w][1]]==U)
- {
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- print_box(nx,ny,SCOL);
- show_info(++s,0);
- }
- }
- }
- gotoxy(H+1,0);
- finish_game(1,s);
- }
- void pc_play()
- {
- int nx=TOP,ny=0,s=0;
- hide();
- clrscr();
- show_bar();
- show_maze();
- show_info(s,0);
- print_box(nx,ny,SCOL);
- while(!(nx==(H-2)&&ny==(W-1)))
- {
- Sleep(200-pc_speed*2);
- int w=way.front();way.pop_front();
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- print_box(nx,ny,SCOL);
- show_info(++s,0);
- SetColor(15,0);
- }
- gotoxy(H+1,0);
- finish_game(2,s);
- }
- void user_vs_pc()
- {
- int nx=TOP,ny=0,mx=H-2,my=W-1,s=0;
- hide();
- clrscr();
- show_bar();
- show_maze();
- print_box(nx,ny,SCOL);
- print_box(mx,my,MCOL);
- while(true)
- {
- int z=-1;
- if(nx==(H-2)&&ny==(W-1))break;
- if(mx==1&&my==0)break;
- if(kbhit())
- {
- int w=getkey();
- if(w==-1)return;
- if(nx+m[w][0] >= 0 && nx+m[w][0] < H && ny+m[w][1] >= 0 && ny+m[w][1] < W &&
- p[nx+m[w][0]][ny+m[w][1]]==U)
- {
- print_box(mx,my,BCOL);
- int z=3-way.back();way.pop_back();
- mx+=m[z][0],my+=m[z][1];
- print_box(mx,my,MCOL);
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- print_box(nx,ny,SCOL);
- show_info(++s,0);
- }
- }
- }
- if(nx==(H-2)&&ny==(W-1))finish_game(1,s);
- else finish_game(2,s);
- }
- void random_go()
- {
- int nx=TOP,ny=0,mx=H-2,my=W-2,z=-1,s=0;
- hide();
- clrscr();
- show_bar();
- show_maze();
- print_box(nx,ny,SCOL);
- print_box(mx,my,MCOL);
- while(true)
- {
- if(nx==(H-2)&&ny==(W-1))break;
- if(kbhit())
- {
- int w=getkey();
- if(w==-1)return;
- if(nx+m[w][0] >= 0 && nx+m[w][0] < H && ny+m[w][1] >= 0 && ny+m[w][1] < W &&
- p[nx+m[w][0]][ny+m[w][1]]==U)
- {
- if((nx+m[w][0]==mx)&&(ny+m[w][1])==my)continue;
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- print_box(nx,ny,SCOL);
- print_box(mx,my,BCOL);
- z=decide(mx,my,z);
- mx+=m[z][0],my+=m[z][1];
- print_box(mx,my,MCOL);
- show_info(++s,0);
- }
- }
- }
- finish_game(1,s);
- }
- void user_survive()
- {
- int nx=TOP,ny=0,s=0,b=BLOOD;
- map<PII,int> BB=blood_bag;
- hide();
- clrscr();
- show_bar();
- show_maze();
- show_blood_bag();
- show_info(s,b);
- print_box(nx,ny,SCOL);
- while(!(nx==(H-2)&&ny==(W-1)))
- {
- if(kbhit())
- {
- int w=getkey();
- if(w==-1)return;
- if(p[nx+m[w][0]][ny+m[w][1]]==U)
- {
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- if(BB.find(mp(nx,ny))!=BB.end())b+=BB[mp(nx,ny)],BB[mp(nx,ny)]=0;
- print_box(nx,ny,SCOL);
- if(b<=1){finish_game(0,s);return;}
- show_info(++s,--b);
- }
- }
- }
- gotoxy(H+1,0);
- finish_game(1,s);
- }
- void pc_survive()
- {
- int nx=TOP,ny=0,s=0,b=BLOOD;
- deque<int> ddq = way;
- map<PII,int> BB=blood_bag;
- hide();
- clrscr();
- show_bar();
- show_maze();
- show_blood_bag();
- show_info(s,b);
- print_box(nx,ny,SCOL);
- while(!(nx==(H-2)&&ny==(W-1)))
- {
- Sleep(200-pc_speed*2);
- int w=way.front();way.pop_front();
- print_box(nx,ny,BCOL);
- nx+=m[w][0],ny+=m[w][1];
- if(BB.find(mp(nx,ny))!=BB.end())b+=BB[mp(nx,ny)],BB[mp(nx,ny)]=0;
- print_box(nx,ny,SCOL);
- show_info(++s,--b);
- SetColor(15,0);
- }
- way = ddq;
- gotoxy(H+1,0);
- finish_game(2,s);
- }
- ///以下為選單系列===========================================
- void spawn()
- {
- clrscr();
- int chs;
- show_bar();
- printf("\t1. Prim生成\n");
- printf("\t2. Kruskal生成\n");
- printf("\t3. 呵呵生成\n");
- printf("\t4. BACK\n");
- printf("\n");
- printf("\t->");
- scanf("%d",&chs);
- if(chs==4)return;
- for(int i=0;i<H;i++)for(int j=0;j<W;j++)p[i][j]=V;
- if(chs==1)prim_build(true);
- if(chs==2)kruskal_build(true);
- if(chs==3)haha_build(true,0);
- set_blood_bag(BAG);
- gotoxy(H+TOP,0);
- system("PAUSE");
- }
- void menu()
- {
- for(int i=0;i<H;i++)for(int j=0;j<W;j++)p[i][j]=V;
- kruskal_build(false);
- set_blood_bag(BAG);
- while(true)
- {
- show();
- clrscr();
- int chs;
- show_bar();
- printf("\t0. < SPAWN > 迷宮生成\n");
- printf("\t1. <U S E R> 鍵盤走迷宮\n");
- printf("\t2. < P C > 電腦走迷宮\n");
- printf("\t3. < FIGHT > 與電腦競賽\n");
- printf("\t4. < CRAZY > 與亂走電腦競賽\n");
- printf("\t5. <SURVIVE> 生存模式\n");
- printf("\t6. < PCSUR > 電腦生存\n");
- printf("\t7 < RESET > 血包重置\n");
- printf("\t8. < E N D > 離開\n");
- printf("\n\t\t Type What You Need: ");
- scanf("%d",&chs);
- if(chs==0)spawn();
- if(chs==1)user_play();
- if(chs==2)pc_play();
- if(chs==3)user_vs_pc();
- if(chs==4)random_go();
- if(chs==5)user_survive();
- if(chs==6)pc_survive();
- if(chs==7)set_blood_bag(BAG);
- if(chs==8)return;
- }
- }
- int main()
- {
- srand(time(NULL));
- menu();
- return 0;
- }
Add Comment
Please, Sign In to add comment