这是去年写的第一个小项目(虽然感觉称不上是项目),但毕竟是一次完整的编程过程,当作是编程路上的学习经历发一下好了。 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() //左移方法 { //和前面一样,不写了 erasureblock(); block[0].Left();
createblock(); repaint(); } public boolean collideL() //左移碰撞检测 {
if(block[0].getX()<=0)//是否在最左端 return true; //左边是否有方块 for(int
bj=block[0].getX();bj<block[0].getX()+block[0].getwidth();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; } class
Threadt extends Thread { public void run()//线程2,用来启动线程1 { synchronized(this) {
while(true) { try { Thread.sleep(1000); } catch (Exception e) {}
if(iscontinue)//游戏是否继续 { this.notify(); break; } } } } } class Move extends
KeyAdapter//键盘适配器 { public void keyReleased(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_DOWN)//释放下键,速度变慢 { if(speed==50) speed=500; } }
public void keyPressed(KeyEvent e) {
if(e.getKeyCode()==KeyEvent.VK_LEFT)//按下左键触发事件 { if(!collideL())//是否可以左移
makeLeft();//左移方法 } //以下同上 else if (e.getKeyCode() == KeyEvent.VK_RIGHT) {
if(!collideR()) makeRight(); } else if (e.getKeyCode() == KeyEvent.VK_UP) {
if(!collideT()) makeTurn(); } else if(e.getKeyCode()==KeyEvent.VK_DOWN) {
speed=50; } } } public void paintComponent(Graphics g)//绘制面板 {
super.paintComponent(g); for(int i=0;i<height;i++) { for(int j=0;j<widht;j++) {
switch(board[i][j])//三种型号对应三种颜色 { case 0:g.setColor(Color.BLACK);break;//没有方块
case 1:g.setColor(Color.WHITE);break;//移动中的方块 case
2:g.setColor(Color.GRAY);break;//已固定的方块 } g.fillRect((size+1)*j+15,
(size+1)*i+25, size, size);//画方块 } if(i==4)//方块堆积界限 { g.setColor(Color.RED);
g.drawLine(15, (size+1)*i+25, (size+1)*10+15, (size+1)*i+25); } }
if(isgameover)//游戏结束则打印“Game Over” { Font lose=new Font("黑体",Font.BOLD,50);
g.setFont(lose); g.setColor(Color.RED); g.drawString("Game Over", 50, 250); } }
} class Nextb extends JPanel//预览面板类 { int Size; private static int[][]
paint;//预览方块 Nextb() { Size=40; paint=null; } Nextb(int[][] p)//构造预览方块 {
Size=40; paint=new int[p.length][p[0].length]; for(int i=0;i<p.length;i++)
for(int j=0;j<p[0].length;j++) paint[i][j]=p[i][j]; repaint(); } public void
paintComponent(Graphics gg)//绘制面板 { super.paintComponent(gg);//刷新面板,以免重叠
if(paint!=null) { for(int i=0;i<paint.length;i++) for(int
j=0;j<paint[0].length;j++) { gg.setColor(Color.GREEN); if(paint[i][j]==1)
gg.fillRect((Size+1)*j+15, (Size+1)*i+25, Size, Size); } } } } public class
newtetris extends JFrame implements ActionListener//游戏界面类 { theGame
game;//定义一个游戏对象 public static JPanel menu;//定义静态菜单面板 Label
prompt1,prompt2,prompt3; public static TextField score;//计分文本框 TextArea
methon;//玩法介绍文本区 JButton start,replay;//开始,暂停按钮 newtetris() { game=new
theGame(); menu=new JPanel(); Font se=new Font("宋体",Font.BOLD,25); prompt1=new
Label(" 下一个:"); prompt2=new Label(" 得分:"); prompt3=new Label(" 玩法:");
prompt1.setFont(se); prompt2.setFont(se); prompt3.setFont(se); score=new
TextField(3); methon=new TextArea(""+10,8,TextArea.SCROLLBARS_NONE); start=new
JButton("开始"); replay=new JButton("暂停"); menu.setLayout(new
GridLayout(0,2,10,30));//菜单面板使用网格布局 Font sc=new Font("宋体",Font.BOLD,15); Font
sp=new Font("宋体",Font.BOLD,100); methon.setFont(sc);
methon.setText("↑:顺时针旋转90度\n↓:快速下移\n←:向左移动\n→:向右移动");
methon.setEditable(false); methon.setFocusable(false); score.setFont(sp);
score.setText("0"); score.setEditable(false); score.setFocusable(false);
menu.setPreferredSize(new Dimension(400,600)); menu.add(prompt1); menu.add(new
Nextb()); menu.add(prompt2); menu.add(score); menu.add(prompt3);
menu.add(methon); menu.add(start); menu.add(replay);
this.add(menu,BorderLayout.EAST); this.add(game,BorderLayout.CENTER);
start.addActionListener(this); replay.addActionListener(this);
this.setVisible(true); this.setSize(750,700); this.setResizable(false);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); this.setTitle("俄罗斯方块"); }
public void actionPerformed(ActionEvent e) { if(e.getSource()==start) {
game.Start();//开始游戏 game.requestFocusInWindow();//聚焦到游戏面板 } else
if(e.getSource()==replay) { if(e.getActionCommand().equals("暂停")) {
game.setcontinue(false);//设置游戏暂停 replay.setText("继续");//按钮变成继续
game.requestFocusInWindow();//聚焦到面板 } else
if(e.getActionCommand().equals("继续")) { game.setcontinue(true);//设置游戏继续
replay.setText("暂停");//按钮变成暂停 game.requestFocusInWindow();//聚焦到面板 } } } public
static void main(String[] args) { new newtetris(); } }
热门工具 换一换