目前学到Swing第二章,这两天没有学新知识,写了个俄罗斯方块。

写之前想不好怎么实现,找来别人的程序看了一下,再加上自己的想法,做了下面这个半成品,接下来可以加上各种菜单、按钮贴图等美化,都是些锦上添花的动作,繁琐但不难。

我觉得写俄罗斯方块,难点在于如何将方块的形状(七种)、状态(四种翻转)、动作(左、右、下落)等提炼成数组。 这里采用四维数组来表示每一种方块:【种类】【翻转】【X坐标】【Y坐标】,每种方块都画在一个4*4的大方块中,把这个大方块作为一个整体进行移动。再写了一个方法遍历大方块,判断该方块的位置是否合法。

有了合适的模型,再把每个步骤转化成代码,就不难了。

import java.awt.Color;

import java.awt.Dimension;

import java.awt.Font;

import java.awt.Graphics;

import java.awt.Toolkit;

import java.awt.event.ActionEvent;

import java.awt.event.ActionListener;

import java.awt.event.KeyAdapter;

import java.awt.event.KeyEvent;

import java.awt.image.BufferedImage;

import java.util.Arrays;

import java.util.Random;

import javax.swing.JFrame;

import javax.swing.JPanel;

import javax.swing.JCheckBox;

import javax.swing.Timer;

import javax.swing.JOptionPane;

public class KingTetris{

// 20行,10列

private final int ROW = 20;

private final int COL = 10;

// 每个方块边长,单位为像素

private final int LEN = 35;

// 游戏区域的左、上边距

private final int LEFT_MARGIN = LEN*2;

private final int UP_MARGIN = LEN;

// 面布大小,单位为像素

private final int AREA_WIDTH = LEN*22;

private final int AREA_HEIGHT = LEN*22;

// 是否需要网格

private boolean showGrid = true;

// 是否彩色,将来可以作为贴图控制

private boolean isColor = true;

// 得分

private int score = 0;

// 画布

private MyCanvas drawArea = new MyCanvas();

// 窗口

private JFrame f = new JFrame("俄罗斯方块");

// 画图用的image

private BufferedImage image = new BufferedImage(AREA_WIDTH, AREA_HEIGHT, BufferedImage.TYPE_INT_RGB);

private Graphics g = image.createGraphics();

// 数组,用于保存背景

private int[][] map = new int[COL][ROW];

// 数组,用于保存颜色

private Color[] color = new Color[]{Color.green, Color.red, Color.orange, Color.blue, Color.cyan, Color.yellow, Color.magenta, Color.gray};

//默认灰色

private final int DEFAULT = 7;

private Color[][] mapColor = new Color[COL][ROW];

//组件的横坐标

int wordX = LEN*14;// 组件的横坐标

int wordY = LEN*9; // 字的初始纵坐标

//shape的四个参数

private int type, state, x, y, nextType, nextState;

//如果刚开始游戏,由于无nextType,先给type等随机一个,下为首次开始游戏的标志

private boolean newBegin = true;

// 用数组来代表不同形状的下坠物,四维分别是类型Type、旋转状态State、横坐标X、纵坐标Y。画示意图即可得出坐标

// 方块共有7种,分别以S、Z、L、J、I、O、T这7个字母的形状来命名

private int[][][][] shape = new int[][][][]{

// S的四种翻转状态:

{ { {0,1,0,0}, {1,1,0,0}, {1,0,0,0}, {0,0,0,0} },

{ {0,0,0,0}, {1,1,0,0}, {0,1,1,0}, {0,0,0,0} },

{ {0,1,0,0}, {1,1,0,0}, {1,0,0,0}, {0,0,0,0} },

{ {0,0,0,0}, {1,1,0,0}, {0,1,1,0}, {0,0,0,0} } },

// Z:

{ { {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,0} },

{ {0,1,1,0}, {1,1,0,0}, {0,0,0,0}, {0,0,0,0} } },

// L:

{ { {0,0,0,0}, {1,1,1,0}, {0,0,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}, {0,1,0,0}, {0,1,1,1}, {0,0,0,0} },

{ {0,0,1,0}, {0,0,1,0}, {0,1,1,0}, {0,0,0,0} } },

// J:

{ { {0,0,0,0}, {0,0,1,0}, {1,1,1,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,1,1,1}, {0,1,0,0}, {0,0,0,0} },

{ {0,1,0,0}, {0,1,0,0}, {0,1,1,0}, {0,0,0,0} } },

// I:

{ { {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} },

{ {0,0,0,0}, {1,1,1,1}, {0,0,0,0}, {0,0,0,0} } },

// O:

{ { {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,1,1,0}, {0,1,1,0}, {0,0,0,0} } },

// T:

{ { {0,1,0,0}, {1,1,0,0}, {0,1,0,0}, {0,0,0,0} },

{ {0,0,0,0}, {1,1,1,0}, {0,1,0,0}, {0,0,0,0} },

{ {0,1,0,0}, {0,1,1,0}, {0,1,0,0}, {0,0,0,0} },

{ {0,1,0,0}, {1,1,1,0}, {0,0,0,0}, {0,0,0,0} } },

};

/**

* 初始化界面

*/

private void init(){

drawArea.setPreferredSize(new Dimension(AREA_WIDTH, AREA_HEIGHT));

f.add(drawArea);

JCheckBox gridCB = new JCheckBox("显示网格",true);

JCheckBox colorCB = new JCheckBox("彩色方块", false);

gridCB.setBounds(wordX, wordY-LEN,LEN,LEN);

colorCB.setBounds(wordX, wordY-2*LEN,LEN,LEN);

// paintArea();

// 加键盘监听器

f.addKeyListener(new KeyAdapter(){

public void keyPressed(KeyEvent e){

switch (e.getKeyCode()) {

case KeyEvent.VK_UP:

turn();

break;

case KeyEvent.VK_LEFT:

left();

break;

case KeyEvent.VK_RIGHT:

right();

break;

case KeyEvent.VK_DOWN:

down();

break;

}

}

});

Timer timer = new Timer(1000, new timerListener());

newShape();

timer.start();

// 窗口显示在屏幕正中

// Toolkit是抽象类,只能用getDefaultToolkit()方法来获取实例。

// getScreenSize()方法返回的是一个Dimension对象,还须用getWidth()获取宽度

f.pack();

int screenSizeX = (int)Toolkit.getDefaultToolkit().getScreenSize().getWidth();

int screenSizeY = (int)Toolkit.getDefaultToolkit().getScreenSize().getHeight();

int fSizeX = (int)f.getSize().getWidth();

int fSizeY = (int)f.getSize().getHeight();

f.setResizable(false);// 禁止改变Frame大小

f.setBounds((screenSizeX-fSizeX)/2, (screenSizeY-fSizeY)/2, fSizeX,fSizeY );

f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

f.setVisible(true);

}

/**

* 绘图

*/

private void paintArea(){

// 默认黑色,填充白色

g.setColor(Color.white);

g.fillRect(0, 0, AREA_WIDTH, AREA_HEIGHT);

// 方格线

// 先画最外围

g.setColor(Color.gray);

for (int offset = 0; offset <= 2; offset++){

g.drawRect(LEFT_MARGIN-offset, UP_MARGIN-offset, COL*LEN+offset*2, ROW*LEN+offset*2);

}

// 如果showGrid为true则显示网格

if(showGrid){

g.setColor(Color.gray);

// 9条竖线

for (int i = 1 ; i <= 9; i++){

g.drawLine(LEFT_MARGIN+LEN*i, UP_MARGIN, LEFT_MARGIN+LEN*i, UP_MARGIN+ROW*LEN);

}

// 19条横线

for(int i = 1; i <= 19; i++){

g.drawLine(LEFT_MARGIN, UP_MARGIN+LEN*i, LEFT_MARGIN+COL*LEN, UP_MARGIN+LEN*i);

}

}

// 右上角显示下一个shape

int offset2 = 3;// 边框粗细

int col = 4;// 右上角方框的列数

int row = 4;// 行数

g.setColor(Color.gray);

g.setFont(new Font("Microsoft YaHei Mono", Font.BOLD, 20));

g.drawString("下一个:", wordX, LEN*2);

int nextX = wordX;

int nextY = LEN*2;

//暂不画方框

// for (int offset = 0; offset <= 2; offset++){

// g.drawRect(nextX-offset+10, nextY+10-offset, col*LEN+offset*2, row*LEN+offset*2);

// }

//画下一次出现的下坠方块

g.setColor(isColor?color[nextType]:color[DEFAULT]);

for(int i = 0; i < 4; i++){

for(int j = 0; j < 4; j++){

if (shape[nextType][nextState][i][j]==1) {

g.fill3DRect(nextX+10+i*LEN, nextY+10+j*LEN, LEN, LEN,true);

}

}

}

g.setColor(Color.gray);

g.setFont(new Font("Times", Font.BOLD, 15));

g.drawString("玩法:", wordX, wordY+LEN*2);

g.drawString("上箭头:翻转", wordX, wordY+LEN*3);

g.drawString("左箭头:左移", wordX, wordY+LEN*4);

g.drawString("右箭头:右移", wordX, wordY+LEN*5);

g.drawString("下箭头:下落", wordX, wordY+LEN*6);

g.setFont(new Font("Times", Font.BOLD, 25));

g.drawString("得分:" + score, wordX, wordY+LEN*8);

//画下坠物shape

g.setColor(isColor?color[type]:color[DEFAULT]);

for(int i = 0; i < 4; i++){

for(int j = 0; j < 4; j++){

if (shape[type][state][i][j]==1) {

g.fill3DRect(LEFT_MARGIN+(x+i)*LEN, UP_MARGIN+(y+j)*LEN, LEN, LEN,true);

}

}

}

//画背景map

for(int i = 0; i < COL; i++){

for(int j = 0; j < ROW; j++){

if (map[i][j] == 1) {

g.setColor(mapColor[i][j]);

g.fill3DRect(LEFT_MARGIN+i*LEN, UP_MARGIN+j*LEN, LEN, LEN,true);

}

}

}

drawArea.repaint();

}

/**

* 自定义画布,重写paint()方法

*/

private class MyCanvas extends JPanel{

public void paint(Graphics g){

g.drawImage(image, 0, 0, null);

}

}

/**

* 判断位置是否合法

*/

private boolean check(int type, int state, int x, int y){

for(int i = 0; i < 4; i++){

for(int j = 0; j < 4; j++){

if ( (shape[type][state][i][j] == 1) && ( (x+i>=COL) || (x+i<0 ) || (y+j>=ROW) || (map[x+i][y+j]==1) ) ) {

return false;

}

}

}

return true;

}

/**

* 判断游戏是否结束

*/

private boolean isGameOver(int type, int state, int x, int y){

return !check(type, state, x, y);

}

/**

* 新建方块

*/

private void newShape(){

Random rand = new Random();

if(newBegin){

type = rand.nextInt(7);

state = rand.nextInt(4);

newBegin = false;

}

else{

type = nextType;

state = nextState;

}

nextType = rand.nextInt(7);

nextState = rand.nextInt(4);

x = 3;

y = 0;

// 如果游戏已结束,则重新开始

if(isGameOver(type, state, x, y)){

JOptionPane.showMessageDialog(f, "GAME OVER!");

newGame();

}

paintArea();

}

/**

* 新建游戏

*/

private void newGame(){

newMap();

score = 0;

newBegin = true;

}

/**

* 清空背景图

*/

private void newMap(){

for(int i = 0; i < COL; i++){

Arrays.fill(map[i],0);

}

}

/**

* 消行

*/

private void delLine(){

boolean flag = true;

int addScore = 0;

for(int j = 0; j < ROW; j++){

flag = true;

for( int i = 0; i < COL; i++){

if (map[i][j]==0){

flag = false;

break;

}

}

if(flag){

addScore += 10;

for(int t = j; t > 0; t--){

for(int i = 0; i

map[i][t] = map[i][t-1];

}

}

}

}

score += addScore*addScore/COL;

}

/**

* 计时器所用的事件监听器

*/

private class timerListener implements ActionListener{

public void actionPerformed(ActionEvent e){

if(check(type, state , x, y+1) ){

y = y +1;

}

else{

add(type, state, x, y);

delLine();

newShape();

}

paintArea();

}

}

/**

* 把shape存到map的add方法

*/

private void add(int type, int state, int x, int y){

for(int i = 0; i < 4; i++){

for(int j = 0; j < 4 ; j++){

if((y+j=0)&&(map[x+i][y+j]==0)){

map[x+i][y+j]=shape[type][state][i][j];

mapColor[x+i][y+j]=color[isColor?type:DEFAULT];

}

}

}

}

/**

* 下面为四个方向键对应的方法

*/

private void turn(){

int tmpState = state;

state = (state + 1)%4;

if (!check(type,state, x, y )) {

state = tmpState; //不能转就什么都不做

}

paintArea();

}

private void left(){

if(check(type,state, x-1, y)){

--x;

}

paintArea();

}

private void right(){

if (check(type,state, x+1, y)) {

++x;

}

paintArea();

}

private void down(){

if (check(type,state, x, y+1)) {

++y;

}

//如果下不去则固定之

else{

add(type, state, x, y);

delLine();

newShape();

}

paintArea();

}

/**

* 主函数

*/

public static void main(String[] args){

new KingTetris().init();

}

}

版权声明:本文为博主原创文章,未经博主允许不得转载。

java俄罗斯方块简单代码_Java简易俄罗斯方块相关推荐

  1. java语言简单代码_java语言编程如何实现一个最简单程序?

    在编程语言中,实践出结果是最重要的,其他的什么都是为此做准备,下面我们就来看看该如何编译一个最简单的java程序. 首先,启动你的编程软件,如eclipse等,具体可以网上了解, 再来,创建一个新的j ...

  2. java 的简单代码_java初学 简单代码

    1.简单的java程序 public class RightAndWrong { public static void main(String argc[]){ boolean bool = true ...

  3. java猜拳游戏代码_Java实现简单猜拳游戏

    本文实例为大家分享了java实现简单猜拳游戏的具体代码,供大家参考,具体内容如下 看网上的猜拳游戏那么多,但都是用switch输入数字,所以用if嵌套,写一个简单的猜拳游戏 package game; ...

  4. java弹球游戏代码_Java实现简单的弹球游戏

    本文实例为大家分享了Java实现简单的弹球游戏的具体代码,供大家参考,具体内容如下 该程序主要是用于对java图形化界面编程进行联系,程序实现全部采用的是AWT包下的类. 程序仅做参考,供学习使用. ...

  5. java 生产者消费者代码_Java生产者和消费者代码

    java 生产者消费者代码 This also helps us to understand the concept of synchronised multi-threading in java, ...

  6. java俄罗斯方块简单代码_求个简单的俄罗斯方块java代码,初学者能看懂的

    展开全部 java版的我没32313133353236313431303231363533e4b893e5b19e31333330346531有,给你看个js版的: .d {margin :1px;w ...

  7. java俄罗斯方块英文书籍_Java版俄罗斯方块

    Java版俄罗斯方块 08年写的一个Java版俄罗斯方块程序 界面做的中规中矩,每种形状颜色都不相同 程序控制还可以,没什么大的Bug 消磨时间的时候可以Down下来玩玩 下载链接:http://do ...

  8. java计算器简单源代码_java 简单的计算器程序实例代码

    java 简单的计算器程序 实现实例: import java.awt.*; import java.awt.event.*; import javax.swing.*; public class C ...

  9. java记事本打开功能_Java简易实现记事本的打开与保存

    记事本的打开与保存 一些总结 * Swing中有时方法不显示,需要把方setVisible(true)放到最后执行 * AWT中的TextArea默认是中间布局 * fileDialog对话框Load ...

  10. java发送简单邮件_Java程序实现发送简单文本邮件

    /** * Java程序实现发送简单文本邮件 * * @author Administrator * */ public class SendTextMail { // 定义发件人地址 public  ...

最新文章

  1. 设计模式之命令模式、举例分析、通俗易懂
  2. xampp mysql 内存溢出_php - SQLSTATE [HY000] [2002]连接被拒绝 - 堆栈内存溢出
  3. epoll的再次认识
  4. IEEE 1588-PTP简介
  5. 在网易游戏的第三年——Jerish的2021总结
  6. 《计算机科学与工程导论:基于IoT和机器人的可视化编程实践方法第2版》一2.1 工作流和可视化编程...
  7. C++操作Excel表格
  8. mutate  字段替换
  9. Signing for ‘xxx‘ requires a development team.
  10. super this
  11. 救生艇(双指针)-C语言
  12. webpack合成sprite图
  13. python绘制等值线图_使用matplotlib绘制等值线图
  14. 解决T400\T500\W500等安装win10驱动后黑屏问题
  15. android把音乐存到sd卡上,将离线音乐移动到Spotify for Android到SD卡 | MOS86
  16. Win10的截图功能
  17. 大数据行业部署实战2:环境大数据统计
  18. 咩了个咩三消小游戏算法逻辑分析 ,提供源码
  19. 宿州可以学中专计算机的学校有哪些,宿州中专学校排名榜,有哪些专业
  20. 今天端午节了,哈哈。。。

热门文章

  1. Codeproject收藏
  2. 中文字符:中国 的unicode/UTF-8/GBK编码
  3. linux发行版本中 图形方式的运行级,在大多数 Linux 发行版本中,图形方式的运行级定义为?...
  4. Qt配置OpenCV教程,无需复杂的编译过程,(详细版)
  5. 一文了解参数检验和非参数检验
  6. 集体智慧编程 - 读书笔记
  7. 说说浏览器缓存里的websql与 indexeddb
  8. poster模板_高分北斗大赛报名进行中,ppt、poster展示模板推送
  9. android iso打开软件,安卓手机如何打开.iso文件?
  10. 驱动大师显示无法连接服务器,教你win10系统无法连接到nvidia服务器的解决教程...