码迷,mamicode.com
首页 > 其他好文 > 详细

俄罗斯方块

时间:2015-06-20 15:50:14      阅读:202      评论:0      收藏:0      [点我收藏+]

标签:java   游戏   

这里面用了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);
	}

}

//word文档的内容

技术分享
技术分享

技术分享



技术分享
技术分享

技术分享

技术分享

技术分享

\技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享

技术分享












































































































俄罗斯方块

标签:java   游戏   

原文地址:http://blog.csdn.net/hncu1306602liuqiang/article/details/46572905

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!