botzone Tetris2
为了证明窝最近没有颓废
(并且为了多骗点访问量
游戏链接:https://botzone.org/game/Tetris2
大概就是先写个估价,然后剪剪枝搜它4步。
#include<iostream> #include<string> #include<cmath> #include<algorithm> #include<cstdlib> #include<ctime> #include<cstring> #define INF 1e180 using namespace std; #define MAPWIDTH 10 #define MAPHEIGHT 20 //W1 防长条 //W2、W3 优先放两边 //W4 forfuture //W5、W6 封顶 //W7 多给长条 //W8 maxheiht //W9、13 拒绝不可达行 //W10 高度系数 //W11 unreachable //W12 奖励行 const int GO[7][4]={{1,1,1,1},{1,1,1,1},{1,1,0,0},{1,1,0,0},{1,1,1,1},{1,1,0,0},{1,0,0,0}}; const bool TYPEwork[7]={0,0,0,0,1,1,0}; const int M_DEEP=4,E_DEEP=2,RE=0,intwo=1; double W1=1.2,W2=0.998,W3=0.98,W4=3,W5=1.4,W6=1,prize=0,W7=30,W8=10,W9=1,W10=100,W11=2,W12=intwo?100:0,W13=1.4,paper=5; int Work_num=3,Type_num=3; #define CONDITION (x==5&&y==3&&o==1)||(x==1&&y==2&&o==1) // 我所在队伍的颜色(0为红,1为蓝,仅表示队伍,不分先后) int currBotColor; int enemyColor; // 先y后x,记录地图状态,0为空,1为以前放置,2为刚刚放置,负数为越界 // (2用于在清行后将最后一步撤销再送给对方) int gridInfo[2][MAPHEIGHT + 2][MAPWIDTH + 2] = { 0 }; // 代表分别向对方转移的行 int trans[2][6][MAPWIDTH + 2] = { 0 }; // 转移行数 int transCount[2] = { 0 }; // 运行eliminate后的当前高度 int maxHeight[2] = { 0 }; // 总消去行数的分数之和 int elimTotal[2] = { 0 }; // 连续几回合发生过消去了 int elimCombo[2] = { 0 }; // 一次性消去行数对应分数 const int elimBonus[] = { 0, 1, 3, 5, 7 }; // 给对应玩家的各类块的数目总计 int typeCountForColor[2][7] = { 0 }; int turnID, blockType; int nextTypeForColor[2]; double MMH=0; int debug; #ifndef _BOTZONE_ONLINE FILE *DEBUG=fopen("b.out","w"); #endif bool forsize[MAPHEIGHT+2][MAPWIDTH+2][4]; const int blockShape[7][4][8] = { { { 0,0,1,0,-1,0,-1,-1 },{ 0,0,0,1,0,-1,1,-1 },{ 0,0,-1,0,1,0,1,1 },{ 0,0,0,-1,0,1,-1,1 } }, { { 0,0,-1,0,1,0,1,-1 },{ 0,0,0,-1,0,1,1,1 },{ 0,0,1,0,-1,0,-1,1 },{ 0,0,0,1,0,-1,-1,-1 } }, { { 0,0,1,0,0,-1,-1,-1 },{ 0,0,0,1,1,0,1,-1 },{ 0,0,-1,0,0,1,1,1 },{ 0,0,0,-1,-1,0,-1,1 } }, { { 0,0,-1,0,0,-1,1,-1 },{ 0,0,0,-1,1,0,1,1 },{ 0,0,1,0,0,1,-1,1 },{ 0,0,0,1,-1,0,-1,-1 } }, { { 0,0,-1,0,0,1,1,0 },{ 0,0,0,-1,-1,0,0,1 },{ 0,0,1,0,0,-1,-1,0 },{ 0,0,0,1,1,0,0,-1 } }, { { 0,0,0,-1,0,1,0,2 },{ 0,0,1,0,-1,0,-2,0 },{ 0,0,0,1,0,-1,0,-2 },{ 0,0,-1,0,1,0,2,0 } }, { { 0,0,0,1,-1,0,-1,1 },{ 0,0,-1,0,0,-1,-1,-1 },{ 0,0,0,-1,1,-0,1,-1 },{ 0,0,1,0,0,1,1,1 } } }; // 7种形状(长L| 短L| 反z| 正z| T| 直一| 田格),4种朝向(上左下右),8:每相邻的两个分别为x,y const int rotateBlank[7][4][10] = { { { 1,1,0,0 },{ -1,1,0,0 },{ -1,-1,0,0 },{ 1,-1,0,0 } }, { { -1,-1,0,0 },{ 1,-1,0,0 },{ 1,1,0,0 },{ -1,1,0,0 } }, { { 1,1,0,0 },{ -1,1,0,0 },{ -1,-1,0,0 },{ 1,-1,0,0 } }, { { -1,-1,0,0 },{ 1,-1,0,0 },{ 1,1,0,0 },{ -1,1,0,0 } }, { { -1,-1,-1,1,1,1,0,0 },{ -1,-1,-1,1,1,-1,0,0 },{ -1,-1,1,1,1,-1,0,0 },{ -1,1,1,1,1,-1,0,0 } }, { { 1,-1,-1,1,-2,1,-1,2,-2,2 } ,{ 1,1,-1,-1,-2,-1,-1,-2,-2,-2 } ,{ -1,1,1,-1,2,-1,1,-2,2,-2 } ,{ -1,-1,1,1,2,1,1,2,2,2 } }, { { 0,0 },{ 0,0 } ,{ 0,0 } ,{ 0,0 } } }; // 旋转的时候需要为空的块相对于旋转中心的坐标 class Tetris { public: const int blockType; // 标记方块类型的序号 0~6 int blockX; // 旋转中心的x轴坐标 int blockY; // 旋转中心的y轴坐标 int orientation; // 标记方块的朝向 0~3 const int(*shape)[8]; // 当前类型方块的形状定义 int color; Tetris(int t, int color) : blockType(t), shape(blockShape[t]), color(color) { } inline Tetris &set(int x = -1, int y = -1, int o = -1) { blockX = x == -1 ? blockX : x; blockY = y == -1 ? blockY : y; orientation = o == -1 ? orientation : o; return *this; } // 判断当前位置是否合法 inline bool isValid(int x = -1, int y = -1, int o = -1) { x = x == -1 ? blockX : x; y = y == -1 ? blockY : y; o = o == -1 ? orientation : o; if (o < 0 || o > 3) return false; int i, tmpX, tmpY; for (i = 0; i < 4; i++) { tmpX = x + shape[o][2 * i]; tmpY = y + shape[o][2 * i + 1]; if (tmpX < 1 || tmpX > MAPWIDTH || tmpY < 1 || tmpY > MAPHEIGHT || gridInfo[color][tmpY][tmpX] != 0) return false; } return true; } // 判断是否落地 inline bool onGround() { if (isValid() && !isValid(-1, blockY - 1)) return true; return false; } // 将方块放置在场地上 inline bool place() { if (!onGround()) return false; int i, tmpX, tmpY; for (i = 0; i < 4; i++) { tmpX = blockX + shape[orientation][2 * i]; tmpY = blockY + shape[orientation][2 * i + 1]; gridInfo[color][tmpY][tmpX] = 2; } return true; } // 检查能否逆时针旋转自己到o inline bool rotation(int o) { if (o < 0 || o > 3) return false; if (orientation == o) return true; int fromO = orientation; int i, blankX, blankY; while (true) { if (!isValid(-1, -1, fromO)) return false; if (fromO == o) break; // 检查旋转碰撞 if (intwo) for (i = 0; i < 5; i++) { blankX = blockX + rotateBlank[blockType][fromO][2 * i]; blankY = blockY + rotateBlank[blockType][fromO][2 * i + 1]; if (blankX == blockX && blankY == blockY) break; if (gridInfo[color][blankY][blankX] != 0) return false; } fromO = (fromO + 1) % 4; } return true; } }; // 围一圈护城河 void init() { int i; for (i = 0; i < MAPHEIGHT + 2; i++) { gridInfo[1][i][0] = gridInfo[1][i][MAPWIDTH + 1] = -2; gridInfo[0][i][0] = gridInfo[0][i][MAPWIDTH + 1] = -2; } for (i = 0; i < MAPWIDTH + 2; i++) { gridInfo[1][0][i] = gridInfo[1][MAPHEIGHT + 1][i] = -2; gridInfo[0][0][i] = gridInfo[0][MAPHEIGHT + 1][i] = -2; } } inline bool isValid(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){ if (o < 0 || o > 3) return false; int i, tmpX, tmpY; for (i = 0; i < 4; i++){ tmpX = x + blockShape[type][o][2 * i]; tmpY = y + blockShape[type][o][2 * i + 1]; if (tmpX < 1 || tmpX > MAPWIDTH ||tmpY < 1 || tmpY > MAPHEIGHT ||map[tmpY][tmpX] != 0)return false; } return true; } inline bool onGround(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){ if (isValid(map,type,x,y,o) && !isValid(map,type,x,y-1,o)) return true; return false; } inline bool rotation(int map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o){ if (intwo) for (int i = 0; i < 5; i++) { int blankX = x + rotateBlank[type][o][2 * i]; int blankY = y + rotateBlank[type][o][2 * i + 1]; if (blankX == x && blankY == y) break; if (map[blankY][blankX]) return 0; } return 1; } namespace Util { // 检查能否从场地顶端直接落到当前位置 inline bool checkDirectDropTo(int map[MAPHEIGHT+2][MAPWIDTH+2], int blockType, int x, int y, int o) { const int *def = blockShape[blockType][o]; for (; y <= MAPHEIGHT; y++) for (int i = 0; i < 4; i++) { int _x = def[i * 2] + x, _y = def[i * 2 + 1] + y; if (_y > MAPHEIGHT) continue; if (_y < 1 || _x < 1 || _x > MAPWIDTH || map[_y][_x]) return false; } return true; } void dfs(int map[MAPHEIGHT+2][MAPWIDTH+2],bool bo[MAPHEIGHT+2][MAPWIDTH+2][4],int type,int x,int y,int o){ //cout<<x<<y<<o<<endl; if (!isValid(map,type,x,y,o)) return; if (bo[y][x][o]) return; //if (debug) fprintf(DEBUG,"O_O::::%d %d %d %d %d\n",x,y,o,bo[y][x][o],sizeof(bo)); bo[y][x][o]=1; dfs(map,bo,type,x-1,y,o);dfs(map,bo,type,x+1,y,o);dfs(map,bo,type,x,y-1,o); if (rotation(map,type,x,y,o))dfs(map,bo,type,x,y,(o+1)%4); } void init(int map[MAPHEIGHT+2][MAPWIDTH+2],bool bo[MAPHEIGHT+2][MAPWIDTH+2][4],int type,bool de=0){ debug=de; memset(bo,0,sizeof(forsize)); //if (debug) fprintf(DEBUG,"%d\n",type); for (int o=0;o<4;o++) for (int x=1;x<=MAPWIDTH; x++){ if (checkDirectDropTo(map,type,x,MAPHEIGHT,o)) dfs(map,bo,type,x,MAPHEIGHT,o); if (checkDirectDropTo(map,type,x,MAPHEIGHT-1,o)) dfs(map,bo,type,x,MAPHEIGHT-1,o); if (type==5) if (checkDirectDropTo(map,type,x,MAPHEIGHT-2,o)) dfs(map,bo,type,x,MAPHEIGHT-2,o); } } // 检查能否从场地顶端直接落到当前位置 inline bool checkDirectDropTo(int color, int blockType, int x, int y, int o) { auto &def = blockShape[blockType][o]; for (; y <= MAPHEIGHT; y++) for (int i = 0; i < 4; i++) { int _x = def[i * 2] + x, _y = def[i * 2 + 1] + y; if (_y > MAPHEIGHT) continue; if (_y < 1 || _x < 1 || _x > MAPWIDTH || gridInfo[color][_y][_x]) return false; } return true; } // 消去行 void eliminate(int color) { int &count = transCount[color] = 0; int i, j, emptyFlag, fullFlag, firstFull = 1, hasBonus = 0; maxHeight[color] = MAPHEIGHT; for (i = 1; i <= MAPHEIGHT; i++) { emptyFlag = 1; fullFlag = 1; for (j = 1; j <= MAPWIDTH; j++) { if (gridInfo[color][i][j] == 0) fullFlag = 0; else emptyFlag = 0; } if (fullFlag) { if (intwo&&firstFull && ++elimCombo[color] >= 3) { // 奖励行 for (j = 1; j <= MAPWIDTH; j++) trans[color][count][j] = gridInfo[color][i][j] == 1 ? 1 : 0; count++; hasBonus = 1; } firstFull = 0; for (j = 1; j <= MAPWIDTH; j++) { // 注意这里只转移以前的块,不包括最后一次落下的块(“撤销最后一步”) trans[color][count][j] = gridInfo[color][i][j] == 1 ? 1 : 0; gridInfo[color][i][j] = 0; } count++; } else if (emptyFlag) { maxHeight[color] = i - 1; break; } else for (j = 1; j <= MAPWIDTH; j++) { gridInfo[color][i - count + hasBonus][j] = gridInfo[color][i][j] > 0 ? 1 : gridInfo[color][i][j]; if (count) gridInfo[color][i][j] = 0; } } if (count == 0) elimCombo[color] = 0; maxHeight[color] -= count - hasBonus; elimTotal[color] += elimBonus[count]; } // 转移双方消去的行,返回-1表示继续,否则返回输者 int transfer() { int color1 = 0, color2 = 1; if (transCount[color1] == 0 && transCount[color2] == 0) return -1; if (transCount[color1] == 0 || transCount[color2] == 0) { if (transCount[color1] == 0 && transCount[color2] > 0) swap(color1, color2); int h2; maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1]; if (h2 > MAPHEIGHT) return color2; int i, j; for (i = h2; i > transCount[color1]; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j]; for (i = transCount[color1]; i > 0; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color2][i][j] = trans[color1][i - 1][j]; return -1; } else { int h1, h2; maxHeight[color1] = h1 = maxHeight[color1] + transCount[color2];//从color1处移动count1去color2 maxHeight[color2] = h2 = maxHeight[color2] + transCount[color1]; if (h1 > MAPHEIGHT) return color1; if (h2 > MAPHEIGHT) return color2; int i, j; for (i = h2; i > transCount[color1]; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color2][i][j] = gridInfo[color2][i - transCount[color1]][j]; for (i = transCount[color1]; i > 0; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color2][i][j] = trans[color1][i - 1][j]; for (i = h1; i > transCount[color2]; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color1][i][j] = gridInfo[color1][i - transCount[color2]][j]; for (i = transCount[color2]; i > 0; i--) for (j = 1; j <= MAPWIDTH; j++) gridInfo[color1][i][j] = trans[color2][i - 1][j]; return -1; } } // 颜色方还能否继续游戏 inline bool canPut(int color, int blockType) { Tetris t(blockType, color); for (int y = MAPHEIGHT; y >= 1; y--) for (int x = 1; x <= MAPWIDTH; x++) for (int o = 0; o < 4; o++) { t.set(x, y, o); if (t.isValid() && checkDirectDropTo(color, blockType, x, y, o)) return true; } return false; } // 打印场地用于调试 inline void printField() { #ifndef _BOTZONE_ONLINE static const char *i2s[] = { "~~", "~~", " ", "[]", "##" }; cout << "~~:墙,[]:块,##:新块" << endl; for (int y = MAPHEIGHT + 1; y >= 0; y--) { for (int x = 0; x <= MAPWIDTH + 1; x++) cout << i2s[gridInfo[0][y][x] + 2]; for (int x = 0; x <= MAPWIDTH + 1; x++) cout << i2s[gridInfo[1][y][x] + 2]; cout << endl; } #endif } } int sum_n[21]={0,1,3,6,10,15,21,28,36,45,55,66,78,91,105,120,136,153,171,190,210}; double GetBoardTransitions(int map[MAPHEIGHT+2][MAPWIDTH+2]){ int mmh=0; for (int _y=1;_y<=MAPHEIGHT;_y++) for (int _x=1;_x<MAPWIDTH;_x++) if ((map[_y][_x]&&!map[_y][_x+1])||(!map[_y][_x]&&map[_y][_x+1])) mmh++; for (int _y=1;_y<MAPHEIGHT;_y++) for (int _x=1;_x<=MAPWIDTH;_x++) if ((map[_y][_x]&&!map[_y+1][_x])||(!map[_y][_x]&&map[_y+1][_x])) mmh++; return mmh; } double GetBoardBuriedHoles(int map[MAPHEIGHT+2][MAPWIDTH+2]){ int mmh=0; for (int _x=1;_x<=MAPWIDTH;_x++){ int _y; for (_y=MAPHEIGHT;_y;_y--) if (map[_y][_x]) break; for (;_y;_y--) if (!map[_y][_x]) mmh++; } return mmh; } double GetBoardWells(int map[MAPHEIGHT+2][MAPWIDTH+2]){ double mmh=0,W; for (int _x=1;_x<=MAPWIDTH;_x++){ int _y,wells=0,f=0;W=1.5; for (_y=MAPHEIGHT;_y>=0;_y--){ if(map[_y][_x]==0){ if(map[_y][_x-1]!=0&&map[_y][_x+1]!=0) wells++; }else{ mmh+=sum_n[wells]*W; wells=0; if (f) W+=0.1;else W=0.8; f=1; } } } return mmh; } int qx[300],qy[300],l,r; const int f[2][4]={{0,0,1,-1},{1,-1,0,0}}; inline int bfs(int map[MAPHEIGHT+2][MAPWIDTH+2]){ l=r=0; bool bo[MAPHEIGHT+2][MAPWIDTH+2]; for (int _x=1;_x<=MAPWIDTH;_x++) for (int _y=1;_y<=MAPHEIGHT;_y++) bo[_y][_x]=0; for (int _x=1;_x<=MAPWIDTH;_x++) if (!map[MAPHEIGHT][_x]) qx[r]=_x,qy[r]=MAPHEIGHT,r++; while (l<r){ for (int i=0;i<4;i++) if (!map[qy[l]+f[0][i]][qx[l]+f[1][i]]&&!bo[qy[l]+f[0][i]][qx[l]+f[1][i]]) bo[qy[l]+f[0][i]][qx[l]+f[1][i]]=1,qy[r]=qy[l]+f[0][i],qx[r]=qx[l]+f[1][i],r++; l++; } double mmh=0; for (int _x=1;_x<=MAPWIDTH;_x++) for (int _y=1;_y<=MAPHEIGHT;_y++) mmh+=(!map[_y][_x])&&(!bo[_y][_x]); return mmh; } int finalX, finalY, finalO,_finalX,_finalY,_finalO; double work(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int deepth,double forfuture,bool currBotColor,int eRound); bool canreach[7][MAPHEIGHT+2][MAPWIDTH+2]; double Mavis(int _map[MAPHEIGHT+2][MAPWIDTH+2],int type,int x,int y,int o,int deepth,double MMH,bool currBotColor,int eRound){ bool _bo[MAPHEIGHT+2][MAPWIDTH+2][4],cell_reach[MAPHEIGHT+2][MAPWIDTH+2]; int map[MAPHEIGHT+2][MAPWIDTH+2]; int emptynum[MAPHEIGHT+2],sta[MAPHEIGHT+2]; bool reach[MAPHEIGHT+2]; double value[MAPHEIGHT+2][MAPWIDTH+2]; memset(emptynum,0,sizeof(emptynum)); memset(sta,0,sizeof(sta)); memset(reach,1,sizeof(reach)); memset(cell_reach,0,sizeof(cell_reach)); for (int _y=0;_y<=MAPHEIGHT+1;_y++) for (int _x=0;_x<=MAPWIDTH+1;_x++) map[_y][_x]=_map[_y][_x]; double holenum=1+prize*10; int ErodedPieceCellsMetric,erodedShape=0; bool myCount[7]={0,0,0,0,0,0,0}; for (int i=0;i<7;i++){ myCount[i]=1; for (int j=0;j<7;j++) if (i!=j&&typeCountForColor[currBotColor][i]+1-typeCountForColor[currBotColor][j]>2) myCount[i]=0; } for (int i=0;i<4;i++){ int tmpX=x+blockShape[type][o][2*i]; int tmpY=y+blockShape[type][o][2*i+1]; map[tmpY][tmpX]=3; } int pop=0,O_O=0; for (int _y=1;_y<=MAPHEIGHT;_y++){ int _x=1; for (_x=1;_x<=MAPWIDTH;_x++) if (!map[_y][_x]) break; if (_x==MAPWIDTH+1){ holenum-=prize;pop++; for (_x=1;_x<=MAPWIDTH;_x++) erodedShape+=map[_y][_x]==3,map[_y][_x]=-1; } } ErodedPieceCellsMetric=pop*erodedShape; for (int _x=1;_x<=MAPWIDTH;_x++){ int p=1; for (int i=1;i<=MAPHEIGHT;i++) if (map[i][_x]!=-1) map[p][_x]=map[i][_x],p++; for (;p<=MAPHEIGHT;p++) map[p][_x]=0; } double P_P=0; int max=0; for (int _x=1;_x<=MAPWIDTH;_x++){ int _y=MAPHEIGHT; for (;_y;_y--) if (map[_y][_x]) break; double cost=_y*_y; int u=x<6?x:x-5; cost*=pow(1.05,u); P_P+=cost; if (max<_y) max=_y; } int BoardTransitions=GetBoardTransitions(map),BuriedHoles=GetBoardBuriedHoles(map),Wells=GetBoardWells(map),Bfs=bfs(map); holenum=sqrt(P_P)/3+2.5*max+2*BoardTransitions+7*BuriedHoles+2*Bfs+Wells; if (pop&&eRound>1) holenum-=W12; #ifndef _BOTZONE_ONLINE if (CONDITION) fprintf(DEBUG,">_<%d %d %d %d\n",x,y,o,deepth); if (CONDITION){ for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"\n")) for (int x=1;x<=MAPWIDTH;x++) fprintf(DEBUG,"%c",map[y][x]?'#':'.'); fprintf(DEBUG,"%d %d %d %d %d %lf\n",x,y,o,deepth,type,holenum); fprintf(DEBUG,"ErodedPieceCellsMetric:%d\n",ErodedPieceCellsMetric); fprintf(DEBUG,"BoardTransitions:%d\n",BoardTransitions); fprintf(DEBUG,"BuriedHoles:%d\n",BuriedHoles); fprintf(DEBUG,"Wells:%d\n\n",Wells); } #endif //printf("%d %d %d %d\n",x,y,o,deepth); if (deepth){ if (deepth==1){ double forfuture=-INF,test; for (int i=0;i<7;i++) if (myCount[i]){ typeCountForColor[currBotColor][i]++; if ((test=work(map,i,deepth-1,forfuture,currBotColor,pop?eRound+1:0))>forfuture) forfuture=test; typeCountForColor[currBotColor][i]--; } if (forfuture>=INF-1) return INF-1; holenum+=forfuture*W4; //printf("%d %d %d %lf %lf\n",x,y,o,holenum,forfuture); }else{ int type_num=Type_num; int TY[type_num]; double Work[type_num]; double forfuture=-INF,test; for (int j=0;j<type_num;j++) Work[j]=-INF; for (int i=0,j;i<7;i++) if (myCount[i]){ typeCountForColor[currBotColor][i]++; test=work(map,i,0,forfuture,currBotColor,pop?eRound+1:0); for (j=0;j<type_num;j++) if (Work[j]<test) break; if (j<type_num){ for (int k=type_num-1;k>j;k--) TY[k]=TY[k-1],Work[k]=Work[k-1]; Work[j]=test;TY[j]=i; } typeCountForColor[currBotColor][i]--; } for (int i=0;i<type_num;i++) if (Work[i]>-INF+1){ if (Work[0]<0){ if (Work[i]<Work[0]*1.05-1) break; }else if (Work[i]<Work[0]*0.95-1) break; typeCountForColor[currBotColor][TY[i]]++; if ((test=work(map,TY[i],deepth-1,forfuture,currBotColor,pop?eRound+1:0))>forfuture) forfuture=test; typeCountForColor[currBotColor][TY[i]]--; } /*printf("%d\n",type_num); for (int i=0;i<type_num;i++) printf("%lf ",Work[i]);puts(""); */ if (forfuture>=INF-1) return INF-1; holenum+=forfuture*W4; //printf("%d %d %d %lf %lf\n",x,y,o,holenum,forfuture); } } holenum-=ErodedPieceCellsMetric; return holenum; } double work(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int deepth,double forfuture,bool currBotColor,int eRound){ bool bo[MAPHEIGHT+2][MAPWIDTH+2][4]; int fx=-1,fy,fo,i,work_num=Work_num; /*fprintf(DEBUG,">_<%d\n",ty); for (int y=MAPHEIGHT;y;y--,fprintf(DEBUG,"\n")) for (int x=1;x<=MAPWIDTH;x++) fprintf(DEBUG,"%c",_map[y][x]?'#':'.');*/ double MMH=INF,test; Util::init(_map,bo,ty); if (deepth){ double work[work_num]; int XX[work_num],YY[work_num],OO[work_num]; for (i=0;i<work_num;i++) work[i]=INF; for (int y = 1; y <= MAPHEIGHT; y++) for (int x = 1; x <= MAPWIDTH; x++) for (int o = 0; o < 4; o++) if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]){ test=Mavis(_map,ty,x,y,o,0,MMH,currBotColor,eRound); for (i=0;i<work_num;i++) if (test<work[i]) break; if (i==work_num) continue; for (int j=work_num-1;j>i;j--) work[j]=work[j-1],XX[j]=XX[j-1],YY[j]=YY[j-1],OO[j]=OO[j-1]; work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o; } for (int i=0;i<work_num;i++) if (work[i]<INF-1){ if (work[0]<0){ if (work[i]>work[0]*0.8+10) break; }else if (work[i]>work[0]*1.2+10) break; if ((test=Mavis(_map,ty,XX[i],YY[i],OO[i],deepth,MMH,currBotColor,eRound))<MMH){ fx=XX[i];fy=YY[i];fo=OO[i]; MMH=test; if (MMH<forfuture) return MMH; } } if (fx==-1) fx=XX[0],fy=YY[0],fo=OO[0]; }else{ for (int y = 1; y <= MAPHEIGHT; y++) for (int x = 1; x <= MAPWIDTH; x++) for (int o = 0; o < 4; o++) if (GO[ty][o]&&onGround(_map,ty,x,y,o)&&bo[y][x][o]&&(test=Mavis(_map,ty,x,y,o,0,INF,currBotColor,eRound))<MMH){ fx=x; fy=y; fo=o; MMH=test; if (MMH<forfuture) return MMH; } } finalX=fx;finalY=fy;finalO=fo; //printf("%d %d %d %d %d\n",ty,deepth,fx,fy,fo); //fprintf(DEBUG,"===================================%d %d %d %d %lf\n",ty,finalX,finalY,finalO,MMH); return MMH; } double gain(int _map[MAPHEIGHT+2][MAPWIDTH+2],int x,int y,int o,int ty,int _ty,bool currBotColor,int DEEPTH){ int map[MAPHEIGHT+2][MAPWIDTH+2]; for (int _y=0;_y<=MAPHEIGHT+1;_y++) for (int _x=0;_x<=MAPWIDTH+1;_x++) map[_y][_x]=_map[_y][_x]; for (int i=0;i<4;i++){ int tmpX=x+blockShape[ty][o][2*i]; int tmpY=y+blockShape[ty][o][2*i+1]; map[tmpY][tmpX]=3; } int pop=0; for (int _y=1;_y<=MAPHEIGHT;_y++){ int _x=1; for (_x=1;_x<=MAPWIDTH;_x++) if (!map[_y][_x]) break; if (_x==MAPWIDTH+1){ pop++; for (_x=1;_x<=MAPWIDTH;_x++) map[_y][_x]=-1; } } for (int _x=1;_x<=MAPWIDTH;_x++){ int p=1; for (int i=1;i<=MAPHEIGHT;i++) if (map[i][_x]!=-1) map[p][_x]=map[i][_x],p++; for (;p<=MAPHEIGHT;p++) map[p][_x]=0; } return work(map,_ty,DEEPTH,INF,currBotColor,pop?elimCombo[currBotColor]+1:0); } int blockForEnemy(int _map[MAPHEIGHT+2][MAPWIDTH+2],int ty,int DEEPTH){ int minCount = 99,mmh=-1; for (int i = 0; i < 7; i++) if (typeCountForColor[enemyColor][i] < minCount) minCount = typeCountForColor[enemyColor][i]; bool bo[MAPHEIGHT+2][MAPWIDTH+2][4]; int fx=-1,fy,fo,i,work_num=Work_num; double MMH=INF,test; Util::init(_map,bo,ty); double work[work_num]; int XX[work_num],YY[work_num],OO[work_num]; for (i=0;i<work_num;i++) work[i]=INF; for (int y = 1; y <= MAPHEIGHT; y++) for (int x = 1; x <= MAPWIDTH; x++) for (int o = 0; o < 4; o++) if (onGround(_map,ty,x,y,o)&&bo[y][x][o]){ test=Mavis(_map,ty,x,y,o,0,MMH,currBotColor,elimCombo[currBotColor]); for (i=0;i<work_num;i++) if (test<work[i]) break; if (i==work_num) continue; for (int j=work_num-1;j>i;j--) work[j]=work[j-1],XX[j]=XX[j-1],YY[j]=YY[j-1],OO[j]=OO[j-1]; work[i]=test;XX[i]=x;YY[i]=y;OO[i]=o; } double _mmh=-INF; for (int _ty=0;_ty<7;_ty++) if (typeCountForColor[enemyColor][_ty]+1-minCount<=2){ typeCountForColor[enemyColor][_ty]++; double _MMH=INF; for (int i=0;i<work_num;i++) if (work[i]<INF-1){ if (work[0]<0){ if (work[i]>work[0]*0.8+10) break; }else if (work[i]>work[0]*1.2+10) break; if ((test=gain(_map,XX[i],YY[i],OO[i],ty,_ty,enemyColor,DEEPTH))<_MMH){ _MMH=test; //printf("===%d %lf\n",i,test); } } if (_MMH>_mmh) _mmh=_MMH,mmh=_ty; //printf("%d %lf\n",_ty,_MMH); typeCountForColor[enemyColor][_ty]--; } return mmh; } int main(){ #ifndef _BOTZONE_ONLINE freopen("a.in","r",stdin); //freopen("a.out","w",stdout); #endif // 加速输入 istream::sync_with_stdio(false); srand(time(NULL)); init(); cin >> turnID; // 先读入第一回合,得到自己的颜色 // 双方的第一块肯定是一样的 cin >> blockType >> currBotColor; enemyColor = 1 - currBotColor; nextTypeForColor[0] = blockType; nextTypeForColor[1] = blockType; typeCountForColor[0][blockType]++; typeCountForColor[1][blockType]++; // 然后分析以前每回合的输入输出,并恢复状态 // 循环中,color 表示当前这一行是 color 的行为 // 平台保证所有输入都是合法输入 for (int i = 1; i < turnID; i++){ int currTypeForColor[2] = { nextTypeForColor[0], nextTypeForColor[1] }; int x, y, o; // 根据这些输入输出逐渐恢复状态到当前回合 // 先读自己的输出,也就是自己的行为 // 自己的输出是自己的最后一步 // 然后模拟最后一步放置块 cin >> blockType >> x >> y >> o; // 我当时把上一块落到了 x y o! Tetris myBlock(currTypeForColor[currBotColor], currBotColor); myBlock.set(x, y, o).place(); // 我给对方什么块来着? typeCountForColor[enemyColor][blockType]++; nextTypeForColor[enemyColor] = blockType; // 然后读自己的输入,也就是对方的行为 // 裁判给自己的输入是对方的最后一步 cin >> blockType >> x >> y >> o; // 对方当时把上一块落到了 x y o! Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor); enemyBlock.set(x, y, o).place(); // 对方给我什么块来着? typeCountForColor[currBotColor][blockType]++; nextTypeForColor[currBotColor] = blockType; // 检查消去 Util::eliminate(0); Util::eliminate(1); // 进行转移 Util::transfer(); } // 做出决策(你只需修改以下部分) // 遇事不决先输出(平台上编译不会输出) work(gridInfo[currBotColor],blockType,M_DEEP,-INF,currBotColor,elimCombo[currBotColor]); _finalX=finalX;_finalY=finalY;_finalO=finalO; int currTypeForColor[2] = { nextTypeForColor[0], nextTypeForColor[1] }; Tetris myBlock(currTypeForColor[currBotColor], currBotColor); myBlock.set(_finalX,_finalY,_finalO).place(); #ifndef _BOTZONE_ONLINE Util::printField(); #endif /*work(gridInfo[enemyColor],nextTypeForColor[enemyColor],1,-INF); Tetris enemyBlock(currTypeForColor[enemyColor], enemyColor); enemyBlock.set(finalX,finalY,finalO).place(); //Util::printField(); Util::eliminate(0); Util::eliminate(1); Util::transfer(); */ cout << blockForEnemy(gridInfo[enemyColor],nextTypeForColor[enemyColor],E_DEEP)<< " " << _finalX << " " << _finalY << " " << _finalO<<endl; }