TETRIS 项目开发笔记
java学习一个月了,没有什么进展,期间又是复习Linux,又是看Android,瞻前顾后,感觉自己真的是贪得无厌,
学习的东西广而不精,所以写出的文章也就只能泛泛而谈。五一小长假,哪里都没有去,也不想去,刚刚无聊刷新了下
朋友圈,朋友们不是在玩,就是在吃,突然一下子感觉自己老了许多。岁月真是把杀猪刀,夺走了我们的青春,但却无
法夺走我们的激情。
好好复习了!
在老师引领下,算是把人生中的第一个Java项目敲完了,感觉对于学习OOP的朋友,应该有所帮助,先做个笔记吧
等后期有时间再添些自己的Feature。
package com.manue1.tetris; import javax.swing.JFrame; /**
* 游戏窗口
* @author Manue1
* @version 1.0
*
*/
public class GameFrame extends JFrame{ private static final long serialVersionUID = 1L;
private Tetris tetris;
public GameFrame(){ tetris =new Tetris();
add(tetris);
setSize(530,580);
setDefaultCloseOperation(EXIT_ON_CLOSE);
setLocationRelativeTo(null);
}
public static void main(String[] args){
GameFrame frame =new GameFrame();
frame.setVisible(true);
frame.tetris.action(); //创建4个格子 } }
package com.manue1.tetris; import java.awt.image.BufferedImage; /**
* 定义格子
* @author Manue1
*/
public class Cell extends Object{
private int row; int col;
private BufferedImage image; public Cell(int row, int col, BufferedImage image) {
super();
this.row = row;
this.col = col;
this.image = image;
} public int getRow() {
return row;
} public void setRow(int row) {
this.row = row;
} public int getCol() {
return col;
} public void setCol(int col) {
this.col = col;
} public BufferedImage getImage() {
return image;
} public void setImage(BufferedImage image) {
this.image = image;
} @Override
public String toString() {
return "Cell [col=" + col + ", image=" + image + ", row=" + row + "]";
} public void moveLeft(){
col--;
}
public void moveRight(){
col++;
}
public void moveDrop(){
row++;
} }
定义格子
package com.manue1.tetris;
import java.util.Arrays;
import java.util.Random; /**
* 4格方块
* 只能被子类使用
* @author Manue1
*/
public abstract class Tetromino { protected Cell[] cells =new Cell[4];//{^,^,^,^} /*旋转状态
*
*/
protected State[] states;
/* 旋转状态的序号
*
*/
protected int index =10000;
/*内部类
*
*/
protected class State {
int row0, col0, row1, col1, row2, col2, row3, col3;
public State(int row0, int col0, int row1, int col1, int row2,
int col2, int row3, int col3) {
this.row0 = row0;
this.col0 = col0;
this.row1 = row1;
this.col1 = col1;
this.row2 = row2;
this.col2 = col2;
this.row3 = row3;
this.col3 = col3;
}
}
/** 向右转 */
public void rotateRight() { index++;
State s = states[index % states.length];
Cell o = cells[0];
int row = o.getRow();
int col = o.getCol();
cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
} /** 向左转 */
public void rotateLeft() {
index--;
State s = states[index % states.length];
Cell o = cells[0];
int row = o.getRow();
int col = o.getCol();
cells[1].setRow(row + s.row1);
cells[1].setCol(col + s.col1);
cells[2].setRow(row + s.row2);
cells[2].setCol(col + s.col2);
cells[3].setRow(row + s.row3);
cells[3].setCol(col + s.col3);
} //工厂方法,随机产生4格方块 public static Tetromino randomOne(){
Random random =new Random();
int type =random.nextInt(7);
switch(type){
case 0:
return new T();
case 1:
return new I();
case 2:
return new S();
case 3:
return new J();
case 4:
return new L();
case 5:
return new Z();
case 6:
return new O();
} return null; } //方块下落 左右移动 一个格子
public void moveRight(){
for(int i=0;i<cells.length ;i++){
cells[i].moveRight();
}
}
public void moveLeft(){
for(int i=0;i<cells.length ;i++){
cells[i].moveLeft();
}
}
public void sofeDrop(){
for(int i=0;i<cells.length ;i++){
cells[i].moveDrop();
}
}
//显示方块中每个格子的行列信息
public String toString(){
return Arrays.toString(cells);
} } // 定义七类格子
class T extends Tetromino{
public T(){
cells[0]=new Cell(0,4,Tetris.T);
cells[1]=new Cell(0,3,Tetris.T);
cells[2]=new Cell(0,5,Tetris.T);
cells[3]=new Cell(1,4,Tetris.T);
states = new State[4];
states[0] = new State(0, 0, 0, -1, 0, 1, 1, 0);
states[1] = new State(0, 0, -1, 0, 1, 0, 0, -1);
states[2] = new State(0, 0, 0, 1, 0, -1, -1, 0);
states[3] = new State(0, 0, 1, 0, -1, 0, 0, 1);
}
}
class S extends Tetromino{
public S(){
cells[0]=new Cell(0,4,Tetris.S);
cells[1]=new Cell(0,5,Tetris.S);
cells[2]=new Cell(1,3,Tetris.S);
cells[3]=new Cell(1,4,Tetris.S); states = new State[] { new State(0, 0, 0, -1, -1, 0, -1, 1),
new State(0, 0, -1, 0, 0, 1, 1, 1) }; }
}
class Z extends Tetromino{
public Z() {
cells[0] = new Cell(1, 4, Tetris.Z);
cells[1] = new Cell(0, 3, Tetris.Z);
cells[2] = new Cell(0, 4, Tetris.Z);
cells[3] = new Cell(1, 5, Tetris.Z); states = new State[] { new State(0, 0, -1, -1, -1, 0, 0, 1),
new State(0, 0, -1, 1, 0, 1, 1, 0) };
}
}
class O extends Tetromino{
public O() {
cells[0] = new Cell(0, 4, Tetris.O);
cells[1] = new Cell(0, 5, Tetris.O);
cells[2] = new Cell(1, 4, Tetris.O);
cells[3] = new Cell(1, 5, Tetris.O);
states = new State[] { new State(0, 0, 0, 1, 1, 0, 1, 1),
new State(0, 0, 0, 1, 1, 0, 1, 1) };
}
}
class J extends Tetromino{
public J() {
cells[0] = new Cell(0, 4, Tetris.J);
cells[1] = new Cell(0, 3, Tetris.J);
cells[2] = new Cell(0, 5, Tetris.J);
cells[3] = new Cell(1, 5, Tetris.J); states = new State[] { new State(0, 0, 0, -1, 0, 1, 1, 1),
new State(0, 0, -1, 0, 1, 0, 1, -1),
new State(0, 0, 0, 1, 0, -1, -1, -1),
new State(0, 0, 1, 0, -1, 0, -1, 1) };
}
}
class L extends Tetromino{
public L() {
cells[0] = new Cell(0, 4, Tetris.L);
cells[1] = new Cell(0, 3, Tetris.L);
cells[2] = new Cell(0, 5, Tetris.L);
cells[3] = new Cell(1, 3, Tetris.L); states = new State[] { new State(0, 0, 0, 1, 0, -1, -1, 1),
new State(0, 0, 1, 0, -1, 0, 1, 1),
new State(0, 0, 0, -1, 0, 1, 1, -1),
new State(0, 0, -1, 0, 1, 0, -1, -1) };
}
}
class I extends Tetromino{
public I() {
cells[0] = new Cell(0, 4, Tetris.I);
cells[1] = new Cell(0, 3, Tetris.I);
cells[2] = new Cell(0, 5, Tetris.I);
cells[3] = new Cell(0, 6, Tetris.I); states = new State[] { new State(0, 0, 0, -1, 0, 1, 0, 2),
new State(0, 0, -1, 0, 1, 0, 2, 0) };
}
}
七中方块
package com.manue1.tetris;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.util.Arrays;
import java.util.Timer;
import java.util.TimerTask; import javax.swing.JPanel;
import javax.imageio.ImageIO; /**
* 俄罗斯方块面板
* @author Manue1
* @version 1.0
*/
public class Tetris extends JPanel { private static final long serialVersionUID = 1L;
/*
* 分数 墙 正在 下落的方块 下一个方块
*/
public static final int FONT_COLOR=0x667799;
public static final int FONT_SIZE=30;
private int score;
private int lines; // 销毁的行数
private Cell[][] wall = new Cell[ROWS][COLS]; // 墙
private Tetromino tetromino; // 正在下落的四格方块
private Tetromino nextOne;
public static final int ROWS = 20; // 行数
public static final int COLS = 10; // 列数 /*
* 背景图片
*/
private static BufferedImage background;
private static BufferedImage overImage;
public static BufferedImage T;
public static BufferedImage S;
public static BufferedImage I;
public static BufferedImage L;
public static BufferedImage J;
public static BufferedImage O;
public static BufferedImage Z; /*
* 静态代码块
*/
static {
try { // 从Tetris类所在的包中读取图片文件到内存对象
background = ImageIO.read(Tetris.class.getResource("tetris.png"));
overImage = ImageIO.read(Tetris.class.getResource("game-over.png"));
T = ImageIO.read(Tetris.class.getResource("T.png"));
I = ImageIO.read(Tetris.class.getResource("I.png"));
S = ImageIO.read(Tetris.class.getResource("S.png"));
Z = ImageIO.read(Tetris.class.getResource("Z.png"));
J = ImageIO.read(Tetris.class.getResource("J.png"));
L = ImageIO.read(Tetris.class.getResource("L.png"));
O = ImageIO.read(Tetris.class.getResource("O.png")); } catch (Exception e) {
e.printStackTrace();
}
} // 在Tetris类中重写 绘制方法 绘制背景图片
public void paint(Graphics g) {
g.drawImage(background, 0, 0, null);
g.translate(15, 15); // 坐标系平移
paintWall(g); // 画墙
paintTetromino(g);
paintnextOne(g);
paintScore(g);//绘制分数
if (gameOver) {
g.drawImage(overImage, 0, 0, null);
}
} /*
* 在Tetris添加启动方法action()
*/
public void action() {
wall = new Cell[ROWS][COLS];
tetromino = Tetromino.randomOne();
nextOne = Tetromino.randomOne(); /* 处理键盘按下事件, 在按下按键时候执行下落方法
* 监听键盘事件 创建监听器对象, 注册监听器
*/ this.addKeyListener(new KeyAdapter() {
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();// [c] if (key == KeyEvent.VK_Q) {//Q表示退出
System.exit(0);// 结束Java进程
}
if (gameOver) {
if (key == KeyEvent.VK_S) {//S表示开始
startAction();
repaint();
}
return;
}
if (pause) {// pause = true
if (key == KeyEvent.VK_C) {//C表示继续
continueAction();
repaint();
}
return;
} switch (key) {
case KeyEvent.VK_DOWN:
//tetromino.sofeDrop();
softDropAction(); break;
case KeyEvent.VK_RIGHT:
//tetromino.moveRight();
moveRightAction();
break;
case KeyEvent.VK_LEFT:
//tetromino.moveLeft();
moveLeftAction();
break;
case KeyEvent.VK_SPACE : hardDropAction();
break;
case KeyEvent.VK_UP:
rotateRightAction();
break;
case KeyEvent.VK_P://按键盘上的P表示暂停
pauseAction();
break;
}
repaint();// 再画一次!
}
}); this.requestFocus(); //为面板请求焦点 this.setFocusable(true); //面板可以获得焦点
/*
* 计时器 自动下落
*/
timer = new Timer();
timer.schedule(
new TimerTask(){
public void run(){
//tetromino.sofeDrop();
softDropAction();
repaint();
}
},1000,1000); } public static final int CELL_SIZE = 26; /*
* 画墙
*/ private void paintWall(Graphics g) {
for (int row = 0; row < wall.length; row++) {
Cell[] line = wall[row];
// line 代表墙上的每一行
for (int col = 0; col < line.length; col++) {
Cell cell = line[col];
// cell 代表墙上的每个格子
int x = col * CELL_SIZE;
int y = row * CELL_SIZE;
if (cell == null) {
g.drawRect(x, y, CELL_SIZE, CELL_SIZE); } else {
g.drawImage(cell.getImage(), x - 1, y - 1, null); }
// g.drawString(row+","+col, x,y+CELL_SIZE);
}
}
} /*
* 正在下落 方块
*/
public void paintTetromino(Graphics g) {
if (tetromino == null) {return;} // 如果是空 直接不执行了 输入数据的有效性检测
Cell[] cells = tetromino.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int x = cell.getCol() * CELL_SIZE;
int y = cell.getRow() * CELL_SIZE;
g.drawImage(cell.getImage(), x, y, null);
}
}
/*
* 下一个下落的方块
*/
public void paintnextOne(Graphics g) {
if (nextOne == null) {return;} // 如果是空 直接不执行了 输入数据的有效性检测
Cell[] cells = nextOne.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int x = (cell.getCol()+10) * CELL_SIZE;
int y = (cell.getRow()+1) * CELL_SIZE;
g.drawImage(cell.getImage(), x, y, null);
}
} /*在Tetris类中添加方法
* 检测正在下路方块是否出界
*/
/** 检查当前正在下落的方块是否出界了 */
private boolean outOfBounds() {
Cell[] cells = tetromino.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int col = cell.getCol();
if (col < 0 || col >= COLS) {
return true;
}
}
return false;
}
/** 检查正在下落的方块是否与墙上的砖块重叠 */
private boolean coincide() {
Cell[] cells = tetromino.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int row = cell.getRow();
int col = cell.getCol();
// 如果墙的row,col位置上有格子,就重叠了!
if (row >= 0 && row < ROWS && col >= 0 && col <= COLS
&& wall[row][col] != null) {
return true;// 重叠
}
}
return false;
}
/** 在Tetris 类上添加方法, 向右移动的流程控制 */
public void moveRightAction() {
// 尝试先向右移动, 如果发现超出了边界, 就
// 向左移动, 修正回来.
tetromino.moveRight();// coincide重叠
if (outOfBounds() || coincide()) {
tetromino.moveLeft();
}
}
public void moveLeftAction() {
tetromino.moveLeft();
if (outOfBounds() || coincide()) {
tetromino.moveRight();
}
} /* 下落流程控制
*
*/ public void softDropAction() {
if (canDrop()) {
tetromino.sofeDrop();
} else {
landIntoWall();
destoryLines();
checkGameOverAction();
tetromino = nextOne;
nextOne = Tetromino.randomOne();
}
}
public void hardDropAction(){
while(canDrop()){
tetromino.sofeDrop();
}
landIntoWall();
destoryLines();
checkGameOverAction();
tetromino = nextOne;
nextOne = Tetromino.randomOne(); } private static int[] scoreTable={0,1,10,50,100}; /* 调用删除行方法。循环让上面所有的行落下来 */
private void destoryLines() {
int lines = 0;
for (int row = 0; row < wall.length; row++) {
if (fullCells(row)) {
deleteRow(row);
lines++;
}
}
this.score += scoreTable[lines];
this.lines += lines;
} /*
* 删除行
*/
private void deleteRow(int row) {
for (int i = row; i >= 1; i--) {
System.arraycopy(wall[i - 1], 0, wall[i], 0, COLS);
}
Arrays.fill(wall[0], null);
} /* 判断行是否被填充
*
*/
private boolean fullCells(int row){
Cell[] line =wall[row];
/*
for(Cell cell : line){
if(cell==null) return false;
}
*/
for(int i=0;i<line.length;i++){
if(line[i]==null)return false;
}
return true;
} /*下落到最低行停止
*
*/
private void landIntoWall(){
Cell[] cells=tetromino.cells;
for(int i=0;i<cells.length;i++){
Cell cell = cells[i];
int row,col;
row=cell.getRow();
col=cell.getCol();
wall[row][col]=cell;
}
} private boolean canDrop() {
Cell[] cells = tetromino.cells;
for (int i = 0; i < cells.length; i++) {
Cell cell = cells[i];
int row = cell.getRow();
if (row == ROWS - 1) {
return false;
}
}
for (Cell cell : cells) {// Java 5 以后可以使用
int row = cell.getRow() + 1;
int col = cell.getCol();
if (row >= 0 && row < ROWS && col >= 0 && col <= COLS
&& wall[row][col] != null) {
return false;
}
}
return true;
} /*绘制分数
*
*/
private void paintScore(Graphics g) {
int x = 290;
int y = 160;
g.setColor(new Color(FONT_COLOR));
Font font = g.getFont();// 取得g当前字体
font = new Font(font.getName(), font.getStyle(), FONT_SIZE);
g.setFont(font);// 更改了g的字体
String str = "SCORE:" + score;
g.drawString(str, x, y);
y += 56;
str = "LINES:" + lines;
g.drawString(str, x, y);
y += 56;
str = "[P]Pause";
if (pause) {
str = "[C]Continue";
}
if (gameOver) {
str = "[S]Start!";
}
g.drawString(str, x, y); } /** 在Tetris类中添加 旋转流程控制方法 */
public void rotateRightAction() {
tetromino.rotateRight();
if (outOfBounds() || coincide()) {
tetromino.rotateLeft();
}
} /*
* 流程处理
*/
private Timer timer;
private boolean pause;//是否为暂停状态
private boolean gameOver;//是否为游戏结束状态
private long interval = 600;// 间隔时间 /** 在Tetris类中添加 开始流程控制 */
public void startAction() {
pause = false;
gameOver = false;
score = 0;
lines = 0;
clearWall();
tetromino = Tetromino.randomOne();
nextOne = Tetromino.randomOne();
timer = new Timer();
timer.schedule(new TimerTask() {
public void run() {
softDropAction();
repaint();
}
}, interval, interval);
}
/**
* 清除墙上的方块
*/
private void clearWall() {
for (Cell[] line : wall) {
Arrays.fill(line, null);
}
}
/**
* 暂停
*/
public void pauseAction() {
timer.cancel();
pause = true;
}
/**
* 继续
*/
public void continueAction() {
timer = new Timer();
timer.schedule(new TimerTask() {
@Override
public void run() {
softDropAction();
repaint();
}
}, interval, interval);
pause = false;
}
/**
* 游戏结束
*/
public void checkGameOverAction() {
if (wall[0][4] != null) {
timer.cancel();
gameOver = true;
}
}
}
面板操作
TETRIS 项目开发笔记的更多相关文章
- [Openwrt 项目开发笔记]:Openwrt平台搭建(一)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 最近开始着手进行Openwrt平台的物联网网关设 ...
- [openwrt 项目开发笔记]: 传送门
“Openwrt 项目开发笔记”系列传送门: [Openwrt 项目开发笔记]:Openwrt平台搭建(一) (2014-07-11 00:11) [Openwrt 项目开发笔记]:Openwrt平台 ...
- [Openwrt 项目开发笔记]:PHP+Nginx安装(七)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我们已经搭建了MySQL数据库了,因 ...
- [Openwrt 项目开发笔记]:MySQL配置(六)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在本人的项目中,运行在路由器上的服务器采用Ngi ...
- [Openwrt 项目开发笔记]:DDNS设置(五)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我主要讲述了如何在Openwrt上安 ...
- [Openwrt 项目开发笔记]:Samba服务&vsFTP服务(四)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一节中,我们讲述了如何在路由器上挂载U盘,以 ...
- [Openwrt 项目开发笔记]:USB挂载& U盘启动(三)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 在上一篇中,我结合Netgear Wndr370 ...
- [Openwrt 项目开发笔记]:Openwrt必要设置(二)
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 前面的两篇blog中,我将如何搭建Openwrt ...
- [Openwrt 项目开发笔记]:Openwrt平台搭建(一)补遗
[Openwrt项目开发笔记]系列文章传送门:http://www.cnblogs.com/double-win/p/3888399.html 正文: 昨晚上熬夜写了[Openwrt项目开发笔记]:O ...
随机推荐
- android L 新控件侧滑菜单DrawerLayout 使用教程
介绍 drawerLayout是Support Library包中实现了侧滑菜单效果的控件,可以说drawerLayout是因为第三方控件如MenuDrawer等的出现之后,google借鉴而出现的产 ...
- [转]SVN-版本控制软件
一.版本控制软件 1.为什么需要版本控制软件 问题:① 团队开发 ② 异地协作 ③ 版本回退 2.解决之道 SCM(Software Configuration Management):软件配置管理 ...
- 互联网行业都缺前端工程师-最高offer薪水38k*16
摘要:现在,几乎整个互联网行业都缺前端工程师,不仅在刚起步的创业公司,对上市公司乃至巨头这个问题也一样存在.没错,优秀的前端工程师简直比大熊猫还稀少. 现在,几乎整个互联网行业都缺前端工程师,不仅在刚 ...
- 为网站加入Drupal星球制作RSS订阅源
目前中文 Drupal 星球的版块还未成立,但大家的积极性挺高,不少站长都已经调整好自己的网站,生成了可供Drupal Planet 使用的RSS订阅源. 如果你也想让网站做好准备,可以不必再花上不少 ...
- 分享一个MVC的多层架构,欢迎大家拍砖斧正
如果你对项目管理.系统架构有兴趣,请加微信订阅号"softjg",加入这个PM.架构师的大家庭 多层架构是开发人员在开发过程当中面对复杂且易变的需求采取的一种以隔离控制为主的应对策 ...
- Oracle 事务
begin begin savepoint p1; DELETE FROM sys_re_xxx; //红色部分替换为需要一起执行的SQL即可 DELETE FROM SYS_xxxx; ...... ...
- Comparing cards
For built-in types, there are conditional operators (<, >, ==, etc.) that compare values and d ...
- 学习记录 Eclipse常用快捷键及其演练
Eclipse中10个最有用的快捷键组合 1. ctrl+shift+r:打开资源 这可能是所有快捷键组合中最省时间的了.这组快捷键可以让你打开你的工作区中任何一个文件,而你只需要按下文件名或mask ...
- MySQL学习笔记(二)
二.SQL基本知识 SQL 是一种典型的非过程化程序设计语言,这种语言的特点是:只指定哪些数据被操纵,至于对这些数据要执行哪些操作,以及这些操作是如何执行的,则未被指定.非过程化程序设计语言的优点在于 ...
- cordova 开发属于自己的插件---android
还是需要开发出自己的插件的... 我的cordova version is 4.0.0 1.需要新建一个文件夹为 myplugin 1.1在myplugin文件夹下 新建 plugin.xml文件 ...