为现有的俄罗斯方块程序添加功能package Tetris;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.File;
import java.io.IOException;
import java.util.Random;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.DataLine;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.SourceDataLine;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.JFrame;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
import javax.swing.text.BadLocationException;
public class Tetris extends JFrame {
public static void main(String[] args) throws LineUnavailableException,
UnsupportedAudioFileException, IOException {
Tetris te = new Tetris();
te.setLocationRelativeTo(null);//使当前窗口居中
te.setVisible(true);
music();
}
public static void music(){
// 获取音频输入流
AudioInputStream audioInputStream;
try{audioInputStream=AudioSystem.getAudioInputStream(new File("D:\\可惜没如果.wav"));
// 获取音频编码对象
AudioFormat audioFormat = audioInputStream.getFormat();
// 设置数据输入
DataLine.Info dataLineInfo = new DataLine.Info(SourceDataLine.class,
audioFormat, AudioSystem.NOT_SPECIFIED);
SourceDataLine sourceDataLine = (SourceDataLine) AudioSystem
.getLine(dataLineInfo);
sourceDataLine.open(audioFormat);
sourceDataLine.start();
/*
* 从输入流中读取数据发送到混音器
*/
int count;
byte tempBuffer[] = new byte[1024];
while ((count = audioInputStream.read(tempBuffer, 0, tempBuffer.length)) != -1) {
if (count > 0) {
sourceDataLine.write(tempBuffer, 0, count);
}
}
// 清空数据缓冲,并关闭输入
sourceDataLine.drain();
sourceDataLine.close();
}catch (Exception e) {
e.printStackTrace();
}
}
// 如果在界面中添加了编辑框等会抢占焦点的控件,则需要用下面的代码
// te.requestFocus(true);//让游戏面板获得焦点-抢到键盘的监听
private TetrisPanel tp;
JMenuItem itemPause;
JMenuItem itemContinue;
public Tetris() {
this.setDefaultCloseOperation(EXIT_ON_CLOSE);
this.setLocation(700, 200);
this.setSize(500, 500);
this.setResizable(false);
this.setTitle("俄罗斯方块");
tp = new TetrisPanel();
this.getContentPane().add(tp);
// 添加菜单
JMenuBar menubar = new JMenuBar();
this.setJMenuBar(menubar);
JMenu menuGame = new JMenu("游戏");
menubar.add(menuGame);
// 版本菜单
JMenu menuHelp = new JMenu("帮助");
menubar.add(menuHelp);
JMenuItem m=menuHelp.add("关于游戏");
String s="游戏简介:"
+"是一款益智方块类游戏,\n"
+ "这款游戏最初是由苏联的电脑科学家帕基特诺夫(Alex Pajitnov)于1985年制作的,\n"
+ "作者给了他一个源自希腊字4(tetra)的名字Tetris。\n"
+ "1989年由任天堂发行GameBoy版,推出后风靡全球,\n"
+ "成为益智方块类型游戏中知名度最高的一款。\n"
+ "它看似简单但却变化无穷,上手极其容易,\n"
+ "但是要熟练的掌握其中的操作于摆放技巧,难度却不低。\n"
+"玩法简介:\n"
+"游戏具有一个用于摆放小方块的平面虚拟场地,\n"
+"一组由几个小方块组成的规则形状(Tetromino),\n"
+"游戏每次随机输出一种形状到场地顶部,自动以一定的速度下落,\n"
+"用户在形状的过程中可以控制形状的左右移动及旋转以将形状填充到场地中,\n"
+"直至形状下落至场地底部或被场地中已有的方块阻挡而不能再下落,\n"
+"游戏再次输出一个形状,周而复始。\n"
+"如果这次填充将场地的一行或多行完全填满,则组成这些行的所有方块将被消除,\n"
+"并且以此来换取一定的积分奖励,\n"
+"而未被消除的方块会一直累积,并对后来的形状摆放造成各种影响,\n"
+"如果下一个形状的输出位置已经被未消除的方块所占据,则游戏结束。";
m.addActionListener(new ActionListener(){
public void actionPerformed(ActionEvent e){
JOptionPane.showMessageDialog(null,"俄罗斯方块游戏\n"+s,"关于游戏",JOptionPane.PLAIN_MESSAGE);
}
});
JMenuItem m1=menuHelp.add("关于我们");
String s1="@辽宁建筑职业学院 \n"
+" 信息工程系软件G174\n"
+ " QQ:126888888 \n";
//@辽宁建筑职业学院 QQ:126888888 ";
m1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(null, " 版权所有:"+s1,"关于我们",JOptionPane.PLAIN_MESSAGE);
}
});
JMenuItem itemNew = new JMenuItem(" 新游戏");
itemNew.setActionCommand("new");
itemPause = new JMenuItem("暂停");
itemPause.setActionCommand("pause");
itemContinue = new JMenuItem("继续");
itemContinue.setActionCommand("continue");
itemContinue.setEnabled(false);
menuGame.add(itemNew);
menuGame.add(itemPause);
menuGame.add(itemContinue);
MenuListener menuListener = new MenuListener();
itemNew.addActionListener(menuListener);
itemPause.addActionListener(menuListener);
itemContinue.addActionListener(menuListener);
// 让整个JPrame添加键盘监听
this.addKeyListener(tp.listener);
}
class MenuListener implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// 玩新游戏
if (e.getActionCommand().equals("new")) {
tp.newGame();
}
if (e.getActionCommand().equals("pause")) {
timer.stop();
itemContinue.setEnabled(true);
itemPause.setEnabled(false);
}
if (e.getActionCommand().equals("continue")) {
timer.restart();
itemContinue.setEnabled(true);
itemPause.setEnabled(false);
}
}
}
private Timer timer;
class TetrisPanel extends JPanel {
// 方块的形状:
// 第一维代表方块类型(包括7种:S、Z、L、J、I、O、T)
// 第二维代表旋转次数
// 第三四维代表方块矩阵
// shapes[type][turnState][i] i--> block[i/4][i%4]
int shapes[][][] = new int[][][] {
/*
* 模板{{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,
* 0,0,0,0},{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}, {0,0,0,0,0,0,0,0,0,0,0,0,
* 0,0,0,0}}
*/
// Ι(※把版本Ι中的横条从第1行换到第2行)
{ { 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 } },
// S
{ { 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0 } },
// Z
{ { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 } },
// J
{ { 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// O
{ { 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// L
{ { 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 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, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// T
{ { 0, 1, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 0, 1, 0, 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 } } };
private int blockType;// 方块类型
private int turnState;// 旋转状态
private int x;// 方块的位置x--列的位置--列号
private int y;// 方块的位置y--行的位置--行号
private int map[][] = new int[13][23];// 地图:12列22行。为防止越界,数组开成:13列23行
private int delay = 1000;
public TimerKeyLister listener = new TimerKeyLister();
private int score = 0;// 分数
public TetrisPanel() {
newGame();
nextBlock();
// timer=newTimer(delay, listener);
// timer.start();
}
public void newGame() {
blockType = (int) (Math. random() * 1000) % 7;
turnState = (int) (Math. random() * 1000) % 4;
x=4;
y=0;
for(int i=0;i<12;i++){//走列
for (int j=0;j<21;j++) {//走行
if(i==0||i==11){//3为界面边框的格
map[i][j] = 3;// 按理只要用0和1以外的整数就可以,但这里用3有特殊作用--后面用
} else {
map[i][j] = 0;
}
}
map[i][21] = 3;// 3为界面边框的格
}
if(timer !=null) {
timer.stop();
}
delay=1000;
timer=new Timer(delay,listener);
timer.start();
}
private void nextBlock(){
blockType=(int) (Math.random() * 1000) % 7;
turnState=(int) (Math.random() * 1000) % 4;
x=4;
y=0;
// game Over
if (crash(x, y, blockType, turnState) ==0){
timer.stop();
int option = JOptionPane.showConfirmDialog(this, "Game Over!!, 还敢来吗...");
if (option == JOptionPane.OK_OPTION){
newGame();
} else if (option==JOptionPane.NO_OPTION){
System.exit(0);
}
}
}
private void down() {
if(crash(x, y+1,blockType, turnState)==0) {// 注意,这里用y+1, 是判断块往下掉一格后,map中对应位置是否为堆积块或框架
add(x, y, blockType, turnState);//把当前方块的信息保存到地图
nextBlock();
} else {
y++;
}
repaint();
}
private void left() {
if (x >= 0) {
x -= crash(x - 1, y, blockType, turnState);
}
repaint();
}
private void right() {
if (x < 8) {
x += crash(x + 1, y, blockType, turnState);
}
repaint();
}
private void turn() {
if (crash(x, y, blockType, (turnState + 1) % 4) == 1) {
turnState = (turnState + 1) % 4;
}
repaint();
}
private void add(int x, int y, int blockType, int turnState) {
for (int a = 0; a < 4; a++) {
for (int b = 0; b < 4; b++) {
if (shapes[blockType][turnState][a * 4 + b]==1){
map[x + b +1][y +a] = 1;
}
}
}
tryDelLine();
}
// 消行
private void tryDelLine(){
for (int b = 0; b <21; b++) {
int c=1;
for(int a=0;a<12;a++) {
c &= map[a][b];// 全部是1, c的结果才是1
}
if (c == 1) {// 有一行需要消
// 依次往下移动一行
for (int d = b; d> 0; d--) {
for (int e = 0; e < 11; e++) {
map[e][d] =map[e][d - 1];
}
}
//加分
score += 100;
delay /=1.05;
timer.setDelay(delay);
}
}
}
// 参数例子:4,3,2,3
// 判断有无碰撞
private int crash(int x,int y,int blockType,int turnState) {
for(int a=0;a<4;a++) {
for(int b=0;b<4;b++) {
//if((shapes[blockType][turnState][a*4+b==1]&&map[x+b+1][y+a]==1))||
//(shapes[blockType][turnState][a*4+b]==1&&map[x+b+1][y+a]==3)){
//}
if((shapes[blockType][turnState][a*4+b] & map[x+b+1][y+a])==1){
return 0;// 碰撞
}
}
}
return 1;// 没有碰撞
}
@Override
public void paint(Graphics g){
// blockType = 6;
// turnState = 3;
// x=4;
// y=6;
super.paint(g);//消除残影
g. setColor(new Color(153, 51, 205));
//画当前方块
for(int j=0;j<16;j++){
if(shapes[blockType][turnState][j] == 1) {
g.fillRect((j%4+x+1)*20,(j/4+y)*20,20,20);
g.setColor(Color.cyan);
g.drawRect((j%4+x+1)*20,(j/4+y)*20,20,20);
g.setColor(new Color(153, 51, 205));
}
}
// 画界面框架以及堆积块--整个地图
g.setColor(Color.red);
for (int i=0; i < 12; i++) {//走列
for (int j=0; j < 22;j++) { //走行
if (map[i][j] == 3){
g.drawRect(i*20,j*20,20,20);
} else if (map[i][j] == 1) {
g.fillRect(i*20,j*20,20,20);
g.setColor(Color. GREEN);
g.drawRect(i*20,j*20,20,20);
g.setColor(Color. red);
}
}
}
// 显示分数,同时为版面美观,在界面上再加点东西
// 画方块区右侧部分
g.setColor(Color.red);
g.setFont(new Font("aa",Font.BOLD,25));
g.drawString("score=" + score,300,225);
g.setFont(new Font("aa", Font.PLAIN,20));
g.setColor(Color.blue);
g.drawString("拒绝盗版游戏,",300, 290);
g.drawString("注意自我保护。",300, 310);
g.drawString("谨防受骗上当。",300, 330);
g.drawString("适度游戏益脑,",300, 350);
g.drawString("沉迷游戏伤身。",300, 370);
g.drawString("合理安排时间,",300, 390);
g.drawString("享受健康生活。",300, 410);
}
class TimerKeyLister extends KeyAdapter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
down();
}
@Override
public void keyPressed(KeyEvent e){
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
down();
break;
case KeyEvent.VK_LEFT:
left();
break;
case KeyEvent.VK_RIGHT:
right();
break;
case KeyEvent.VK_UP:
turn();
break;
case KeyEvent.VK_F1:
plug();
case KeyEvent.VK_F2:
time();
}
}
}
public void plug() {
score += 100;
}
public void time() {
delay = 1000;
timer.setDelay(delay);
}
}
}
|
|