俄罗斯方块游戏 --- java
俄罗斯方块游戏
如有疑问请查看:http://zh.wikipedia.org/zh-tw/%E4%BF%84%E7%BD%97%E6%96%AF%E6%96%B9%E5%9D%97
更多疑问请参考:http://java.itcast.cn/news/b4c1f433/34fd/4a7b/96bf/f1ae5e00ce70.shtml
游戏的运行结果如下:
代码的整体目录结构如下:
游戏发生的场地是在面板(panel)上,是JFrame框架把面板圈了起来
图形具有自己本身的特征,比如说形状,颜色,会定时落下一个单位,以及被触发的变幻,左移,右移,下移,
障碍物是图形落下后到底边框或其它图形产生的障碍物由图形生成的,
控制器负责接受按键事件来控制面板上的图形的移动和产生
这里是程序的入口处:
- package com.kodoyang.tetris.test;
- import javax.swing.JFrame;
- import com.kodoyang.tetris.control.Controller;
- import com.kodoyang.tetris.pojo.Ground;
- import com.kodoyang.tetris.pojo.ShapeFactory;
- import com.kodoyang.tetris.view.Panel;
- public class Game {
- public static void main(String[] args) {
- // TODO Auto-generated method stub
- ShapeFactory shapeFactory = new ShapeFactory();
- Ground ground = new Ground();
- Panel panel = new Panel();
- Controller controller = new Controller(shapeFactory, ground, panel);
- JFrame frame = new JFrame();
- frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- frame.setSize(panel.getSize().width + 10, panel.getSize().height + 35);
- frame.add(panel);
- panel.addKeyListener(controller);
- frame.addKeyListener(controller);
- frame.setVisible(true);
- controller.newGame();
- }
- }
先来看看图形类:
图形的body回填上制造啊它的工厂传给它的参数,
以及它的移动方式,坐标,颜色,画自己的方法,不断下落的线程
- package com.kodoyang.tetris.pojo;
- import java.awt.Color;
- import java.awt.Graphics;
- import com.kodoyang.tetris.listen.ShapeListener;
- import com.kodoyang.tetris.util.Global;
- public class Shape {
- public static final int ROTATE = 0;
- public static final int LEFT = 1;
- public static final int RIGHT = 2;
- public static final int DOWN = 3;
- private int[][] body;
- private int status;
- private Color color;
- private int left;
- private int top;
- public void setBody(int body[][]){
- this.body = body;
- }
- public void setStatus(int status) {
- this.status = status;
- }
- public int getTop(){
- return top;
- }
- public int getLeft(){
- return left;
- }
- private ShapeListener listener;
- public void moveLeft() {
- System.out.println("Shape's moveLeft");
- --left;
- }
- public void moveRight() {
- System.out.println("Shape's moveRight");
- ++left;
- }
- public void moveDown() {
- System.out.println("Shape's moveDown");
- ++top;
- }
- public void rotate() {
- System.out.println("Shape's rotate");
- status = (status + 1) % body.length;
- }
- public void drawMe(Graphics g) {
- System.out.println("Shape's drawMe");
- g.setColor(color);
- for(int x = 0; x < 4; ++x){
- for(int y = 0; y < 4; ++y){
- if(getFlagByPoint(x, y)){
- g.fill3DRect(
- (left + x) * Global.CELL_SIZE,
- (top + y) * Global.CELL_SIZE,
- Global.CELL_SIZE,
- Global.CELL_SIZE,
- true);
- }
- }
- }
- }
- private boolean getFlagByPoint(int x, int y){
- /*boolean res = false;
- try {
- // return body[status][x + y * 4] == 1;
- res = body[status][x + y * 4] == 1;
- } catch (Exception e) {
- // TODO Auto-generated catch block
- System.out.println("(x, y) = (" + x + ", " + y + ")");
- e.printStackTrace();
- }
- return res;*/
- return body[status][x + y * 4] == 1;
- }
- public boolean isMember(int x, int y, boolean rotate){
- int tempStatus = status;
- if(rotate){
- tempStatus = (status + 1) % body.length;
- }
- return body[tempStatus][x + y * 4] == 1;
- }
- private class ShapeDriver implements Runnable {
- @Override
- public void run() {
- while(listener.isShapeMoveDownable(Shape.this)) {
- moveDown();
- listener.shapeMoveDown(Shape.this);
- try {
- Thread.sleep(1000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
- }
- }
- public Shape() {
- new Thread(new ShapeDriver()).start();
- }
- public void addShapeListenner(ShapeListener l) {
- if(l != null)
- this.listener = l;
- }
- public Color getColor() {
- return color;
- }
- public void setColor(Color color) {
- this.color = color;
- }
- }
产生图形的工厂类如下:
shapes中定义了一些预置的图形,colors中定义了一些图形可以使用的颜色
- package com.kodoyang.tetris.pojo;
- import java.awt.Color;
- import java.util.Random;
- import com.kodoyang.tetris.listen.ShapeListener;
- public class ShapeFactory {
- private int[][][] shapes = new int[][][]{
- {
- {
- 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
- },
- {
- 0, 1, 0, 0,
- 0, 1, 0, 0,
- 1, 1, 0, 0,
- 0, 0, 0, 0
- }
- },
- {
- {
- 1, 1, 1, 1,
- 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, 0
- }
- },
- {
- {
- 1, 1, 0, 0,
- 1, 1, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0
- }
- },
- {
- {
- 1, 1, 1, 0,
- 1, 0, 0, 0,
- 0, 0, 0, 0,
- 0, 0, 0, 0
- },
- {
- 1, 0, 0, 0,
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- 0, 0, 0, 0
- },
- {
- 0, 0, 1, 0,
- 1, 1, 1, 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
- }
- },
- {
- {
- 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
- },
- {
- 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
- }
- },
- {
- {
- 1, 0, 0, 0,
- 1, 1, 0, 0,
- 1, 0, 0, 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,
- 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, 1, 0,
- 1, 0, 0, 1,
- 1, 0, 0, 1,
- 0, 1, 1, 0
- },
- {
- 1, 0, 0, 1,
- 0, 1, 1, 0,
- 0, 1, 1, 0,
- 1, 0, 0, 1
- }
- },
- {
- {
- 0, 1, 0, 0,
- 1, 1, 1, 1,
- 0, 1, 0, 0,
- 0, 1, 0, 1
- },
- {
- 1, 0, 1, 0,
- 0, 0, 1, 0,
- 1, 1, 1, 1,
- 0, 0, 1, 0
- }
- },
- {
- {
- 0, 1, 0, 0,
- 1, 1, 1, 1,
- 1, 0, 0, 1,
- 1, 0, 0, 1
- },
- {
- 0, 1, 1, 0,
- 1, 0, 1, 0,
- 0, 1, 0, 1,
- 0, 1, 1, 0
- }
- }
- };
- private Color[] colors = new Color[]{
- Color.CYAN,
- Color.BLACK,
- Color.BLUE,
- Color.GREEN,
- Color.MAGENTA,
- Color.ORANGE,
- Color.PINK,
- Color.RED,
- Color.WHITE,
- Color.YELLOW
- };
- public Shape getShape(ShapeListener listener) {
- System.out.println("ShapeFactory's getShape");
- Shape shape = new Shape();
- shape.addShapeListenner(listener);
- int type = new Random().nextInt(shapes.length);
- shape.setBody(shapes[type]);
- shape.setStatus(0);
- shape.setColor(colors[new Random().nextInt(colors.length)]);
- return shape;
- }
- }
图形监听器的接口类:
实现这个接口的类必须要实现两个方法,让图形下移,判断图形是否可以移动
- package com.kodoyang.tetris.listen;
- import com.kodoyang.tetris.pojo.Shape;
- public interface ShapeListener {
- void shapeMoveDown(Shape shape);
- boolean isShapeMoveDownable(Shape shape);
- }
接受图形的静寂大地类:
当图形不能移动时就变为寂静大地了,构成静寂大地的是一个个的障碍物,
它通过计算图形下一步的位置来得出图形能不能移动的信息
如果障碍物出现在面板的顶部,就表示已经满了,游戏结束
判断某一行满行就把满了的行消掉
- package com.kodoyang.tetris.pojo;
- import java.awt.Color;
- import java.awt.Graphics;
- import com.kodoyang.tetris.util.Global;
- public class Ground {
- private int[][] obstacles = new int[Global.WIDTH][Global.HEIGHT];
- public void accept(Shape shape) {
- System.out.println("Ground's accept");
- for(int x = 0; x < 4; ++x){
- for(int y = 0; y < 4; ++y){
- if(shape.isMember(x, y, false)){
- obstacles[shape.getLeft() + x][shape.getTop() + y]
- = 1;
- }
- }
- }
- deleteFullLine();
- }
- private void deleteFullLine(){
- for(int y = Global.HEIGHT - 1; y >= 0; --y){
- boolean full = true;
- for(int x = 0; x < Global.WIDTH; ++x){
- if(obstacles[x][y] == 0)
- full = false;
- }
- if(full){
- deleteLine(y);
- }
- }
- }
- private void deleteLine(int lineNum) {
- for(int y = lineNum; y > 0; --y){
- for(int x = 0; x < Global.WIDTH; ++x){
- obstacles[x][y] = obstacles[x][y - 1];
- }
- }
- for(int x = 0; x < Global.WIDTH; ++x){
- //obstacles[x][0] = 0;
- }
- }
- public void drawMe(Graphics g) {
- System.out.println("Ground's drawMe");
- g.setColor(Color.DARK_GRAY);
- for(int x = 0; x < Global.WIDTH; ++x){
- for(int y = 0; y <Global.HEIGHT; ++y){
- if(obstacles[x][y] == 1){
- g.fill3DRect(
- x * Global.CELL_SIZE,
- y * Global.CELL_SIZE,
- Global.CELL_SIZE,
- Global.CELL_SIZE,
- true);
- }
- }
- }
- }
- public boolean isMoveable(Shape shape, int action){
- int left = shape.getLeft();
- int top = shape.getTop();
- switch(action){
- case Shape.LEFT:
- --left;
- break;
- case Shape.RIGHT:
- ++left;
- break;
- case Shape.DOWN:
- ++top;
- break;
- }
- for(int x = 0; x < 4; ++x){
- for(int y = 0; y < 4; ++y){
- if(shape.isMember(x, y, action == Shape.ROTATE)){
- if(top + y >= Global.HEIGHT ||
- left + x < 0 ||
- left + x >= Global.WIDTH ||
- obstacles[left + x][top + y] == 1)
- return false;
- }
- }
- }
- return true;
- }
- public boolean isFull(){
- for(int x = 0; x < Global.WIDTH; ++x){
- if(obstacles[x][0] == 1)
- return true;
- }
- return false;
- }
- }
用于显示的面板类:
它的画图方法就是在清空整个面板后,调用图形和静寂大地的画图方法
它的构造方法会决定游戏界面的大小
- package com.kodoyang.tetris.view;
- import java.awt.Color;
- import java.awt.Graphics;
- import javax.swing.JPanel;
- import com.kodoyang.tetris.pojo.Ground;
- import com.kodoyang.tetris.pojo.Shape;
- import com.kodoyang.tetris.util.Global;
- public class Panel extends JPanel {
- private Ground ground;
- private Shape shape;
- public void display(Ground ground, Shape shape) {
- System.out.println("TetrisPanel's display");
- this.ground = ground;
- this.shape = shape;
- this.repaint();
- }
- @Override
- protected void paintComponent(Graphics g) {
- // 重新显示
- g.setColor(Color.LIGHT_GRAY);
- g.fillRect(0, 0, Global.WIDTH * Global.CELL_SIZE,
- Global.HEIGHT * Global.CELL_SIZE);
- if(shape != null && ground != null){
- shape.drawMe(g);
- ground.drawMe(g);
- }
- }
- public Panel() {
- this.setSize(
- Global.WIDTH * Global.CELL_SIZE,
- Global.HEIGHT * Global.CELL_SIZE);
- }
- }
常量定义在全局类中:
每一个正方形小块的大小,面板拥有多少个正方形的边长个单位
- package com.kodoyang.tetris.util;
- public class Global {
- public static final int CELL_SIZE = 20;
- public static final int WIDTH = 20;
- public static final int HEIGHT = 25;
- }
控制它们的中央控制器:
它继承自按键事件的监听并实现了图形监听的接口
它控制当前活动图形以及产生它的工厂,障碍物,面板
产生一个新游戏的方法,判断图形是否可以下落,更新面板上的图形和障碍物,
- package com.kodoyang.tetris.control;
- import java.awt.event.KeyAdapter;
- import java.awt.event.KeyEvent;
- import com.kodoyang.tetris.listen.ShapeListener;
- import com.kodoyang.tetris.pojo.Ground;
- import com.kodoyang.tetris.pojo.Shape;
- import com.kodoyang.tetris.pojo.ShapeFactory;
- import com.kodoyang.tetris.view.Panel;
- public class Controller extends KeyAdapter implements ShapeListener {
- private Shape shape;
- private ShapeFactory shapeFactory;
- private Ground ground;
- private Panel panel;
- @Override
- public synchronized boolean isShapeMoveDownable(Shape shape) {
- // TODO Auto-generated method stub
- if(this.shape != shape){
- return false;
- }
- if( ground.isMoveable(shape, Shape.DOWN) )
- return true;
- ground.accept(this.shape);
- if(!ground.isFull()){
- this.shape = shapeFactory.getShape(this);
- }
- return false;
- }
- @Override
- public void keyPressed(KeyEvent e) {
- switch(e.getKeyCode()) {
- case KeyEvent.VK_UP:
- if(ground.isMoveable(shape, Shape.ROTATE))
- shape.rotate();
- break;
- case KeyEvent.VK_DOWN:
- // if(ground.isMoveable(shape, Shape.DOWN))
- if(isShapeMoveDownable(shape))
- shape.moveDown();
- break;
- case KeyEvent.VK_LEFT:
- if(ground.isMoveable(shape, Shape.LEFT))
- shape.moveLeft();
- break;
- case KeyEvent.VK_RIGHT:
- if(ground.isMoveable(shape, Shape.RIGHT))
- shape.moveRight();
- break;
- }
- panel.display(ground, shape);
- }
- @Override
- public void shapeMoveDown(Shape shape) {
- panel.display(ground, shape);
- }
- public void newGame() {
- shape = shapeFactory.getShape(this);
- }
- public Controller(ShapeFactory shapeFactory,
- Ground ground, Panel panel) {
- this.shapeFactory = shapeFactory;
- this.ground = ground;
- this.panel = panel;
- }
- }
跟多好文请查看:http://www.cnblogs.com/kodoyang/
俄罗斯方块游戏 --- java的更多相关文章
- java俄罗斯方块游戏代码
java俄罗斯方块游戏代码: package com; import java.awt.Color; import java.awt.Graphics; import java.awt.event.K ...
- 经典 HTML5 & Javascript 俄罗斯方块游戏
Blockrain.js 是一个使用 HTML5 & JavaScript 开发的经典俄罗斯方块游戏.只需要复制和粘贴一段代码就可以玩起来了.最重要的是,它是响应式的,无论你的显示屏多么宽都能 ...
- 从零开始---控制台用c写俄罗斯方块游戏(1)
从零开始---控制台用c写俄罗斯方块游戏(1) 很少写博文,一来自身知识有限,二来自己知道,已经有很多这样的博文了,三就是因为懒,文笔也一般,四来刚出来工作,时间也不多 之所以写这篇博文,是因为应群里 ...
- 用C写的俄罗斯方块游戏 By: hoodlum1980 编程论坛
/************************************ * Desc: 俄罗斯方块游戏 * By: hoodlum1980 * Email: jinfd@126.com * Dat ...
- 教你看懂网上流传的60行JavaScript代码俄罗斯方块游戏
早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用C写一个功能基本齐全的俄罗斯方块的话,大 ...
- 俄罗斯方块游戏JavaScript代码
JavaScript代码俄罗斯方块游戏 早就听说网上有人仅仅用60行JavaScript代码写出了一个俄罗斯方块游戏,最近看了看,今天在这篇文章里面我把我做的分析整理一下(主要是以注释的形式). 我用 ...
- 使用JS实现俄罗斯方块游戏
简单的JS俄罗斯方块游戏源码 效果图: 代码如下,复制即可使用: <!DOCTYPE html> <html> <head> <meta charset=&q ...
- C++编写简单的俄罗斯方块游戏
代码地址如下:http://www.demodashi.com/demo/14593.html C++编写简单的俄罗斯方块游戏 使用C++编写一个简单的俄罗斯方块游戏. 1 环境要求 使用C++图形库 ...
- electron写俄罗斯方块游戏(Tetris)
背景 在折腾ES6,突然想起大学时用c语言写过俄罗斯方块,本项目中主要是利用ES6的Class特性进行面向对象编程.项目采用node.js v6.2.0 + electron v1.1.0 进行桌面开 ...
随机推荐
- MyBatis学习总结_01_MyBatis快速入门
一.Mybatis介绍 MyBatis是一个支持普通SQL查询,存储过程和高级映射的优秀持久层框架.MyBatis消除了几乎所有的JDBC代码和参数的手工设置以及对结果集的检索封装.MyBatis可以 ...
- CentOS查看系统信息命令和方法
收集整理的一些linux查看系统信息的命令和方法: 一.linux查看服务器系统信息的方法: 1.查看主机名/内核版本/CPU构架: # uname -n -r -p -o localhost.loc ...
- JVM生产环境参数实例及分析
java application项目(非web项目) 改进前: -Xms128m-Xmx128m-XX:NewSize=64m-XX:PermSize=64m-XX:+UseConcMarkSweep ...
- 爬虫Larbin解析(二)——sequencer()
分析的函数: void sequencer() //位置:larbin-2.6.3/src/fetch/sequencer.ccvoid sequencer() { bool testPriority ...
- HDU 4664 Triangulation(SG函数)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4664 题意:给出一个n个点的凸包(不存在三点共线).每次可以选择两个点连线,但是任意两条线只能在顶点处 ...
- Itext导出PDF,word,图片案例
iText导出pdf.word.图片 一.前言 在企业的信息系统中,报表处理一直占比较重要的作用,本文将介绍一种生成PDF报表的Java组件--iText.通过在服务器端使用Jsp或JavaBean生 ...
- 无锁编程(一) - Double-checked Locking
Double-checked Locking,严格意义上来讲不属于无锁范畴,无论什么时候当临界区中的代码仅仅需要加锁一次,同时当其获取锁的时候必须是线程安全的,此时就可以利用 Double-che ...
- win7 64位系统 Oracle32bit + PL/SQL访问Orale服务,Oracle 11g的安装,中文乱码问题的解决
前几天装了个Oracle32bit客户端 + PL/SQL连接不上oracle,我安装完打开PL/SQL登录界面跟正常的界面不一样,没有那个连接为Normal.SYSDBA的选项,下面有解释,至于我为 ...
- 用VS2005开发WinCE程序调试图文教程
一.WinCE 模拟器通过ActiveSync 6.1(即Windows Mobile设备中心)连接P 1.启动WinCE模拟器 命令行: start .\DeviceEmulator.exe WI ...
- HDU 1527 (Wythoff 博弈) 取石子游戏
对于Wythoff博弈中的两个数列,An和Bn有这样的关系: An + n = Bn, An = floor(φ * n) 所以我们可以根据a b的差值来计算一个新的a出来看看这两个值是否相等. 想等 ...