For investors
股價:
5.36 美元 %For investors
股價:
5.36 美元 %認真做教育 專心促就業(yè)
獲獎學員:陳啟壯
所獲獎項:三等獎
內(nèi)容
俄羅斯方塊一共三個類中間用等號隔開
軟件的開發(fā)過程
1 明確業(yè)務需求
用自然語言,將業(yè)務功能描述清楚
...
2 業(yè)務分析
找到有哪些業(yè)務對象,和圖片的分析
tetris(俄羅斯方塊)
|-- score 累計分數(shù) |-- lines 銷毀的行數(shù) |-- Wall(墻 20行x10列) |-- 20row(行) |--10 col cell(列) |-- tetromino(4格方塊,有7種形態(tài)) |-- 4 cell |--nextOne 下一個準備下落的方塊 |-- 4 cell
3 數(shù)據(jù)模型,一切業(yè)務對象轉(zhuǎn)換為數(shù)字表示
場地按照行列劃分為20x10格子
格子有屬性row,col,color
4 類 設計
Tetris |-- int score |-- int lines |-- Cell[20][10] wall |-- Tetromino tetromino | |--Cell[4] cells |-- row |-- col |-- color
5 算法設計,就是如何利用數(shù)據(jù)的計算實現(xiàn)軟件的功能
4格方塊的初始形態(tài): I S Z J L T O
就在初始數(shù)據(jù)的數(shù)值狀態(tài)設計
四格方塊的下落計算:就是將每個格子的row+1
就是將下落的業(yè)務功能,轉(zhuǎn)換為數(shù)字計算實現(xiàn)
左右移動
下落流程控制:控制方塊下落與墻之間的控制關系
1 合理的文字流程描述
2 分析文字描述中的功能(動作)為方法
3 用流程控制語句連接方法實現(xiàn)功能
4 嚴格測試結(jié)果!TestCase
左右移動流程控制
分數(shù)計算
界面的繪制
鍵盤事件控制
旋轉(zhuǎn)流程控制
加速下降流程控制
開始流程控制(Timer)
暫停流程控制
繼續(xù)流程控制
結(jié)束流程控制
首先是Cell類,最基本的類包含3個私有屬性和get,set方法,重寫Object類的toString輸出方法,并規(guī)定格子所具有的3個移動功能
package com.tarena.tetris;
//包:小寫英文字母,域名倒寫.項目名
/**
* 最小的格子
*/ public class Cell{ private int row; private int col; private int color; public Cell(int row, int col, int color) { super(); this.row = row; this.col = col; this.color = color; } public int getCol() { return col; } public void setCol(int col) { this.col = col; } public int getColor() { return color; } public void setColor(int color) { this.color = color; } public int getRow() { return row; } public void setRow(int row) { this.row = row; } public void left(){ col--; } public void right(){ col++; } public void drop(){ row++; } public String toString(){ return row+","+col; } } =============================================================== package com.tarena.tetris; import java.util.Arrays; import java.util.Timer; import java.util.TimerTask; import javax.swing.JPanel;//是能夠顯示的矩形面板區(qū)域 import javax.swing.JFrame;//窗口框 import javax.swing.border.LineBorder;//實現(xiàn)邊框 import java.awt.Color; import java.awt.Font; import java.awt.Graphics; import java.awt.event.KeyAdapter; import java.awt.event.KeyListener; import java.awt.event.KeyEvent; /*
* 俄羅斯方塊類
* 俄羅斯方塊 擴展了(extends)系統(tǒng)的顯示面板,增加了墻和
* 正在下落的方塊
* */ public class Tetris extends JPanel{ public static final int ROWS = 20; public static final int COLS= 10; /*代表方塊下落著陸的墻*/ private Cell[][] wall = new Cell[ROWS][COLS]; /*是正在下落的方塊*/ private Tetromino tetromino; /*下一個進入的方塊*/ private Tetromino nextOne; private static int score; private int lines; Timer timer; private boolean gameOver = false; private boolean pause = false;//暫停 private static final int[] SCORE_LEVEL={0,1,4,10,100}; private static final Graphics Graphics = null; /*銷毀(destory)滿行*/ // 0 1 2 3 4 /*在Tetris中添加方法,檢查游戲是否結(jié)束*/ public void rotateRightAction(){ tetromino.rotateRight(); if(outOfBounds()||coincide()){ tetromino.rotateLeft(); } } public void rotateLeftAction(){ tetromino.rotateLeft(); if(outOfBounds()||coincide()){ tetromino.rotateRight(); } } /*在Tetris中添加方法,檢查游戲是否結(jié)束*/ private boolean gameOver(){ gameOver = wall[0][4]!=null; return gameOver; } /*在Tetris中添加方法*/ public void hardDropAction(){ while(canDrop()){ tetromino.softDrop(); } tetrominoLandToWall(); destroy(); if(gameOver()){ gameOverAction(); } nextTetromino(); } public void destroy(){ int lines = 0;//統(tǒng)計本次銷毀的行數(shù) for(int row = 0 ;row<wall.length;row++){ Cell[] line = wall[row]; if(fullCell(line)){ clearLine(row,wall); lines++;//每消除一行就累計加1 } } score += SCORE_LEVEL[lines]; this.lines +=lines; } public static void clearLine(int row,Cell[][] wall ){ for(int i=row;i>1;i--){ System.arraycopy(wall[i-1],0,wall[i],0,wall[i].length); } Arrays.fill(wall[0],null); } public static boolean fullCell(Cell []line){ for(int col = 0;col<line.length;col++){ if(line[col]==null) { return false;//找到空格子,這行沒有滿 } } return true; } public String toString(){//顯示全部的墻 String str = ""; for(int row = 0;row<ROWS;row++){ Cell[] line = wall[row]; for(int col = 0;col<COLS;col++){ Cell cell = line[col]; if(tetromino.contains (row,col)){ str +=row+","+col+" "; }else{ str = str + cell + " "; } } str +="\n"; } return str; } /*4格方塊下降流程 * 方塊移動到區(qū)域最下方或是著地到其他方塊上無法移動時, * 就會固定到該處,而新的方法快出現(xiàn)在區(qū)域上方開始下落。 * 如果能下降就繼續(xù)下降, * 否則就著陸到墻上,并且生成(隨機)下一個方塊 * */ public void softDropAction(){ if(canDrop()){//如果能下降 tetromino.softDrop();//方塊繼續(xù)下降 }else{ tetrominoLandToWall();//著陸到墻上 destroy();// if(gameOver()){ gameOverAction(); } nextTetromino();//生產(chǎn)(隨機)下一個方塊 } } private void startGameAction(){ gameOver = false; pause = false; score = 0; lines = 0; emptyWall(); nextTetromino(); repaint(); timer = new Timer(); timer.schedule(new TimerTask(){ public void run(){ softDropAction(); repaint(); } }, 500, 500); } private void emptyWall() { for(int row=0;row<ROWS;row++){ Arrays.fill(wall[row],null); } } /*清理游戲結(jié)束現(xiàn)場,如:停止定時器等*/ private void gameOverAction() { timer.cancel();//停止定時器 } /*檢查 方塊 是否能夠繼續(xù)下落:到底最低部,或者墻上 * 的下方有方塊,返回false不能下降,返回true可以下降 * */ public boolean canDrop(){ //檢查到底部 Cell[] cells = tetromino.getCells(); for(Cell cell:cells){ if(cell.getRow()==ROWS-1){ return false; } } //檢查墻上下方是否有方塊 for(Cell cell:cells){ int row = cell.getRow(); int col = cell.getCol(); Cell block = wall[row+1][col]; if(block!=null){ return false; } } return true; } /*方塊“著陸”到墻上, * 取出每個小cell * 找到cell的行號row和列號col * 將cell放置到wall[row][col]位置上 * */ public void tetrominoLandToWall(){ Cell[] cells = tetromino.getCells(); for(Cell cell:cells){ int row = cell.getRow(); int col = cell.getCol(); wall[row][col] = cell; } } /*生產(chǎn)(隨機)下一個方塊 * 1 下一個變?yōu)楫斍暗? * 2 隨機產(chǎn)生下一個 * */ public void nextTetromino(){ if(nextOne==null){//第一次nextOne是null時候先生產(chǎn)一個 nextOne = Tetromino.randomTetromino(); } tetromino = nextOne;//下一個變?yōu)楫斍暗? nextOne = Tetromino.randomTetromino();//隨機產(chǎn)生下一個 if(tetromino==null){//處理第一次使用時候下一個是null tetromino=Tetromino.randomTetromino(); } } /*以格子為單位左右移動方塊 * 1)如果遇到左右邊界就不能移動了 * 2)如果與墻上的格子相撞就不能移動了 * 變通為: * 1)先將方塊左移動, * 2)檢查(移動結(jié)果是否出界),或者(重合) * 3)如果檢查失敗,就右移的回來 * * */ public void moveLeftAction(){ tetromino.moveLeft(); if(outOfBounds() || coincide()){ tetromino.moveRight(); } } private boolean outOfBounds() { Cell[] cells = tetromino.getCells(); for (int i = 0; i < cells.length; i++) { Cell cell = cells[i]; int row = cell.getRow(); int col = cell.getCol(); if(row == ROWS||col<0||col>=COLS){ return true; } } return false; } private boolean coincide() { Cell[] cells = tetromino.getCells(); for (int i = 0; i < cells.length; i++) { Cell cell = cells[i]; int row = cell.getRow(); int col = cell.getCol(); if(row >0&&row<ROWS&&col<COLS&&col>0 &&wall[row][col]!=null){ return true;//重合 } } return false; } public void moveRightAction(){ tetromino.moveRight(); if(outOfBounds() || coincide()){ tetromino.moveLeft(); } } public static final int CELL_SIZE = 25; /*在Tetris.java中添加main方法 作為軟件的啟動方法*/ public static void main(String []args){ JFrame frame = new JFrame("俄羅斯方塊"); int wigth =(COLS+8)*CELL_SIZE +100; int height =ROWS*CELL_SIZE +100; frame.setSize(wigth,height); frame.setLocationRelativeTo(null);//居中 frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE);//設置關閉窗口就關閉軟件 frame.setLayout(null);//取消默認布局,取消自動充滿 Tetris panel = new Tetris(); panel.setLocation(45,25); panel.setSize((COLS+8)*CELL_SIZE,ROWS*CELL_SIZE); panel.setBorder(new LineBorder(Color.black)); frame.add(panel);//窗口中添加面板 frame.setVisible(true);//顯示窗口時候調(diào)用paint() panel.action(); } /*動作方法,這里是讓軟件開始動作,*/ public void action(){ //wall[18][2] = new Cell(18,2,0xff0000); startGameAction(); //重繪方法->盡快調(diào)用paint() //startGameAction(); //this 是當前Tetris面板 this.requestFocus();//為當前面板請求獲得輸入焦點 //this對象就獲得了輸入焦點,以后任何的 //鍵盤輸入(包括左右方向鍵)目標就是這個面板對象了! //addKeyLIstener添加鍵盤監(jiān)聽,監(jiān)聽那些按鍵輸入了 this.addKeyListener(new KeyAdapter(){ public void keyPressed(KeyEvent e) { int key = e.getKeyCode();//key按鍵 if(gameOver){ if(key==KeyEvent.VK_S){ startGameAction();//啟動游戲開始流程 } return; } if(pause){ if(key==KeyEvent.VK_C){ continueAction(); }return; } //System.out.println("Type:"+e.getKeyCode()); switch(key){ case KeyEvent.VK_RIGHT :moveRightAction();break; case KeyEvent.VK_LEFT :moveLeftAction();break; case KeyEvent.VK_DOWN :softDropAction();break; case KeyEvent.VK_UP :rotateRightAction();break; case KeyEvent.VK_SPACE :hardDropAction();break; case KeyEvent.VK_P :pasueAction();break; } //按鍵->方塊移動方法->改變方塊數(shù)據(jù)->repaint() //->盡快調(diào)用paint()->利用新數(shù)據(jù)繪制 repaint(); } private void continueAction() { pause = false; timer = new Timer(); timer.schedule(new TimerTask(){ public void run(){ softDropAction(); repaint(); } }, 500, 500); } private void pasueAction() { pause = true; timer.cancel(); } }); } //JPanel 類利用paint(涂畫)方法繪制界面 //子類重寫paint方法可以修改繪圖邏輯 public static final int BORDER_COLOR = 0x667799; public static final int BG_COLOR = 0xC3D5EA; public static final int FONT_COLOR = 0; public void paint(Graphics g) { //g 代表綁定在當前面板上的畫筆 //利用畫筆在當前 面板上 繪制了一串字符! paintBackground(g);//填充背景 paintWall(g);//繪制墻 paintTetromino(g);//繪制當前方塊 paintNextOne(g);//繪制下一個方塊 paintScore(g);//繪制分數(shù) paintTetrisBorder(g);//繪制邊線 } private void paintScore(Graphics g) { int x = 12 * CELL_SIZE; int y = 5 * CELL_SIZE; Font font = new Font(getFont().getName(),Font.BOLD,25); String str = "分數(shù): "+score; g.setColor(new Color(FONT_COLOR)); g.setFont(font); g.drawString(str, x, y); y+=2*CELL_SIZE; str = "行數(shù): "+lines; g.drawString(str, x, y); if(gameOver){ str = "(T_T)![s]再來!"; y+=2*CELL_SIZE; g.drawString(str, x, y); } if(pause){ str = "[c]繼續(xù)!"; y+=2*CELL_SIZE; g.drawString(str, x, y); }else{ str = "[p]暫停!"; y+=2*CELL_SIZE; g.drawString(str, x, y); } } private void paintNextOne(Graphics g) { if(nextOne==null)//如果沒有4格方塊就返回,不繪制 return; for (Cell cell : nextOne.getCells()) { int row = cell.getRow()+1; int col = cell.getCol()+9; int x = col*CELL_SIZE; int y = row*CELL_SIZE; g.setColor(new Color(cell.getColor())); g.fillRect(x, y, CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(x, y, CELL_SIZE, CELL_SIZE); } } private void paintTetromino(Graphics g) { if(tetromino==null)//如果沒有4格方塊就返回,不繪制 return; for (Cell cell : tetromino.getCells()) { int row = cell.getRow(); int col = cell.getCol(); int x = col*CELL_SIZE; int y = row*CELL_SIZE; g.setColor(new Color(cell.getColor())); g.fillRect(x, y, CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(x, y, CELL_SIZE, CELL_SIZE); } } private void paintWall(Graphics g) { for (int row = 0; row <ROWS; row++) { for (int col = 0; col < COLS; col++) { Cell cell = wall[row][col]; int x = col*CELL_SIZE; int y = row*CELL_SIZE; if(cell == null){ //g.setColor(new Color(BORDER_COLOR)); // g.drawRect(x, y, // CELL_SIZE, CELL_SIZE); }else{ g.setColor(new Color(cell.getColor())); g.fillRect(x, y, CELL_SIZE, CELL_SIZE); g.setColor(new Color(BORDER_COLOR)); g.drawRect(col*CELL_SIZE, row*CELL_SIZE, CELL_SIZE, CELL_SIZE); } } } } private void paintBackground(Graphics g) { g.setColor(new Color(BG_COLOR)); g.fillRect(0, 0, getWidth(), getHeight()); } private void paintTetrisBorder(Graphics g) { g.setColor(new Color(BORDER_COLOR)); g.drawRect(0, 0, CELL_SIZE*COLS, CELL_SIZE*ROWS-1); g.drawRect(CELL_SIZE*COLS,0, CELL_SIZE*8-1, CELL_SIZE*ROWS-1); } } =============================================================== package com.tarena.tetris; import java.util.Arrays; import java.util.Random; /* * 四格方塊類,有7種子類:I?。浴 Z J?。獭 * */ public abstract class Tetromino { public static final int I_COLOR =0xff6600; public static final int T_COLOR =0xffff00; public static final int S_COLOR =0x66ccff; public static final int Z_COLOR =0x00ff00; public static final int J_COLOR =0x0000ff; public static final int L_COLOR =0xcc00ff; public static final int O_COLOR =0xff0000; protected Cell[] cells = new Cell[4]; /*四格方塊的下落,是四個格子一起下落*/ public void softDrop(){ for(int i = 0;i<cells.length;i++){ cells[i].drop(); } } /*向左移動一步*/ public void moveLeft(){ for(int i = 0;i<cells.length;i++){ Cell cell = cells[i];//引用賦值 cell.left(); } } public void moveRight(){ //增強for循環(huán),是傳統(tǒng)數(shù)組迭代的“簡化版本”, //也稱為foreach循環(huán)(foreach迭代)(java 5以后) for(Cell cell:cells){//底層實現(xiàn)就是經(jīng)典迭代 cell.right(); } } public Cell[] getCells() { return cells; } protected Offset[] states;//旋轉(zhuǎn)的狀態(tài) protected class Offset{ int row0,col0; int row1,col1; int row2,col2; int row3,col3; public Offset(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; } } private int index = 10000-1; /*向右轉(zhuǎn)*/ public void rotateRight(){ index++; Offset offset = states[index%states.length]; Cell axis = cells[0];//找到軸(axis)的位置 cells[0].setRow(offset.row0+axis.getRow()); cells[0].setCol(offset.col0+axis.getCol()); cells[1].setRow(offset.row1+axis.getRow()); cells[1].setCol(offset.col1+axis.getCol()); cells[2].setRow(offset.row2+axis.getRow()); cells[2].setCol(offset.col2+axis.getCol()); cells[3].setRow(offset.row3+axis.getRow()); cells[3].setCol(offset.col3+axis.getCol()); } public void rotateLeft(){ index--; Offset offset = states[index%states.length]; Cell axis = cells[0];//找到軸(axis)的位置 cells[0].setRow(offset.row0+axis.getRow()); cells[0].setCol(offset.col0+axis.getCol()); cells[1].setRow(offset.row1+axis.getRow()); cells[1].setCol(offset.col1+axis.getCol()); cells[2].setRow(offset.row2+axis.getRow()); cells[2].setCol(offset.col2+axis.getCol()); cells[3].setRow(offset.row3+axis.getRow()); cells[3].setCol(offset.col3+axis.getCol()); } /*隨機生成一個具體方法*/ public static Tetromino randomTetromino() { Random random = new Random(); int type = random.nextInt(7);//0~6 switch(type){ case 0:return new I(); case 1:return new T(); case 2:return new S(); case 3:return new J(); case 4:return new Z(); case 5:return new L(); case 6:return new O(); } return null; } public String toString(){ return Arrays.toString(cells); } public boolean contains(int row, int col) { for(int i =0;i<cells.length;i++){ Cell cell = cells[i]; if(cell.getRow()==row && cell.getCol()==col){ return true; } } return false; } } class I extends Tetromino{ public I(){ cells[0] = new Cell(0,4,I_COLOR); cells[1] = new Cell(0,3,I_COLOR); cells[2] = new Cell(0,5,I_COLOR); cells[3] = new Cell(0,6,I_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,2,0), new Offset(0,0,0,-1,0,1,0,2), }; } } class T extends Tetromino{ public T(){ cells[0] = new Cell(0,4,T_COLOR); cells[1] = new Cell(0,3,T_COLOR); cells[2] = new Cell(0,5,T_COLOR); cells[3] = new Cell(1,4,T_COLOR); states = new Offset[]{ new Offset(0,0,1,0,-1,0,0,1), new Offset(0,0,0,-1,0,1,1,0), new Offset(0,0,1,0,-1,0,0,-1), new Offset(0,0,0,1,0,-1,-1,0), }; } } class S extends Tetromino{ public S(){ cells[0] = new Cell(0,4,S_COLOR); cells[1] = new Cell(0,5,S_COLOR); cells[2] = new Cell(1,3,S_COLOR); cells[3] = new Cell(1,4,S_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,1,0,1), new Offset(0,0,0,1,1,-1,1,0), }; } } class Z extends Tetromino{ public Z(){ cells[0] = new Cell(0,4,Z_COLOR); cells[1] = new Cell(0,3,Z_COLOR); cells[2] = new Cell(1,4,Z_COLOR); cells[3] = new Cell(1,5,Z_COLOR); states = new Offset[]{ new Offset(0,0,-1,1,0,1,1,0), new Offset(0,0,-1,-1,-1,0,0,1), }; } } class J extends Tetromino{ public J(){ cells[0] = new Cell(0,4,J_COLOR); cells[1] = new Cell(0,3,J_COLOR); cells[2] = new Cell(0,5,J_COLOR); cells[3] = new Cell(1,5,J_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,1,-1), new Offset(0,0,0,1,0,-1,-1,-1), new Offset(0,0,1,0,-1,0,-1,1), new Offset(0,0,0,-1,0,1,1,1), }; } } class L extends Tetromino{ public L(){ cells[0] = new Cell(0,4,L_COLOR); cells[1] = new Cell(0,3,L_COLOR); cells[2] = new Cell(0,5,L_COLOR); cells[3] = new Cell(1,3,L_COLOR); states = new Offset[]{ new Offset(0,0,-1,0,1,0,-1,-1), new Offset(0,0,0,1,0,-1,-1,1), new Offset(0,0,1,0,-1,0,1,1), new Offset(0,0,0,-1,0,1,1,-1), }; } } class O extends Tetromino{ public O(){ cells[0] = new Cell(0,4,O_COLOR); cells[1] = new Cell(0,5,O_COLOR); cells[2] = new Cell(1,4,O_COLOR); cells[3] = new Cell(1,5,O_COLOR); states = new Offset[]{ new Offset(0,0,0,1,1,0,1,1), new Offset(0,0,0,1,1,0,1,1), }; } }
【免責聲明】本文部分系轉(zhuǎn)載,轉(zhuǎn)載目的在于傳遞更多信息,并不代表本網(wǎng)贊同其觀點和對其真實性負責。如涉及作品內(nèi)容、版權和其它問題,請在30日內(nèi)與聯(lián)系我們,我們會予以更改或刪除相關文章,以保證您的權益!