200字范文,内容丰富有趣,生活中的好帮手!
200字范文 > Java简易俄罗斯方块

Java简易俄罗斯方块

时间:2019-01-25 16:45:47

相关推荐

Java简易俄罗斯方块

目前学到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("俄罗斯方块");// 画图用的imageprivate 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);//画下坠物shapeg.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);}}}//画背景mapfor(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 <COL; 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<ROW)&&(x+i<COL)&&(x+i>=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();}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。