<初学者>求大神指教 俄罗斯方块旋转的 逻辑和java代码

yuchen_8 2016-08-09 12:30:13
<初学者>求大神指教 俄罗斯方块旋转的 逻辑和程序。
琢磨了半天都没想出来,难道真的要一个个列出来吗?
...全文
708 5 打赏 收藏 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
weixin_44153424 2018-12-18
  • 打赏
  • 举报
回复

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Label;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.Random;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;

class Block//方块父类
{
private int x,y;//方块的坐标;
protected int type;//方块的形态,横着是0,竖着是1
protected int[][] bk;//横状方块
protected int[][] kb;//竖状方块


protected Block()//创建坐标,类型
{
Random random=new Random();
x=random.nextInt(7);//随机方块出现的位置
y=0;
type=random.nextInt(2);//随机方块类型(横,竖)
}


//获取方块坐标
public int getX()
{
return x;
}

public int getY()
{
return y;
}

//获取方块类型
public int getType()
{
return type;
}

//获取数组宽度和高度
public int getwidth()
{
return getBlock(type)[0].length;
}

public int getheigth()
{
return getBlock(type).length;
}

//根据类型返回状态方块
public int[][] getBlock(int type)
{
if(type==0)
return bk;
else
return kb;
}

public void Down()//下降方法
{
y++;
}

public void Left()//左移方法
{
x--;
}

public void Right()//右移方法
{
x++;
}

public void Turn()//旋转方法
{

}



}
//长条方块类
class Strip extends Block
{
private final int w=4,h=1;

Strip()
{
super();
bk=new int[h][w];
kb=new int[w][h];
for(int i=0;i<w;i++)
{
bk[h-1][i]=1;
kb[i][h-1]=1;
}
}

public void Turn()//重写父类旋转方法
{
if(type==0)
type=1;
else
type=0;
}

}


//正方形方块类
class Square extends Block
{
final private int w=2,h=2;

Square()
{
super();
bk=new int[h][w];
kb=new int[w][h];
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
{
bk[i][j]=1;
kb[j][i]=1;
}
}

}
//Z字方块1类
class Z1 extends Block
{
final private int w=3,h=2;

Z1()
{
super();
bk=new int[h][w];
kb=new int[w][h];
bk[0][0]=bk[0][1]=bk[1][1]=bk[1][2]=1;
kb[2][0]=kb[1][0]=kb[1][1]=kb[0][1]=1;
}

public void Turn()
{
if(type==0)
type=1;
else
type=0;
}

}

//Z字方块2类
class Z2 extends Block
{
final private int w=3,h=2;

Z2()
{
super();
bk=new int[h][w];
kb=new int[w][h];
bk[0][2]=bk[0][1]=bk[1][1]=bk[1][0]=1;
kb[0][0]=kb[1][0]=kb[1][1]=kb[2][1]=1;
}

public void Turn()
{
if(type==0)
type=1;
else
type=0;
}

}


//三角方块类
class triangle extends Block
{
final private int w=3,h=2;

triangle()
{
super();
bk=new int[h][w];
kb=new int[w][h];
triangle(type);
}

//随机创建四种三角形状的一种
private void triangle(int type)
{
Random r=new Random();
if(type==0)
{
if(r.nextInt(2)==0)
bk[0][1]=bk[1][0]=bk[1][1]=bk[1][2]=1;
else
bk[1][1]=bk[0][0]=bk[0][1]=bk[0][2]=1;
}
else
{
if(r.nextInt(2)==0)
kb[1][0]=kb[0][1]=kb[1][1]=kb[2][1]=1;
else
kb[1][1]=kb[0][0]=kb[1][0]=kb[2][0]=1;
}

}

//旋转方法利用数组的特性赋值
public void Turn()
{
if(type==0)
{
for(int i=0;i<h;i++)
for(int j=0;j<w;j++)
kb[j][h-i-1]=bk[i][j];
type=1;
}
else
{
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
bk[j][w-i-1]=kb[i][j];
type=0;
}
}

}

//不规则方块类1
class irregular1 extends Block
{
final private int w=3,h=2;

irregular1()
{
super();
bk=new int[h][w];
kb=new int[w][h];
irregular1(type);
}

//随机创建四种状的一种
private void irregular1(int type)
{
Random r=new Random();
if(type==0)
{
if(r.nextInt(2)==0)
bk[0][0]=bk[1][0]=bk[1][1]=bk[1][2]=1;
else
bk[1][2]=bk[0][0]=bk[0][1]=bk[0][2]=1;
}
else
{
if(r.nextInt(2)==0)
kb[2][0]=kb[0][1]=kb[1][1]=kb[2][1]=1;
else
kb[0][1]=kb[0][0]=kb[1][0]=kb[2][0]=1;
}

}

//旋转方法利用数组的特性赋值
public void Turn()
{
if(type==0)
{
for(int i=0;i<h;i++)
for(int j=0;j<w;j++)
kb[j][h-i-1]=bk[i][j];
type=1;
}
else
{
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
bk[j][w-i-1]=kb[i][j];
type=0;
}
}

}

//不规则方块类2
class irregular2 extends Block
{
final private int w=3,h=2;

irregular2()
{
super();
bk=new int[h][w];
kb=new int[w][h];
irregular2(type);
}

//随机创建四种状的一种
private void irregular2(int type)
{
Random r=new Random();
if(type==0)
{
if(r.nextInt(2)==0)
bk[0][2]=bk[1][0]=bk[1][1]=bk[1][2]=1;
else
bk[1][0]=bk[0][0]=bk[0][1]=bk[0][2]=1;
}
else
{
if(r.nextInt(2)==0)
kb[0][0]=kb[0][1]=kb[1][1]=kb[2][1]=1;
else
kb[2][1]=kb[0][0]=kb[1][0]=kb[2][0]=1;
}

}

//旋转方法利用数组的特性赋值
public void Turn()
{
if(type==0)
{
for(int i=0;i<h;i++)
for(int j=0;j<w;j++)
kb[j][h-i-1]=bk[i][j];
type=1;
}
else
{
for(int i=0;i<w;i++)
for(int j=0;j<h;j++)
bk[j][w-i-1]=kb[i][j];
type=0;
}
}

}

//游戏主体类
class theGame extends JPanel implements Runnable
{
private int score;//游戏得分
private int speed;//方块下落速度
private int MAX_blockheight;//方块堆积的最大高度
private final int widht=10,height=20,size=30;//面板宽度,高度和大小
private final int[][] board;//游戏面板
private Block[] block;//游戏运行时的方块
private boolean isgameover,iscontinue;//游戏是否结束,游戏是否继续

theGame()
{
board=new int[height][widht];
block=new Block[2];//定义两个方块,一个运行,另一个预览
buildblock();//初始化预览个方块
MAX_blockheight=height-1;//初始化方块堆积最大高度
score=0;
speed=500;
isgameover=false;
iscontinue=true;
this.addKeyListener(new Move());//对面板键盘监听

}

public void Start()//开始方法,由按钮控制
{
Thread run=new Thread(this);
run.start();//创建线程1,游戏开始
}

public void setcontinue(boolean b) //设置是否继续游戏
{
iscontinue=b;
}

//游戏运行线程
public void run()
{
do
{
passblock();//将预览方块传递给运行方块
buildblock();//新建预览方块
PaintNext();//显示预览方块
createblock();//在面板产生方块
while(!collideD())//碰撞检测
{
makeDown(); //方块下落方法

try {
Thread.sleep(speed);//挂起线程,控制方块速度
} catch (InterruptedException e) {
e.printStackTrace();
}

if(!iscontinue)//若不继续,挂起该线程直到点击继续
{

Threadt t=new Threadt();
synchronized(t)
{
try
{
t.start();
t.wait();
}catch(InterruptedException e) {}
}
}
}
create_stable_block();//方块无法下落,固定方块
setMax_ofblockheight();//记录方块堆积的最高高度
score();//计分方法
destoryblock();//销毁方块

}while(!gameover());//检测游戏是否结束

repaint();
}


private void PaintNext() //显示预览方块方法
{
new Nextb(block[1].getBlock(block[1].getType()));//将预览方块数组传递给预览面板类构造对象
newtetris.menu.repaint();//刷新菜单面板
}

private void create_stable_block() //固定方块方法
{
for(int bi=block[0].getY();bi<block[0].getY()+block[0].getheigth();bi++)
for(int bj=block[0].getX();bj<block[0].getX()+block[0].getwidth();bj++)
if(board[bi][bj]==1)
board[bi][bj]=2;
}

private void destoryblock() //销毁方块方法
{
block[0]=null;
System.gc();
}

private void setMax_ofblockheight() //设置方块堆积的最高点
{
if(block[0].getY()<MAX_blockheight)
MAX_blockheight=block[0].getY();
}

private void score() //计分方法
{
int n;
for(int i=height-1;i>=MAX_blockheight;i--)
{
n=0;//计算这行方块数

for(int j=0;j<widht;j++)
{
if(board[i][j]==0)
break;
else
n++;
}

if(n==widht)//判断这行是否布满方块
{
enLine(i);//消去这行
score++;
newtetris.score.setText(""+score);
i+=1;
}
}
}

//消行方法
private void enLine(int x)
{
for(int i=x;i>=MAX_blockheight;i--)
for(int j=0;j<widht;j++)
board[i][j]=board[i-1][j];

MAX_blockheight+=1;
}

private boolean gameover() //判断游戏是否结束方法
{
if(MAX_blockheight<=3)
{
isgameover=true;
return true;
}
return false;
}

private boolean collideD() //下落碰撞检测
{
if(block[0].getY()+block[0].getheigth()>=height)//检测是否最低点
return true;

//检测下方是否有方块
for(int i=block[0].getY()+block[0].getheigth()-1;i>=0;i--)
for(int j=block[0].getX()+block[0].getwidth()-1;j>=0;j--)
if(board[i][j]==1&&board[i+1][j]==2)
return true;
return false;
}

private void makeDown() //下降方法
{

erasureblock();//擦除原方块
block[0].Down();//改变y值使下降
createblock();//产生新方块
repaint();
}

//在新坐标上产生一个方块
private void createblock()
{
for(int bi=block[0].getY(),i=0;i<block[0].getheigth();i++,bi++)
for(int bj=block[0].getX(),j=0;j<block[0].getwidth();j++,bj++)
if(board[bi][bj]==0&&block[0].getBlock(block[0].getType())[i][j]==1)
board[bi][bj]=block[0].getBlock(block[0].getType())[i][j];
}

//擦除原来坐标上的方块
private void erasureblock()
{
for(int bi=block[0].getY();bi<block[0].getY()+block[0].getheigth();bi++)
for(int bj=block[0].getX();bj<block[0].getX()+block[0].getwidth();bj++)
if(board[bi][bj]==1)
board[bi][bj]=0;


}

private void passblock() //将预览方块传给运行方块方法
{
block[0]=block[1];

}

private void buildblock() //创建预览方块方法
{
Random r=new Random();
switch(r.nextInt(7))//随机创建七种方块
{
case 0:block[1]=new Strip();break;
case 1:block[1]=new Square();break;
case 2:block[1]=new Z1();break;
case 3:block[1]=new Z2();break;
case 4:block[1]=new triangle();break;
case 5:block[1]=new irregular1();break;
case 6:block[1]=new irregular2();break;

}


}


public void makeTurn() //旋转方法
{
erasureblock();//擦除原方块
block[0].Turn();//调用方块的旋转方法
createblock();//产生新方块
repaint();
}

public boolean collideT() //旋转碰撞检测
{

for(int bi=block[0].getY()+block[0].getwidth()-1;bi>=block[0].getY();bi--)
for(int bj=block[0].getX()+block[0].getheigth()-1;bj>=block[0].getX();bj--)
if(board[bi][bj]==2)
return true;

return false;
}

public void makeRight() //右移方法
{
erasureblock();//擦除原方块
block[0].Right();//调用方块的右移方法
createblock();//产生新方块
repaint();
}

public boolean collideR() //右移碰撞检测
{
if(block[0].getX()+block[0].getwidth()>=widht)
return true;

for(int bj=block[0].getX()+block[0].getwidth()-1;bj>=block[0].getX();bj--)
for(int bi=block[0].getY();bi<block[0].getY()+block[0].getheigth();bi++)
if(board[bi][bj]==1&&board[bi][bj+1]==2)
return true;

return false;
}

public void makeLeft() //左移方法
{
//和前面一样,不写了
erasu
逗泥丸的平方 2016-08-10
  • 打赏
  • 举报
回复
引用 3 楼 yuchen_8 的回复:
[quote=引用 2 楼 qq_35209952 的回复:] 想写也可以 .. 不过首先要定义重心,然后可以写一个公共的旋转
3q 如何定义一个重心呢?[/quote] 呃 .. 看你的方块是怎样实现的了.. 重心只是说围绕哪个点进行旋转... 90度 其实就是在重心的基础上进行一种坐标的变换而已. 嗯.. 可以参照一下矩阵转置,这种转置就是以矩阵中心为重心的情况. http://www.2cto.com/kf/201303/197201.html
yuchen_8 2016-08-10
  • 打赏
  • 举报
回复
引用 2 楼 qq_35209952 的回复:
想写也可以 .. 不过首先要定义重心,然后可以写一个公共的旋转
3q 如何定义一个重心呢?
NewMoons 2016-08-09
  • 打赏
  • 举报
回复
一共七种固定类型的方块,有的类型如四方块不存在旋转问题,总的旋转方案不超过28种。有必要写算法吗? 除非类型不是固定的(那也不叫俄罗斯方块了),否则真没必要写旋转算法来计算旋转后的位置模型。 没真正做过俄罗斯方块,仅供参考。
逗泥丸的平方 2016-08-09
  • 打赏
  • 举报
回复
想写也可以 .. 不过首先要定义重心,然后可以写一个公共的旋转

62,620

社区成员

发帖
与我相关
我的任务
社区描述
Java 2 Standard Edition
社区管理员
  • Java SE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧