俄罗斯方块机器人2
2011-02-15 11:50
253 查看
以前写的俄罗斯方块机器人程序只找当前图形的最佳摆放位置,而没有考虑当前图形对下一个图形摆放的影响,这回我在原来的基础上加入了这个功能,效果比较明显,在一般情况下(就是不是特别虽的情况下)可以消超过100行,但随机生成的图形特别难摆我也就没招了。。
PS:俄罗斯方块我玩的不好,写出的程序也就是把我玩俄罗斯方块的技巧实现一下,我的技巧是,尽量不留空,尽量往低放,尽量消行。如果我和这个程序对战,我肯定玩不过它。。。
编写环境:VC++ 6.0
PS:俄罗斯方块我玩的不好,写出的程序也就是把我玩俄罗斯方块的技巧实现一下,我的技巧是,尽量不留空,尽量往低放,尽量消行。如果我和这个程序对战,我肯定玩不过它。。。
编写环境:VC++ 6.0
#include<iostream> #include<conio.h> #include<windows.h> #include <time.h> #pragma comment(lib, "winmm.lib") using namespace std; #define MAPSIZEH 20 #define MAPSIZEL 15 char GRA[24][4][4]= { {0,0,0,0,0,1,1,0,0,1,1,0,0,0,0,0}, /*小田字格*/ {0,0,0,0,0,0,0,0,1,1,1,1,0,0,0,0}, /*横*/ {0,1,0,0,0,1,0,0,0,1,0,0,0,1,0,0}, /*竖*/ {0,0,0,0,0,1,0,0,1,1,1,0,0,0,0,0}, /*上土*/ {0,0,0,0,0,1,0,0,0,1,1,0,0,1,0,0}, /*右土*/ {0,0,0,0,0,0,0,0,1,1,1,0,0,1,0,0}, /*下土*/ {0,0,0,0,0,1,0,0,1,1,0,0,0,1,0,0}, /*左土*/ {0,0,0,0,0,1,0,0,0,1,1,0,0,0,1,0}, /*Z*/ {0,0,0,0,0,1,1,0,1,1,0,0,0,0,0,0}, /*Z*/ {0,0,0,0,0,0,1,0,0,1,1,0,0,1,0,0}, /*Z*/ {0,0,0,0,1,1,0,0,0,1,1,0,0,0,0,0}, /*Z*/ {0,0,0,0,0,1,1,0,0,0,1,0,0,0,1,0}, /*-|*/ {0,0,0,0,0,0,1,0,1,1,1,0,0,0,0,0}, /*__|*/ {0,1,0,0,0,1,0,0,0,1,1,0,0,0,0,0}, /*||_*/ {0,0,0,0,0,1,1,1,0,1,0,0,0,0,0,0}, /*|--*/ {0,0,0,0,0,1,1,0,0,1,0,0,0,1,0,0}, /*||-*/ {0,0,0,0,1,1,1,0,0,0,1,0,0,0,0,0}, /*--|*/ {0,0,1,0,0,0,1,0,0,1,1,0,0,0,0,0}, /*_||*/ {0,0,0,0,0,1,0,0,0,1,1,1,0,0,0,0}, /*|__*/ {0,0,0,0,0,1,1,1,0,1,1,1,0,1,1,1}, /*超级大田*/ {0,1,1,0,0,1,1,0,0,1,1,0,0,1,1,0}, /*大竖*/ {0,0,0,0,1,1,1,1,1,1,1,1,0,0,0,0}, /*大横*/ {0,0,0,0,0,1,0,0,1,1,1,0,0,1,0,0}, /*十*/ {0,0,0,0,0,1,1,1,0,1,0,1,0,1,1,1}, /*空心大田*/ }; char MAP[MAPSIZEH][MAPSIZEL]; int STARTX,STARTY/*起始XY坐标*/,TYPE/*当前图形类型*/,NEXTTYPE/*下一个图形*/,SOCER/*当前分数*/,TURN[24]={0,2,1,4,5,6,3,8,7,10,9,12,13,14,11,16,17,18,15,19,21,20,22,23}; /*旋转状态跳转*/ struct move { int x,y; }move[4]={0,-1,0,1,1,0,0,0}; /*左右下和不动,不动的用于判定方块是否能旋转*/ bool decidemove(int type,int dis) /*判断方块是否能够移动或旋转*/ { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(GRA[type][i][j]) { if(STARTX+i+move[dis].x<0||STARTX+i+move[dis].x>=MAPSIZEH||STARTY+j+move[dis].y<0||STARTY+j+move[dis].y>=MAPSIZEL||MAP[STARTX+i+move[dis].x][STARTY+j+move[dis].y]==1) return false; } return true; } void lockinmap(int s) /*将方块固定在地图上*/ { int i,j; for(i=0;i<4;i++) for(j=0;j<4;j++) if(GRA[TYPE][i][j]) MAP[STARTX+i][STARTY+j]=s; } void moving(int type,int dis) /*将方块在屏幕上移动*/ { lockinmap(0); /*将MAP中的'2'置为0*/ STARTX+=move[dis].x; STARTY+=move[dis].y; /*移动方块*/ lockinmap(2); } void gotoxy(int x,int y) /*移动光标*/ { COORD C; C.X = x; C.Y = y; SetConsoleCursorPosition(GetStdHandle(STD_OUTPUT_HANDLE),C); } void show() /*显示屏*/ { gotoxy(0,0); int i,j; for(i=0;i<MAPSIZEH;i++,cout<<endl) for(j=0;j<MAPSIZEL;j++) if(MAP[i][j]) cout<<"■"; else cout<<" "; gotoxy(MAPSIZEL*2+4,2); for(i=0;i<4;i++,gotoxy(MAPSIZEL*2+4,2+i)) for(j=0;j<4;j++) if(GRA[NEXTTYPE][i][j]) cout<<"■"; else cout<<" "; gotoxy(MAPSIZEL*2+4,2+10); cout<<" SCORE "; gotoxy(MAPSIZEL*2+4,2+12); cout<<" "<<SOCER; gotoxy(MAPSIZEL*3+1,MAPSIZEH); } void creat() /*生成随机方块*/ { STARTX=0; STARTY=MAPSIZEL/2-1; TYPE=NEXTTYPE; srand((unsigned)time(NULL)+TYPE); NEXTTYPE=rand()%19; /*生成随机数*/ if(decidemove(TYPE,3)==false) { system("cls"); cout<<" GAME END"<<endl<<"YOUR SOCER IS "; PlaySound("end.wav",NULL,SND_ALIAS|SND_ASYNC); Sleep(2000); cout<<SOCER<<endl; system("pause"); exit(0); } moving(TYPE,3); } void check() /*判定消行和记分函数*/ { int i,j,res=0,sum; for(i=MAPSIZEH-1;i>-1;i--) { for(j=MAPSIZEL-1,sum=0;j>-1;j--) sum+=MAP[i][j]; if(sum==MAPSIZEL) /*如果发现满行则消行*/ { res++; int k=i,s; for(;k>0;k--) for(s=0;s<MAPSIZEL;s++) MAP[k][s]=MAP[k-1][s]; memset(MAP,0,sizeof(char)*MAPSIZEL); i++; } } if(res) PlaySound("AK47A.wav",NULL,SND_ALIAS|SND_ASYNC); else PlaySound("oned.wav",NULL,SND_ALIAS|SND_ASYNC); SOCER+=100*res*res; /*消行分数计算*/ } void OnTime() { if(true==decidemove(TYPE,2)) { moving(TYPE,2); } else { lockinmap(1); check(); creat(); } show(); } void operate(char op) /*控制方块移动函数*/ { if(op=='a'||op=='A') { if(true==decidemove(TYPE,0)) { moving(TYPE,0); show();} } else if(op=='d'||op=='D') { if(true==decidemove(TYPE,1)) { moving(TYPE,1); show(); } } else if(op=='w'||op=='W') { if(decidemove(TURN[TYPE],3)==true) { lockinmap(0); TYPE=TURN[TYPE]; moving(TYPE,3); show(); PlaySound("sound1.wav",NULL,SND_ALIAS|SND_ASYNC); } } else if(op=='s'||op=='S') { if(true==decidemove(TYPE,2)) moving(TYPE,2); else { lockinmap(1); check(); creat(); } show(); } else if(op==0x20) { while(true==decidemove(TYPE,2)) moving(TYPE,2); lockinmap(1); check(); creat(); show(); } } void first() /*初始化界面*/ { memset(MAP,0,sizeof(MAP)); SOCER=0; srand((unsigned)time(NULL)); NEXTTYPE=rand()%20; creat(); int i; show(); for(i=0;i<MAPSIZEH;i++) { gotoxy(MAPSIZEL*2,i); cout<<"┃"; gotoxy(MAPSIZEL*3,i); cout<<"┃"; } gotoxy(0,MAPSIZEH); for(i=0;i<MAPSIZEL*1.5;i++) cout<<"━"; } void BOT() { int x,y,savetype,savex,savey,temp,temp2,max,max2,maxl,maxtype,i,j,k,mapnum[4],l,l2,savetype2; while(1) /*开始自动下方块*/ { max=0; savetype=TYPE; x=STARTX; y=STARTY; maxl=STARTY; maxtype=TYPE; for(;;) /*遍历当前图形的几种旋转图形*/ { while(decidemove(TYPE,0)==true) STARTY--; for(;;STARTX=x,STARTY++) /*往右移动的所有情况*/ { while(decidemove(TYPE,2)==true) /*将图形下到底*/ STARTX++; memset(mapnum,0,sizeof(mapnum)); for(i=0;i<4&&STARTX+i<MAPSIZEH;i++) /*统计STARTX开始的那四行原来有的方块数*/ for(j=0;j<MAPSIZEL;j++) if(MAP[STARTX+i][j]==1) mapnum[i]++; for(i=0;i<4&&STARTX+i<MAPSIZEH;i++) /*如果将当前图形插入后每行几个块*/ for(j=0;j<4;j++) if(GRA[TYPE][i][j]) mapnum[i]++; for(i=0,l=0,temp=0;i<4;i++) /*开始记分*/ for(j=0;j<4;j++) if(GRA[TYPE][i][j]) { for(k=1;STARTX+i+k<MAPSIZEH;k++) if(MAP[STARTX+i+k][STARTY+j]==0&&(i+k>3||(i+k<4&&GRA[TYPE][i+k][j]==0))) l++; else { temp+=1; break; } k=i; } if(l<8) temp-=l*10; temp+=(k+STARTX)*10; for(i=0,k=0;i<4;i++) /*能消一行就加1000分*/ if(mapnum[i]==MAPSIZEL) k++; temp+=1000*k; /*遍历下一个图形的4种情况*/ for(i=0;i<4;i++) /*将当前图形固定在地图上*/ for(j=0;j<4;j++) if(GRA[TYPE][i][j]) MAP[STARTX+i][STARTY+j]=1; savetype2=TYPE; TYPE=NEXTTYPE; savey=STARTY; savex=STARTX; STARTX=x; STARTY=y; for(max2=0;;) /*遍历当前图形的几种旋转图形*/ { while(decidemove(TYPE,0)==true) STARTY--; for(;;STARTX=x,STARTY++) /*往右移动的所有情况*/ { while(decidemove(TYPE,2)==true) /*将图形下到底*/ STARTX++; memset(mapnum,0,sizeof(mapnum)); for(i=0;i<4&&STARTX+i<MAPSIZEH;i++) /*统计STARTX开始的那四行原来有的方块数*/ for(j=0;j<MAPSIZEL;j++) if(MAP[STARTX+i][j]==1) mapnum[i]++; for(i=0;i<4&&STARTX+i<MAPSIZEH;i++) /*如果将当前图形插入后每行几个块*/ for(j=0;j<4;j++) if(GRA[TYPE][i][j]) mapnum[i]++; for(i=0,l2=0,temp2=0;i<4;i++) /*开始记分*/ for(j=0;j<4;j++) if(GRA[TYPE][i][j]) { for(k=1;STARTX+i+k<MAPSIZEH;k++) if(MAP[STARTX+i+k][STARTY+j]==0&&(i+k>3||(i+k<4&&GRA[TYPE][i+k][j]==0))) l2++; else { temp2+=1; break; } k=i; } if(l2<8) temp2-=l2*10; temp2+=(k+STARTX)*10; for(i=0,k=0;i<4;i++) /*能消一行就加1000分*/ if(mapnum[i]==MAPSIZEL) k++; temp2+=1000*k; if(temp2>max2) max2=temp2; STARTX=x; if(decidemove(TYPE,1)==false) break; } STARTX=x; STARTY=y; if(decidemove(TURN[TYPE],3)==true) /*如果图形不能旋转就停止,旋转回原图形也停止*/ TYPE=TURN[TYPE]; else break; if(NEXTTYPE==TYPE) break; } /*下一个图形枚举完毕,恢复第一个图形*/ TYPE=savetype2; STARTY=savey; STARTX=savex; for(i=0;i<4;i++) for(j=0;j<4;j++) if(GRA[TYPE][i][j]) MAP[STARTX+i][STARTY+j]=0; /**/ if(temp+max2>max) { maxl=STARTY; maxtype=TYPE; max=temp+max2; } STARTX=x; if(decidemove(TYPE,1)==false) break; } STARTX=x; STARTY=y; if(decidemove(TURN[TYPE],3)==true) /*如果图形不能旋转就停止,旋转回原图形也停止*/ TYPE=TURN[TYPE]; else break; if(savetype==TYPE) break; } /*找到位置后开始控制*/ TYPE=savetype; STARTX=x; STARTY=y; while(TYPE!=maxtype) /*旋转到目标图形*/ { operate('w'); Sleep(20); /*调整速度,可以将其注释掉提高速度*/ } char o='a'; if(maxl>STARTY) o='d'; while(STARTY!=maxl) /*移动到目标列*/ { operate(o); Sleep(20); /*调整速度,可以将其注释掉提高速度*/ } operate(0x20); // Sleep(100); } } int main() { first(); /*初始化界面*/ while(1) /*进入游戏*/ BOT(); return 0; }
相关文章推荐
- 俄罗斯方块机器人版
- 俄罗斯方块
- C++编写俄罗斯方块游戏
- 小翼的java开发俄罗斯方块(1)
- java swing开发俄罗斯方块游戏
- C++控制台实现俄罗斯方块游戏
- 用Python编写一个简单的俄罗斯方块游戏的教程
- lufylegend引擎俄罗斯方块的实现
- ccf2016年4月10日认证考试 俄罗斯方块问题思路
- 俄罗斯方块中方块的旋转变形
- 教你如何在linux操作系统下玩【俄罗斯方块】高清+语音教程
- easyX图形函数库开发的俄罗斯方块游戏(C版本)
- 趣味python编程之经典俄罗斯方块
- [java游戏开发快速入门]俄罗斯方块游戏开发开篇
- QT项目一:俄罗斯方块游戏
- 查色盲俄罗斯方块源码
- JavaScript--js写的俄罗斯方块
- 一个基于Yahoo UI的Ajax俄罗斯方块游戏
- (原创)一种用C#编写俄罗斯方块游戏的方法
- 俄罗斯方块即将完成