📄 俄罗斯方块人工智能版.java
字号:
else
nextBlockUpdate(); //刷新下一个方块的数据
}
/*定义绘制下一个方块的函数*/
public void drawNextBlock(Graphics g)
{
g.setColor(colors[typeNext+1]);
for (int j=0; j<4; j++)
{
for (int i=0; i<4; i++)
{
if (block[typeNext][shapeNext][j][i] == 1) //一个方块存储在一个4*4正方形容器里,判断容器里这个位子是否有小方
块
{
g.fill3DRect(frameX+i*16+frameSize*(width+1)+9, frameY+j*16+29, 16, 16, true);
g.fill3DRect(frameX+i*16+frameSize*(width+1)+10, frameY+j*16+30, 14, 14, true);
}
}
}
}
/*更新下一个方块数据的函数*/
public void nextBlockUpdate()
{
type = typeNext; //将下一个方块类型覆盖当前方块类型
shape = shapeNext; //将下一个方块形态覆盖当前方块形态
typeNext = (int) (Math.random() * 7); //初始化下一个方块类型
shapeNext = (int) (Math.random() * 4); //初始化下一个方块形态
x = width / 2 - 1; //初始化方块的坐标
y = 0;
}
/*判断方块下一步的移动是否可行的函数*/
public boolean moveFit(int xmove, int ymove)
{
for (int j=0; j<4; j++)
{
for (int i=0; i<4; i++)
{
if (block[type][shape][j][i] == 1) //一个方块存储在一个4*4正方形容器里,判断容器里这个位子是否有小小方块
{
if (xmove + i < 0 || xmove+i > width - 1 || ymove < 0 || ymove+j > height + 3 || (map[ymove+j][xmove+i]
!= 0))
return false; //不能移动
}
}
}
return true; //能移动
}
/*定义消行的函数*/
public void RemoveRow()
{
int rowSmallBlockNum; //定义一个保存当行已有多少的方块的变量
int reMoveRowNum = 0; //定义一个保存一次共消去多少行的变量
int sc[] = {0,100,300,700,1200}; //定义一个存储分数的数组
for(int j=0; j<4; j++)
{
rowSmallBlockNum = 0;
for (int i=0; i<width; i++)
{
if (map[y+j][i] != 0) //判断地图布局上的此格是否有小方块
rowSmallBlockNum++;
if (rowSmallBlockNum == width) //判断当行格子是否填满了
{
reMoveRowNum++;
for (int jj=y+j; jj>1; jj--)
{
for (int ii=0; ii<width; ii++)
{
map[jj][ii] = map[jj-1][ii]; //把要消去的行的上面所有行的数据向下移动一行
}
}
}
}
}
score += sc[reMoveRowNum]; //根据一次消去几个行的情况而加相应的分数
scoreLevel += sc[reMoveRowNum]; //等级和分数关系
}
/*定义响应键盘的函数*/
public boolean keyDown(Event e, int key)
{
switch (gamestate) //根据游戏状态选择分支程序运行
{
case GameGoing : //游戏进行状态下的分支
if (key == Event.DOWN) //判断是否按下下键
{
fallBlock(); //调用方块下落方法
}
if (key == Event.LEFT) //判断是否按下左键
{
x = moveFit(x-1,y) ? --x : x; //根据周围有没有其它方块或墙壁来判断能否左移
}
if (key == Event.RIGHT) //判断是否按下右键
{
x = moveFit(x+1,y) ? ++x : x; //根据周围有没有其它方块或墙壁来判断能否右移
}
if (key == Event.UP) //判断是否按下上键
{
shapeChange(); //调用方块变形的方法
}
if (key == 'p' || key == 'P') //判断是否按下P键
{
gamestate = GameStop; //设置游戏状态为暂停
}
repaint(); //刷新屏幕
break;
case GameStop : //游戏暂停状态下的分支
if (key == 'p' || key == 'P')
{
gamestate = GameGoing; //设置游戏状态为进行
}
break;
}
return true;
}
/*定义方块变形的函数*/
public void shapeChange()
{
shape++; //方块变形
if (shape == 4) shape = 0; //一个四种形态,变到第五种的时候又变回第一种形态
if (moveFit(x,y)) //根据周围有没有其它方块或墙壁来判断能否变形
{
shape--;
if (shape == -1) shape = 3;
shape++;
if (shape == 4) shape = 0;
}
else
{
shape--; //不能变形,所以把第一行程序变了的形态又变回来
if (shape == -1) shape = 3;
}
}
/*定义方块自动上移的函数*/
public void blockAllUp()
{
upStyle = (byte) (upStyle == 1 ? 0 : 1); //有两种上移方式,变换方式
for (int j=1; j<height+4; j++) //所有方块上移一格
for (int i=0; i<width; i++)
map[j-1][i] = map[j][i];
for (int i=0; i<width; i+=2) //创造底部一行方块
{
map[height+3][i] = (upStyle == 1 ? 0 : 8);
map[height+3][i+1] = (upStyle == 1 ? 8 : 0);
}
blockUpTime = 0; //重置上移的时间
}
/*计算下一个方块的最佳下落方法*/
public void autoPlayNext()
{
int typeCopy = typeNext;
int shapeCopy = shapeNext;
int shapeBestCopy = shapeBest2;
int xCopy, yCopy, xMoveMin, xMoveMax;
int xCopyCopy;
int xMoveMinDown,xMoveMaxDown; //方块下落完成后的最佳坐标
int rowSmallBlockNum, reMoveRowNum; //定义保存当行已有多少的方块的变量和保存一次共消去多少行的变量
int topRowThis = 0, topRowAll; //当行高度和局面的最大高度
int emptyBlockNum; //压在方块下的空格子数目
int valueMax = 0; //当前局面的评估值
int mapCopy[][]=new int [height+4][width]; //声明2个数组保存不同时间局面的数据
int mapCopy2[][]=new int [height+4][width];
int[] aRam = {54, 11, 32, 53, 44, 51, 65, 0, 13, 25, 31, 42, 57, 63,55};
bug = 1; //bug开始发生
for (int i=0; i<width; i++) //保存当前局面
for (int j=0; j<height+4; j++)
mapCopy[j][i] = map[j][i];
type = typeNext;
shape = shapeBest2;
xBest = xBest2;
xblockDownMove = xblockDownMove2;
yblockDownMove = yblockDownMove2;
if (xblockDownMove != xBest) //模拟方块下落
{
x = xblockDownMove;
y = yblockDownMove;
}
else
{
x = xBest;
for (; moveFit(x, y+1); y++){}
}
for (int j=0; j<4; j++) //保存模拟方块下落后的局面
{
for (int i=0; i<4; i++)
{
if (block[type][shape][j][i] == 1) //一个方块存储在一个4*4正方形容器里,判断容器里这个位子是否有小小方块
{
map[y+j][x+i] = 9; //将当前方块的坐标数据存储到布局的点阵里
}
}
}
for (int j=0; j<4; j++) //模拟消行
{
rowSmallBlockNum = 0;
for (int i=0; i<width; i++)
{
if (map[y+j][i] != 0) //判断地图布局上的此格是否有小方块
rowSmallBlockNum++;
if (rowSmallBlockNum == width) //判断当行格子是否填满了
{
for (int jj=y+j; jj>1; jj--)
{
for (int ii=0; ii<width; ii++)
{
map[jj][ii] = map[jj-1][ii]; //把要消去的行的上面所有行的数据向下移动一行
}
}
}
}
}
for (int i=0; i<width; i++) //保存当前局面
for (int j=0; j<height+4; j++)
mapCopy2[j][i] = map[j][i];
boolean hasEmptyBlock = false;
for (int i=0; i<width; i++) //计算局面的高度
{
for (topRowThis=0;topRowThis<height+4;topRowThis++)
{
if (map[topRowThis][i] != 0)
{
break;
}
}
if (topRowThis < height + 3) //计算有多少个空格子
{
for (int j=topRowThis+1; j<height+4; j++)
{
if (map[j][i] == 0) //这儿是一个压在方块下的空的格子
{
hasEmptyBlock = true;
break;
}
}
}
if (hasEmptyBlock) break;
}
for (int iii = (int) (Math.random() * aRa), jjj=0; jjj<adWan; iii++, jjj++)
{
type=typeRam[iii];
for (shape=0; shape<4; shape++)
{
for(xCopy = width/2-1; moveFit(xCopy+1,0); xCopy++){} //计算方块的最大水平位移
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -