这里面用了io流写了等级,会生成一个文件。
如果想学习,可以看我的word文档,已经复制在下方。
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Properties;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.Timer;
public class Tetris extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private TetrisJPanel jPanel;
private JMenuItem menuItem_start, menuItem_stop, menuItem_end,
menuItem_rank, menuItem_help;
private JLabel jLabel_First, jLabel_Second, jLabel_Three;
private JDialog jDialog;
public Tetris() {
super("俄罗斯方块");
addMenu();
// new 对象
this.jPanel = new TetrisJPanel();
// 设置背景,这里有点邪门。。。
// jPanel.setBackground(Color.black);
this.setBackground(Color.white);
this.getContentPane().add(jPanel);
// 初始化排名
writeRankToFile(jPanel.dir, jPanel.filename, 0);
// 为框架添加键盘监听
this.addKeyListener(jPanel.listener);
}
private void addMenu() {
// new 对象
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("菜单");
menuItem_start = new JMenuItem("新建游戏");
menuItem_stop = new JMenuItem("暂停");
menuItem_stop.setActionCommand("stop");
menuItem_rank = new JMenuItem("排名");
menuItem_end = new JMenuItem("结束");
jDialog = new JDialog(this, "^_^排名记录^_^");
jLabel_First = new JLabel();
jLabel_Second = new JLabel();
jLabel_Three = new JLabel();
JMenu menu_help = new JMenu("帮助");
menuItem_help = new JMenuItem("游戏说明");
// 为JDialog加控件
jDialog.setDefaultCloseOperation(HIDE_ON_CLOSE);
jDialog.setVisible(false);
jDialog.setBounds(350, 70, 200, 150);
jDialog.setLayout(new GridLayout(3, 1));
jDialog.add(jLabel_First);
jDialog.add(jLabel_Second);
jDialog.add(jLabel_Three);
// 给菜单项加监听
menuItem_start.addActionListener(this);
menuItem_stop.addActionListener(this);
menuItem_rank.addActionListener(this);
menuItem_end.addActionListener(this);
menuItem_help.addActionListener(this);
// 加工具条和菜单
this.setJMenuBar(menuBar);
menuBar.add(menu);
menuBar.add(menu_help);
// menu加组件
menu.add(menuItem_start);
menu.add(menuItem_stop);
menu.add(menuItem_rank);
menu.addSeparator();
menu.add(menuItem_end);
// menu_help加组件
menu_help.add(menuItem_help);
}
public void showRank(String dir, String fileName) {
jLabel_First.setText(" First: "
+ readRankFromFile(dir, fileName, 1));
jLabel_Second.setText(" Second: "
+ readRankFromFile(dir, fileName, 2));
jLabel_Three.setText(" Third: "
+ readRankFromFile(dir, fileName, 3));//这个单词先前写错了
jDialog.setVisible(true);
}
public void writeRankToFile(String dir, String fileName, int value) {
File file = null;
FileInputStream fis = null;
Properties p = new Properties();
FileOutputStream fos = null;
try {
file = new File(dir + fileName);
// 路径名表示的文件不可用,这时指定默认路径名
if (!file.canExecute()) {
dir = "d:/tetris/game/";
file = new File(dir);
file.mkdirs();
file = new File(dir + fileName);
}
file.createNewFile();
// 从文件中读取数据
fis = new FileInputStream(dir + fileName);
p.load(fis);
// 第一个名
int temp1 = 120;
String first = p.getProperty("First");
if (first != null) {
temp1 = Integer.parseInt(first);
}
p.setProperty("First", String.valueOf(temp1));
// 第二名
int temp2 = 60;
first = p.getProperty("Second");
if (first != null) {
temp2 = Integer.parseInt(first);
}
p.setProperty("Second", String.valueOf(temp2));
// 第三名
int temp3 = 0;
first = p.getProperty("Three");
if (first != null) {
temp3 = Integer.parseInt(first);
}
p.setProperty("Three", String.valueOf(temp3));
// 插入排名数据****
if (value > temp1) {
p.setProperty("First", String.valueOf(value));
} else if (value > temp2) {
p.setProperty("Second", String.valueOf(value));
} else if (value > temp3) {
p.setProperty("Three", String.valueOf(value));
}
// 把数据保存到文件中
fos = new FileOutputStream(dir + fileName);
p.store(fos, "写入\"tetris\"游戏数据");
} catch (IOException e) {
new RuntimeException("文件创建失败");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public int readRankFromFile(String dir, String fileName, int value) {
File file = null;
FileInputStream fis = null;
Properties p = new Properties();
// 如果没成员,那么返回0
int temp = 0;
try {
file = new File(dir + fileName);
// 如果文件不存在,那么就返回0
if (!file.canExecute()) {
return 0;
}
// 从文件中读取数据
fis = new FileInputStream(dir + fileName);
p.load(fis);
String first = p.getProperty("First");
// 第一个名
if (value == 1 && first != null) {
temp = Integer.parseInt(first);
}
// 第二名
first = p.getProperty("Second");
if (value == 2 && first != null) {
temp = Integer.parseInt(first);
}
// 第三名
first = p.getProperty("Three");
if (value == 3 && first != null) {
temp = Integer.parseInt(first);
}
} catch (IOException e) {
new RuntimeException("文件创建失败");
} finally {
if (fis != null) {
try {
fis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return temp;
}
// 不访问外面的变量,使本类可以独立
public class TetrisJPanel extends JPanel {
private static final long serialVersionUID = 1L;
// 设置排名
protected String dir = "d:/tetris/game/",
filename = "tetris.properties";
// 控制游戏是否开始或暂停
public boolean isStart;
// 设置像素
private final int paintWidth = 20;
private int blockType, turnState;
private int blockType_copy = ((int) (Math.random() * 1000)) % 7;
private int turnState_copy = ((int) (Math.random() * 1000)) % 4;
// 设置方块的位置
private int x, y;
// 方块数据
private final int[][][] shapes = {
// I型
{
// 状态
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// J型
{
// 状态
{ 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 1, 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, 0, 0 }
},
// L型
{
// 状态
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 1, 0, 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, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// O型
{
// 状态
{ 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, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
// S型
{
// 状态
{ 0, 1, 1, 0, 1, 1, 0, 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, 1, 1, 0, 1, 1, 0, 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 }
},
// T型
{
// 状态
{ 1, 1, 1, 0, 0, 1, 0, 0, 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, 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 }
},
// Z型
{
// 状态
{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 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 表示积累块
// * 2
// * 3 表示框架
// */
// 游戏地图24+4行12+3列
private int[][] map = new int[24 + 4][12 + 3];
// 定时器
protected TimerListener listener = new TimerListener();
// 定时
private int delay = 1000;
Timer timer = new Timer(delay, listener);
// 记分
private int score = 0;
// 画笔字体
Font drawFont = new Font("宋体", Font.BOLD, 30);
public TetrisJPanel() {
newMap();
nextBlock();
timer.start();
}
// /*
// * 左移和右移都不能消行
// * 只有向下移动才可能消行
// */
private void down() {
// 先预测下移一位是否安全,如果不安全就返回0
if (collide(x, y + 1, blockType, turnState) == 0) {
// 当前快与框架与积淀块碰撞时要重新开始游戏
add(x, y, blockType, turnState);
nextBlock();
} else {
y++;
}
tryDelecteLine();
}
private void right() {
// 根据T型方块定的10,O型是9,
if (x <= 10) {// 有了预判,就可以随意了,只要不太小就行
// 先预测右移一位是否安全
x += collide(x + 1, y, blockType, turnState);
}
}
private void left() {
// 根据I型方块定的0是1,
if (x >= 1) {// 有了预判,就可以随意了,只要不太大就行
// 没有碰撞就返回1,先预测左移一位是否安全
x -= collide(x - 1, y, blockType, turnState);
}
}
private void turn() {
if (collide(x, y, blockType, (turnState + 1) % 4) == 1) {
turnState = (turnState + 1) % 4;
}
}
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[y + a][x + b] = 1;
}
}
}
}
// 碰撞 crash collide impact 单词
private int collide(int x, int y, int blockType, int turnState) {
for (int a = 0; a < 4; a++) {// 方块的行
for (int b = 0; b < 4; b++) {// 方块的列
// 一个数与1与运算,可以判断这个数是否是素数
// 这里的框架与积淀块分别是3,1;
// 遍历整个方块,然后与map的下一行进行对比(y+1),由此判断此方块是否碰撞
if ((map[y + a][x + b] & shapes[blockType][turnState][a * 4
+ b]) == 1) {
// 确认当前块会覆盖 框架或积淀块
// 设置map[][]中的数据为沉淀快
// 当碰撞时返回1
return 0;
}
}
}
// 当方块没有与框架与积淀块碰撞时返回1,方便计算
return 1;
}
private void tryDelecteLine() {
// 从最下面一行开始遍历,这样写会有特殊效果,会出现东西掉下来的感觉
for (int a = 23; a >= 0; a--) {// 24行
int c = 1;
for (int b = 1; b <= 12; b++) {
c &= map[a][b];
}
// 如果c==1,那么说明当前行装满了
if (c == 1) {
// 第一行没有拷贝
for (int i = a; i > 0; i--) {
for (int j = 1; j <= 12; j++) {
map[i][j] = map[i - 1][j];
}
}
// 第一行全赋值为0
for (int i = 1; i <= 12; i++) {
map[0][i] = 0;
}
score += 12;
delay -= 150;
setScoreDelay(score, delay);
}
}
}
private void newMap() {
// map[24+3][12+3]
for (int i = 0; i < map[0].length - 1; i++) {// 列,多加了1列
for (int j = 0; j < map.length - 3; j++) {// 行,多加了2行,加下边的一行
// 多加了1列,2行,第一列和倒数第二列
if (i == 0 || (i + 2 == map[0].length)) {// 表示框架
map[j][i] = 3;
} else {// 下次调用次函数可以重新初始化
map[j][i] = 0;
}
}
// 实际上并不需要四行
map[map.length - 4][i] = 3;// 最下边的框架
}
}
private void nextBlock() {
blockType = blockType_copy;
turnState = turnState_copy;
blockType_copy = ((int) (Math.random() * 1000)) % 7;
turnState_copy = ((int) (Math.random() * 1000)) % 4;
x = 5;
y = 0;
// 如果撞到了就重新开始,会返回0
if (collide(x, y, blockType, turnState) == 0) {
end();
JOptionPane.showMessageDialog(Tetris.this, "你输了,游戏结束!!!");
}
}
public void setScoreDelay(int score, int delay) {
this.score = score;
// 1000-150*5 < 400
if (delay < 400) {
delay = 1000;
}
timer.setDelay(delay);
}
public void start() {
// 初始化数据
end();
timer.start();
// 设置分数
score = 0;
// 游戏失败,但是不清空,重新开始时就清空
newMap();
nextBlock();
isStart = true;
}
public void end() {
// 所有数据复原
writeRankToFile(dir, filename, score);
isStart = false;
timer.stop();
setScoreDelay(0, 1000);
repaint();
}
class TimerListener extends KeyAdapter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// 先画
repaint();
// 控制游戏是否开始
if (!isStart) {
return;
}
// 自动向下
down();
}
// 有三个类,但是只有这个用到了
@Override
public void keyPressed(KeyEvent e) {
// 控制游戏是否开始或暂停
if (!isStart) {
return;
}
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
down();
break;
case KeyEvent.VK_RIGHT:
right();
break;
case KeyEvent.VK_LEFT:
left();
break;
case KeyEvent.VK_UP:
turn();
break;
}
repaint();
}
}
@Override
protected void paintComponent(Graphics g) {
// 清除内容,可以解决残影
super.paintComponent(g);
// 画当前块
g.setColor(Color.blue);
for (int a = 0; a < 16; a++) {
if (shapes[blockType][turnState][a] == 1) {
// x 表示列(a%4),y表示行(a/4)
g.fill3DRect((x + a % 4) * paintWidth, (y + a / 4)
* paintWidth, paintWidth, paintWidth, false);
// 画在右边
g.fill3DRect(340 + (a % 4) * paintWidth, 80 + (a / 4)
* paintWidth, paintWidth, paintWidth, false);
} else {
g.draw3DRect(340 + (a % 4) * paintWidth, 80 + (a / 4)
* paintWidth, paintWidth, paintWidth, false);
}
}
// 画框架和堆积快
for (int j = 0; j < map.length; j++) {// 行,多加了2行
for (int i = 0; i < map[i].length; i++) {// 列,多加了1列
if (map[j][i] == 3) {// 框架
g.setColor(Color.YELLOW);
g.fill3DRect(i * paintWidth, j * paintWidth,
paintWidth, paintWidth, true);
} else if (map[j][i] == 1) {// 画堆积快
g.setColor(Color.red);
g.fill3DRect(i * paintWidth, j * paintWidth,
paintWidth, paintWidth, true);
g.setColor(Color.black);
g.draw3DRect(i * paintWidth, j * paintWidth,
paintWidth, paintWidth, false);
}
}
}
// 记分面板
g.setColor(Color.red);
if (score <= 120) {
g.drawString("score:" + score, 340, 20);
} else {
g.setFont(drawFont);
g.drawString("恭喜你胜利" + score, 10, 100);
isStart = false;
}
// 下一个
g.drawString("下一个", 340, 200);
for (int a = 0; a < 16; a++) {
if (shapes[blockType_copy][turnState_copy][a] == 1) {// 空白快
g.fill3DRect(340 + (a % 4) * paintWidth, 220 + (a / 4)
* paintWidth, paintWidth, paintWidth, true);
} else {
g.draw3DRect(340 + (a % 4) * paintWidth, 220 + (a / 4)
* paintWidth, paintWidth, paintWidth, false);
}
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == menuItem_start) {
if (JOptionPane.showConfirmDialog(this, "你确定新建游戏吗?") == 0) {
jPanel.start();
}
}
if (e.getActionCommand().equalsIgnoreCase("stop")) {
menuItem_stop.setActionCommand("continue");
menuItem_stop.setText("继续");
jPanel.isStart = false;
}
if (e.getActionCommand().equalsIgnoreCase("continue")) {
menuItem_stop.setActionCommand("stop");
menuItem_stop.setText("暂停");
jPanel.isStart = true;
}
if (e.getSource() == menuItem_rank) {
showRank(jPanel.dir, jPanel.filename);
}
if (e.getSource() == menuItem_end) {
if (JOptionPane.showConfirmDialog(this, "你确定要退出吗?") == 0) {
System.exit(0);
}
}
if (e.getSource() == menuItem_help) {
JOptionPane.showMessageDialog(this,
"每消一行就加12分,满120分就胜利。\n如果想看以前的记录,可以看前三名。");
}
}
public static void main(String[] args) {
Tetris te = new Tetris();
// 一个像素有10int的大小,纯手工调试,不要抄袭啊!!!
te.setBounds(300, 60, 500, 565);
// te.setResizable(false);
te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
te.setVisible(true);
}
}
//这个是没有等级的。
package design_Tetris_Analog1;
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 javax.swing.JApplet;
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;
public class Tetris extends JFrame implements ActionListener {
private static final long serialVersionUID = 1L;
private TetrisJPanel jPanel;
public boolean isStart;
JMenuItem menuItem_start, menuItem_stop, menuItem_end;
public Tetris() {
addMenu();
// new 对象
this.jPanel = new TetrisJPanel();
// 设置背景,这里有点邪门。。。
// jPanel.setBackground(Color.black);
this.setBackground(Color.white);
this.getContentPane().add(jPanel);
// 为框架添加键盘监听
this.addKeyListener(jPanel.listener);
}
private void addMenu() {
// new 对象
JMenuBar menuBar = new JMenuBar();
JMenu menu = new JMenu("菜单");
menuItem_start = new JMenuItem("新建游戏");
menuItem_stop = new JMenuItem("暂停");
menuItem_stop.setActionCommand("stop");
menuItem_end = new JMenuItem("结束");
// 给菜单项加监听
menuItem_start.addActionListener(this);
menuItem_stop.addActionListener(this);
menuItem_end.addActionListener(this);
// 加工具条和菜单
this.setJMenuBar(menuBar);
menuBar.add(menu);
menu.add(menuItem_start);
menu.add(menuItem_stop);
menu.add(menuItem_end);
}
class TetrisJPanel extends JPanel {
private static final long serialVersionUID = 1L;
private int blockType, turnState;
private int blockType_copy = ((int) (Math.random() * 1000)) % 7;
private int turnState_copy = ((int) (Math.random() * 1000)) % 4;
// 设置方块的位置
private int x, y;
// 方块数据
private final int[][][] shapes = {
// I型
{
// 状态
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0 },
{ 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// J型
{
// 状态
{ 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 1, 0, 0, 0, 1, 1, 1, 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, 0, 0 }
},
// L型
{
// 状态
{ 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0 },
{ 1, 1, 1, 0, 1, 0, 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, 1, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 } },
// O型
{
// 状态
{ 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, 1, 1, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 }
},
// S型
{
// 状态
{ 0, 1, 1, 0, 1, 1, 0, 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, 1, 1, 0, 1, 1, 0, 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 }
},
// T型
{
// 状态
{ 1, 1, 1, 0, 0, 1, 0, 0, 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, 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 }
},
// Z型
{
// 状态
{ 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
{ 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0 },
{ 1, 1, 0, 0, 0, 1, 1, 0, 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 表示积累块
// * 2
// * 3 表示框架
// */
// 游戏地图24+4行12+3列
private int[][] map = new int[24 + 4][12 + 3];
// 定时器
protected TimerListener listener = new TimerListener();
// 定时
private int delay = 1000;
Timer timer = new Timer(delay, listener);
// 记分
private int score = 0;
// 画笔字体
Font drawFont = new Font("宋体", Font.BOLD, 30);
// 控制游戏是否开始
public TetrisJPanel() {
// this.setBackground(Color.blue);//加监听器后,调用down()函数,就可以用了
newMap();
nextBlock();
timer.start();
}
class TimerListener extends KeyAdapter implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
// 控制游戏是否开始
if (!isStart) {
return;
}
// 自动向下
down();
repaint();
}
// 有三个类,但是只有这个用到了
@Override
public void keyPressed(KeyEvent e) {
// 控制游戏是否开始
if (!isStart) {
return;
}
switch (e.getKeyCode()) {
case KeyEvent.VK_DOWN:
// System.out.println("down");
down();
break;
case KeyEvent.VK_RIGHT:
// System.out.println("right");
right();
break;
case KeyEvent.VK_LEFT:
// System.out.println("left");
left();
break;
case KeyEvent.VK_UP:
// System.out.println("turn");
turn();
break;
}
repaint();
}
}
private void newMap() {
// map[24+3][12+3]
for (int i = 0; i < map[0].length - 1; i++) {// 列,多加了1列
for (int j = 0; j < map.length - 3; j++) {// 行,多加了2行,加下边的一行
// 多加了1列,2行,第一列和倒数第二列
if (i == 0 || (i + 2 == map[0].length)) {// 表示框架
map[j][i] = 3;
} else {// 下次调用次函数可以重新初始化
map[j][i] = 0;
}
}
// 实际上并不需要四行
map[map.length - 4][i] = 3;// 最下边的框架
}
repaint();
}
private void nextBlock() {
blockType = blockType_copy;
turnState = turnState_copy;
blockType_copy = ((int) (Math.random() * 1000)) % 7;
turnState_copy = ((int) (Math.random() * 1000)) % 4;
x = 5;
y = 0;
repaint();
// 如果撞到了就重新开始,会返回0
if (collide(x, y, blockType, turnState) == 0) {
isStart = false;
JOptionPane.showMessageDialog(Tetris.this, "你输了,游戏结束!!!");
//看要不要自动开始游戏
//isStart = true;
newMap();
}
}
// /*
// * 左移和右移都不能消行
// * 只有向下移动才可能消行
// */
private void down() {
// 先预测下移一位是否安全,如果不安全就返回0
if (collide(x, y + 1, blockType, turnState) == 0) {
// 当前快与框架与积淀块碰撞时要重新开始游戏
add(x, y, blockType, turnState);
nextBlock();
} else {
y++;
}
tryDelecteLine();
repaint();
}
private void right() {
// 根据T型方块定的10,O型是9,
if (x <= 10) {// 有了预判,就可以随意了,只要不太小就行
// 先预测右移一位是否安全
x += collide(x + 1, y, blockType, turnState);
repaint();
}
}
private void left() {
// 根据I型方块定的0是1,
if (x >= 1) {// 有了预判,就可以随意了,只要不太大就行
// 没有碰撞就返回1,先预测左移一位是否安全
x -= collide(x - 1, y, blockType, turnState);
repaint();
}
}
private void turn() {
if (collide(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[y + a][x + b] = 1;
}
}
}
}
private void tryDelecteLine() {
// 从最下面一行开始遍历
for (int a = 23; a >= 0; a--) {// 24行
int c = 1;
for (int b = 1; b <= 12; b++) {
c &= map[a][b];
}
// 如果c==1,那么说明当前行装满了
if (c == 1) {
// 第一行没有拷贝
for (int i = a; i > 0; i--) {
for (int j = 1; j <= 12; j++) {
map[i][j] = map[i - 1][j];
}
}
// 第一行全赋值为0
for (int i = 1; i <= 12; i++) {
map[0][i] = 0;
}
score += 12;
delay /= 2;
setScoreDelay(score, delay);
}
}
}
public void setScoreDelay(int score, int delay) {
this.score = score;
timer.setDelay(delay);
if (delay < 100) {
delay = 2000;
}
}
// 碰撞 crash collide impact 单词
private int collide(int x, int y, int blockType, int turnState) {
for (int a = 0; a < 4; a++) {// 方块的行
for (int b = 0; b < 4; b++) {// 方块的列
// 一个数与1与运算,可以判断这个数是否是素数
// 这里的框架与积淀块分别是3,1;
// 遍历整个方块,然后与map的下一行进行对比(y+1),由此判断此方块是否碰撞
if ((map[y + a][x + b] & shapes[blockType][turnState][a * 4
+ b]) == 1) {
// 确认当前块会覆盖 框架或积淀块
// 设置map[][]中的数据为沉淀快
// 当碰撞时返回1
return 0;
}
}
}
// 当方块没有与框架与积淀块碰撞时返回1,方便计算
return 1;
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
// 画当前块
g.setColor(Color.blue);
for (int a = 0; a < 16; a++) {
if (shapes[blockType][turnState][a] == 1) {
// g.fillRect(int x,int y,int width,int height)
// x 表示列(a%4),y表示行(a/4)
g.fillRect((x + a % 4) * 10, (y + a / 4) * 10, 10, 10);
}
}
// 画框架和堆积块
g.setColor(Color.red);
for (int j = 0; j < map.length; j++) {// 行,多加了2行
for (int i = 0; i < map[i].length; i++) {// 列,多加了1列
if (map[j][i] == 3) {
g.drawRect(i * 10, j * 10, 10, 10);
} else if (map[j][i] == 1) {// 画堆积快
g.fillRect(i * 10, j * 10, 10, 10);
}
}
}
// 记分面板
if (score <= 120) {
g.drawString("score:" + score, 170, 20);
} else {
g.setFont(drawFont);
g.drawString("恭喜你胜利" + score, 10, 100);
isStart = false;
}
// 当前块
g.drawString("当前块", 170, 60);
for (int a = 0; a < 16; a++) {
if (shapes[blockType][turnState][a] == 1) {
g.fillRect(180 + (a % 4) * 10, 80 + (a / 4) * 10, 10, 10);
} else {
g.drawRect(180 + (a % 4) * 10, 80 + (a / 4) * 10, 10, 10);
}
}
// 下一个
g.drawString("下一个", 170, 160);
for (int a = 0; a < 16; a++) {
if (shapes[blockType_copy][turnState_copy][a] == 1) {
g.fillRect(180 + (a % 4) * 10, 180 + (a / 4) * 10, 10, 10);
} else {
g.drawRect(180 + (a % 4) * 10, 180 + (a / 4) * 10, 10, 10);
}
}
}
}
@Override
public void actionPerformed(ActionEvent e) {
if (e.getSource() == menuItem_start) {
if (JOptionPane.showConfirmDialog(this, "你确定新建游戏吗?") == 0) {
jPanel.newMap();
// jPanel.nextBlock();
isStart = true;
}
}
if (e.getActionCommand().equalsIgnoreCase("stop")) {
menuItem_stop.setActionCommand("continue");
isStart = false;
menuItem_stop.setText("继续");
}
if (e.getActionCommand().equalsIgnoreCase("continue")) {
menuItem_stop.setActionCommand("stop");
isStart = true;
menuItem_stop.setText("暂停");
}
if (e.getSource() == menuItem_end) {
if (JOptionPane.showConfirmDialog(this, "你确定要退出吗?") == 0) {
System.exit(0);
}
}
}
public static void main(String[] args) {
Tetris te = new Tetris();
// 一个像素有10int的大小,纯手工调试,不要抄袭啊!!!
te.setBounds(800, 60, 250, 305);
te.setResizable(false);
te.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
te.setVisible(true);
}
}
\
原文:http://blog.csdn.net/hncu1306602liuqiang/article/details/46572905