泡泡消除最優解
阿新 • • 發佈:2018-12-26
程式碼只實現了最優解,但是未消除重複,所以比較耗時,有待優化
#include<iostream> #include<cstdlib> #include<fstream> #include<string> #include<stdio.h> #include<sstream> #include<ctime> #include<typeinfo.h> #include<vector> #include <cstring> #define ROW 5 #define COL 5 using namespace std; class Point { private: int x,y;//座標 public: Point() { } Point(int x, int y) { this->x = x; this->y = y; } void setX(int x) { this->x=x; } void setY(int y) { this->y=y; } int getX() { return x; } int getY() { return y; } void print() { cout<<"("<<x<<","<<y<<")"<<endl; } }; class Qipan { private: int score;//儲存當前的分 char pan[ROW][COL];//儲存當前盤面 Point point;//父棋盤點選座標生成該棋盤 // Qipan *parent;//指向父棋盤,用指標出現dfs過程中記憶體釋放,野指標的現象,放棄使用,用以下兩點實現指父功能 int my_pos;//自己在vector (allqipan)的位置 int parent_pos;//父節點在vector(allqipan) 的位置 public: Qipan() { score=0; memset(pan,0,sizeof(pan)); } void setP(Point p) { point=p; } void setMy_pos(int p) { my_pos=p; } void setParent_pos(int p) { parent_pos=p; } void setPan(int i,int j,char k) { pan[i][j]=k; } void setPan(Point p,char k) { pan[p.getX()][p.getY()]=k; } void setPanfrom(char a[ROW][COL]) { int i,j; for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) pan[i][j]=a[i][j]; } } void setPanto(char a[ROW][COL]) { int i,j; for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) a[i][j]=pan[i][j]; } } int getScore() { return score; } void setScore(int n) { score=n; } Point getP() { return point; } char getPan(int i,int j) { return pan[i][j]; } char getPan(Point p) { return pan[p.getX()][p.getY()]; } int getMy_pos() { return my_pos; } int getParent_pos() { return parent_pos; } void initQipan();//初始化盤面 void printQipan();//列印盤面 void printInfo();//列印盤面所有資訊 int calculateScore(int n);//計算消除n個球的得分 int eliminate(int x,int y);//消除 void findChild();//生產子盤面 }; vector<Qipan> allqipan; //過程中所有的盤面 char pan_temp[ROW][COL];//臨時盤面 vector<Qipan> result; //最高得分步驟盤面 int cmp2dArray(char a[ROW][COL],char b[ROW][COL])//判斷相同 { int i,j; for(i=0;i<ROW;i++) for(j=0;j<COL;j++) if(b[i][j]!=a[i][j]) { return 0;//不同 } return 1;//相同 } void Qipan::initQipan() { int i,j; srand((unsigned)time(NULL)); for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) { int tmp = rand()%5; switch(tmp) { case 0:setPan(i,j,'A'); break; case 1:setPan(i,j,'B'); break; case 2:setPan(i,j,'C'); break; case 3:setPan(i,j,'D'); break; case 4:setPan(i,j,'E'); } } } } void Qipan::printQipan() { int i,j; for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) { cout<<getPan(i,j)<<" "; } cout<<endl; } } void Qipan::printInfo() { if(getP().getX()<0||getP().getY()<0)//第一個盤面 { cout<<"初始盤面:"<<endl; printQipan(); cout<<"---------------------------------------"<<endl; } else { cout<<"點選座標:"; getP().print(); cout<<"生成盤面:"<<endl; printQipan(); cout<<"當前得分:"<<getScore()<<endl; cout<<"---------------------------------------"<<endl; } } int Qipan::calculateScore(int n) { int i,j; if(n>=2) { if(n==2) return 2; else { for(i=2,j=2;j<=n;j++) i+=(j-2)*2; return i; } } return 0; } int dir[4][2] = {0,1,0,-1,1,0,-1,0}; int Qipan::eliminate(int x,int y) { int e_num=1; vector<Point> block; Point p(x,y); char temp=getPan(p); setPan(p,temp+32); block.push_back(p); while(!block.empty()) { p= block.back(); int x=p.getX(); int y=p.getY(); block.pop_back(); for(int i = 0; i < 4; i++) { int xx = x + dir[i][0]; int yy = y + dir[i][1]; if(xx < 0 || xx >= ROW || yy < 0 || yy >= COL) continue; if(getPan(xx,yy) != temp) continue; p.setX(xx); p.setY(yy); block.push_back(p); setPan(p,temp+32); e_num++; } } int i,j,k,col_circle_max=COL,row_circle_max=ROW; char bub; for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) { if(pan[i][j]>='a') { pan[i][j]='O'; } } } //向左邊靠攏 while(col_circle_max--) { for(i=0;i<ROW;i++) { for(j=0;j<COL-1;j++) { if(pan[i][j]=='O') { bub=pan[i][j]; pan[i][j]=pan[i][j+1]; pan[i][j+1]=bub; } } } } //向上邊靠攏 while(row_circle_max--) { for(j=0;j<COL;j++) { for(i=0;i<ROW-1;i++) { if(pan[i][j]=='O') { bub=pan[i][j]; pan[i][j]=pan[i+1][j]; pan[i+1][j]=bub; } } } } return e_num; } void Qipan::findChild() { int i,j; char temp; for(i=0;i<ROW;i++) { for(j=0;j<COL;j++) { Point p(i,j); temp=getPan(p); if(temp<='E') { if((i+1<ROW&&getPan(i+1,j)==temp)||(i>0&&getPan(i-1,j)==temp)||(j+1<COL&&getPan(i,j+1)==temp)||(j>0&&getPan(i,j-1)==temp)) { setPanto(pan_temp); //暫存未改變的棋盤 int e_num=eliminate(i,j); Qipan child; child.setParent_pos(getMy_pos()); child.setMy_pos(allqipan.size()); child.setP(p); child.setScore(calculateScore(e_num)+getScore()); child.setPanfrom(pan); setPanfrom(pan_temp);//恢復 allqipan.push_back(child); child.findChild(); } else { continue; } } } } } int main() { Qipan origin; origin.setMy_pos(0); origin.setParent_pos(-1);//表示無父 Point p(-1,-1); origin.setP(p); origin.initQipan(); allqipan.push_back(origin); origin.findChild(); int max_score=0,index; cout<<"\n\n最優解求解過程共生產:"<<allqipan.size()<<"箇中間過程棋盤(未消除重複)"<<endl; for (int i = 0; i < allqipan.size(); ++i) { if(allqipan.at(i).getScore()>max_score) { max_score=allqipan.at(i).getScore(); index=i; } } cout<<"最高分:"<<max_score<<endl; cout<<"\n\n---------------------------------------"<<endl; cout<<"---------------------------------------"<<endl; Qipan temp=allqipan.at(index); result.push_back(temp); while(temp.getParent_pos()>=0) { temp=allqipan.at(temp.getParent_pos()); result.push_back(temp); } for (int i = result.size()-1; i >=0; i--) { result.at(i).printInfo(); } return 0; }