649
技術社區[雲棲]
JAVA俄羅斯方塊程序 勉強能看懂,但是我寫不出來,555
代碼貼出如下:
package com.zzk.cn; import java.awt.*; import java.awt.event.*; import javax.swing.*; import java.lang.*; class systemStatus { public systemStatus(int tmpX, int tmpY) { origin = new Point(tmpX, tmpY); iSystemStatus = 0; } public void drawSystemStatus(Graphics g) { g.setColor(Color.black); String strSystemStatus; switch (iSystemStatus) { case 0: strSystemStatus = "初始化完成...\"S\"鍵開始."; // 在狀態前麵空出一個漢字的寬度. break; case 1: strSystemStatus = "遊戲進行中...\"D\"鍵暫停,\"S\"鍵重新開始."; // 在狀態前麵空出一個漢字的寬度. break; case 2: strSystemStatus = "遊戲暫停中...\"D\"鍵恢複,\"S\"鍵重新開始."; // 在狀態前麵空出一個漢字的寬度. break; case 3: strSystemStatus = "GAMEOVER...\"S\"鍵重新開始."; // 在狀態前麵空出一個漢字的寬度. break; default: strSystemStatus = "係統發生嚴重異常...請立即退出!!!"; // 在狀態前麵空出一個漢字的寬度. break; } g.drawString(strSystemStatus, origin.x, origin.y); } public int getSystemStatus() { return iSystemStatus; } public void setSystemStatus(int iTmp) { iSystemStatus = iTmp; } private Point origin; // 得分字符串的最左邊字符左下角的坐標. private final int ROWINTERVAL = 15; // 2行字符串之間的行間距. private int iSystemStatus; // 存放係統的當前狀態;0-剛啟動或gameOver後重啟動的狀態 // (容器中沒有已固定的格子,分數為0,隻接受S鍵的輸入事件開始遊戲),1-玩家遊戲時的狀態,2-係統暫停時的狀態(計時器停止,隻接收P鍵或S鍵的輸入事件),3-GAMEOVER(計時器停止,隻接收S鍵的輸入事件). } class copyright { public copyright(int tmpX, int tmpY) { origin = new Point(tmpX, tmpY); } public void drawCopyright(Graphics g) { String strCopyright; strCopyright = "作者:"; g.drawString(strCopyright, origin.x, origin.y); strCopyright = "aaa"; g.drawString(strCopyright, origin.x, origin.y + ROWINTERVAL); strCopyright = "聯係方式:"; g.drawString(strCopyright, origin.x, origin.y + 2 * ROWINTERVAL); strCopyright = "暫無"; g.drawString(strCopyright, origin.x, origin.y + 3 * ROWINTERVAL); strCopyright = "版本號:"; g.drawString(strCopyright, origin.x, origin.y + 4 * ROWINTERVAL); strCopyright = "1.0"; g.drawString(strCopyright, origin.x, origin.y + 5 * ROWINTERVAL); } private final int ROWINTERVAL = 15; // 2行字符串之間的行間距. private Point origin; } class score { public score(int tmpX, int tmpY) { origin = new Point(tmpX, tmpY); iScore = 0; } public void restart() { iScore = 0; } public void drawScore(Graphics g) { g.setColor(Color.black); String strScore; strScore = "得分:"; g.drawString(strScore, origin.x, origin.y); strScore = " " + iScore; // 在分數前麵空出一個漢字的寬度. g.drawString(strScore, origin.x, origin.y + ROWINTERVAL); } public void addScore(int tmpLineNum) // tmpLineNum是消除的行數.根據消除的行數來計分. { switch (tmpLineNum) { case 1: iScore += 100; break; case 2: iScore += 300; break; case 3: iScore += 600; break; case 4: iScore += 1000; break; } } private final int ROWINTERVAL = 15; // 2行字符串之間的行間距. private Point origin; // 得分字符串的最左邊字符左下角的坐標. private int iScore; } class preview { public preview(int tmpX, int tmpY, int tmpHeightGrid, int tmpWidthGrid, int tmpHeight, int tmpWidth) { origin = new Point(tmpX, tmpY + tmpHeight); iHeightGrid = tmpHeightGrid; iWidthGrid = tmpWidthGrid; iHeight = tmpHeight; iWidth = tmpWidth; aryGrids = new grid[iHeightGrid][iWidthGrid]; calGridToPosition(); } public void calGridToPosition() // 計算出預覽框中各個格子左上角的坐標. { // 對容器中的4*4個格子進行初始化. for (int i = 0; i < iHeightGrid; i++) { for (int j = 0; j < iWidthGrid; j++) { aryGrids[i][j] = new grid(iHeight / iHeightGrid, iWidth / iWidthGrid, origin.x + j * (iWidth / iWidthGrid), origin.y - i * (iHeight / iHeightGrid), 1, 1, 0); } } } public void drawGrids(Graphics g, int[][] tmpRowColNos) // tmpRowColNos存放有方塊在預覽框中顯示的行號和列號. { // 在預覽框中顯示方塊. for (int i = 0; i < tmpRowColNos.length; i++) if ((tmpRowColNos[i][0] != -1) && (tmpRowColNos[i][1] != -1)) aryGrids[tmpRowColNos[i][0]][tmpRowColNos[i][1]] .drawDiamonds(g); // tmpRowColNos[i][0]是行號,tmpRowColNos[i][1]是列號. } public void drawGridFrame(Graphics g) { // 畫各個格子之間的分割線 g.setColor(Color.lightGray); // 畫格子的豎分隔線 for (int i = 1; i < iWidthGrid; i++) { g.drawLine(origin.x + i * (iWidth / iWidthGrid), origin.y, origin.x + i * (iWidth / iWidthGrid), origin.y - iHeight); } // 畫格子的橫分隔線 for (int i = 1; i < iHeightGrid; i++) { g.drawLine(origin.x, origin.y - i * (iHeight / iHeightGrid), origin.x + iWidth, origin.y - i * (iHeight / iHeightGrid)); } // 畫容器的整個外框 g.setColor(Color.black); // System.out.println("origin in drawGridFrame(): " // +origin.x+","+origin.y); g.drawRect(origin.x, origin.y - iHeight, iWidth, iHeight); } private Point origin; // 原點是整個預覽容器左下角的坐標. private int iHeightGrid; private int iWidthGrid; private int iHeight; private int iWidth; private grid[][] aryGrids; // 第1,2維的下標是用於確定是平麵上的哪個格子.第1維對應行號,取值範圍0~iHeightGrid-1;第2維對應列號,取值範圍是0~iWidthgrid-1 } // 方塊下落固定後,就變成了格子 class diamonds { public diamonds(int tmpRowNo, int tmpColNo) { initDiamondsTable(); referPoint[0] = tmpRowNo; referPoint[1] = tmpColNo; orgReferPoint[0] = tmpRowNo; orgReferPoint[1] = tmpColNo; createNew(); iPreStatusNo = iStatusNo; // 初始化,應付第1個方塊的第1次旋轉時遇到衝突時的情況.其實問題也不大因為剛開始時容器中沒有已固定的方塊會發生衝突. } public void restart() { referPoint[0] = orgReferPoint[0]; referPoint[1] = orgReferPoint[1]; } // 經過判斷方塊無法進行旋轉,調用此函數恢複方塊本次旋轉之前的狀態. public void unCircumrotate() { referPoint[0] = preReferPoint[0]; referPoint[1] = preReferPoint[1]; iStatusNo = iPreStatusNo; setAryDiamonds(); } public void circumrotate() { preReferPoint[0] = referPoint[0]; preReferPoint[1] = referPoint[1]; iPreStatusNo = iStatusNo; iStatusNo = diamondsTable[iSortNo][iStatusNo]; setAryDiamonds(); } // 重新生成一個新的方塊,實質是隨機設定方塊的類型和方塊的狀態,並將其位置複位. public void createNew() { // 獲得在方塊種類數範圍之內的隨機數. iSortNo = (int) (Math.random() * 100) % SORTNUM; // 每個方塊的狀態數是不同的. iStatusNo = (int) (Math.random() * 100) % diamondsTable[iSortNo].length; setAryDiamonds(); } // 返回方塊所占的行號,用於消行. public int[] getRowNos() { int[] rtnRowNos = new int[iHeightGrid]; // 注意返回數組中行號的排列順序是從大到小的.順序不能打亂,否則消行時會產生錯誤. // 對所有的方塊通用. for (int i = 0; i < iHeightGrid; i++) { rtnRowNos[i] = referPoint[0] + (iHeightGrid - i - 1); } return rtnRowNos; } // 返回方塊中所有有效部分在容器中顯示的行號和列號. public int[][] diamondsPosition() { int[][] rtnRowColNos = new int[iHeightGrid * iWidthGrid][2]; // 轉換,把方塊內有效部分的坐標都轉換成容器內的坐標,然後返回. for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (aryDiamonds[i][j] == 1) { rtnRowColNos[i * iWidthGrid + j][0] = referPoint[0] + i; rtnRowColNos[i * iWidthGrid + j][1] = referPoint[1] + j; } else // 把方塊中不用顯示的部分的行號和列號設為-1,便於區分. { rtnRowColNos[i * iWidthGrid + j][0] = -1; rtnRowColNos[i * iWidthGrid + j][1] = -1; } return (rtnRowColNos); } // 返回判定向左移動時判定接觸的方塊部分的行號和列號,數組中元素存放的順序無要求. public int[][] leftTouchGrids() { int[][] rtnRowColNos = new int[iHeightGrid][2]; // 第1維是接觸麵所占格子的數量,第2維的第1,2個元素是格子相對於容器的坐標. // 這裏默認方塊的接觸麵是連續的沒有空缺. for (int i = 0; i < iHeightGrid; i++) { for (int j = 0; j < iWidthGrid; j++) { if (aryDiamonds[i][j] == 1) { rtnRowColNos[i][0] = referPoint[0] + i; rtnRowColNos[i][1] = referPoint[1] + j; break; } } } /* * 隻適合方塊5的代碼. if(iSortNo==5) { rtnRowColNos[0][0]=referPoint[0]; * rtnRowColNos[0][1]=referPoint[1]; rtnRowColNos[1][0]=referPoint[0]; * rtnRowColNos[1][1]=referPoint[1]+1; } */ return rtnRowColNos; } // 返回判定向右移動時判定接觸的方塊部分的坐標 public int[][] rightTouchGrids() { int[][] rtnRowColNos = new int[iHeightGrid][2]; for (int i = 0; i < iHeightGrid; i++) { for (int j = iWidthGrid - 1; j >= 0; j--) { if (aryDiamonds[i][j] == 1) { rtnRowColNos[i][0] = referPoint[0] + i; rtnRowColNos[i][1] = referPoint[1] + j; break; } } } return rtnRowColNos; } // 返回判定向下移動時判定接觸的方塊部分的坐標 public int[][] downTouchGrids() { int[][] rtnRowColNos = new int[iWidthGrid][2]; for (int i = 0; i < iWidthGrid; i++) { for (int j = 0; j < iHeightGrid; j++) { if (aryDiamonds[j][i] == 1) { rtnRowColNos[i][0] = referPoint[0] + j; rtnRowColNos[i][1] = referPoint[1] + i; break; } } } return rtnRowColNos; } public void initDiamondsTable() { diamondsTable = new int[SORTNUM][]; diamondsTable[0] = new int[2]; diamondsTable[1] = new int[4]; diamondsTable[2] = new int[4]; diamondsTable[3] = new int[2]; diamondsTable[4] = new int[2]; diamondsTable[5] = new int[1]; diamondsTable[6] = new int[4]; // 存放各種方塊旋轉後的下一個狀態號. for (int i = 0; i < diamondsTable.length; i++) for (int j = 0; j < diamondsTable[i].length; j++) if (j == diamondsTable[i].length - 1) diamondsTable[i][j] = 0; else diamondsTable[i][j] = j + 1; } public void setAryDiamonds() { switch (iSortNo) { case 0: switch (iStatusNo) { case 0: iHeightGrid = 4; iWidthGrid = 1; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) aryDiamonds[i][j] = 1; // 對於方塊0的狀態0,4*1矩陣中的每一個元素都是顯示部分. break; case 1: iHeightGrid = 1; iWidthGrid = 4; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) aryDiamonds[i][j] = 1; break; } break; case 1: switch (iStatusNo) { case 0: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 1) && (j == 1)) || ((i == 2) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 1: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 1)) || ((i == 0) && (j == 2))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 2: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 1) && (j == 0))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 3: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 1) && (j == 0)) || ((i == 1) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; } break; case 2: switch (iStatusNo) { case 0: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 1) && (j == 0)) || ((i == 2) && (j == 0))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 1: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 1) && (j == 1)) || ((i == 1) && (j == 2))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 2: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 1)) || ((i == 1) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 3: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 0) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; } break; case 3: switch (iStatusNo) { case 0: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 2) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 1: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 2)) || ((i == 1) && (j == 0))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; } break; case 4: switch (iStatusNo) { case 0: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 1)) || ((i == 2) && (j == 0))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 1: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 1) && (j == 2))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; } break; case 5: iHeightGrid = 2; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) aryDiamonds[i][j] = 1; break; case 6: switch (iStatusNo) { case 0: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 1) && (j == 0)) || ((i == 1) && (j == 2))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 1: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 1)) || ((i == 2) && (j == 1))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 2: iHeightGrid = 2; iWidthGrid = 3; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 0) && (j == 2))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; case 3: iHeightGrid = 3; iWidthGrid = 2; aryDiamonds = new int[iHeightGrid][iWidthGrid]; for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) if (((i == 0) && (j == 0)) || ((i == 2) && (j == 0))) aryDiamonds[i][j] = 0; else aryDiamonds[i][j] = 1; break; } break; } } public int getWidthGrid() { return iWidthGrid; } public int getStatusNo() { return iStatusNo; } public void setStatusNo(int tmpStatusNo) { iStatusNo = tmpStatusNo; } public int getSortNo() { return iSortNo; } public void setSortNo(int tmpSortNo) { iSortNo = tmpSortNo; } public int[] getReferPoint() { return (referPoint); } public void setReferPoint(int tmpRowNo, int tmpColNo) { referPoint[0] = tmpRowNo; referPoint[1] = tmpColNo; } private final int SORTNUM = 7; // 目前有7種方塊,各方塊在各狀態定義的圖案參考開發文檔. private int[] orgReferPoint = new int[2]; // 存放調用構造函數時,得到的參照點的行號和列號參數. private int[] preReferPoint = new int[2]; // 用於解決超出右邊界進行調整後,又發生方塊和已固定方塊發生衝突的情況. private int[] referPoint = new int[2]; // 1維數組記錄左下角元素在容器中所處的位置,存放行號和列號,不是存放象素. private int iHeightGrid; // 方塊矩陣高占的格子數. private int iWidthGrid; // 方塊矩陣寬占的格子數. private int[][] aryDiamonds; // 2維矩陣,用於繪製方塊.第1維對應行號,取值範圍是0~iHeightGrid-1,從下到上編號從小到大;第2維對應列號,取值範圍是0~iWidthGrid-1,從左到右編號從小到大.0表示不是方塊的顯示部分,1表示是方塊的顯示部分. private int iSortNo; // 存放當前方塊的種類編號,取值範圍0~6,編號對應的圖案查看開發文檔 private int iStatusNo; // 存放當前方塊的狀態編號,狀態編號隨方塊的旋轉而改變. private int[][] diamondsTable; // 此2維數組中第1維是代表方塊的種類,第2維是代表方塊的狀態,數組中存放的是方塊下一個狀態的編號 private int iPreStatusNo; // 存放方塊在旋轉前的上一個狀態.旋轉方塊不會改變方塊的種類號. } class grid { public grid(int tmpHeight, int tmpWidth, int tmpX, int tmpY, int tmpDiffX, int tmpDiffY, int tmpInUse) { iHeight = tmpHeight; iWidth = tmpWidth; XYPosition = new Point(tmpX, tmpY - tmpHeight); diffX = tmpDiffX; diffY = tmpDiffY; inUse = tmpInUse; } public void drawGrid(Graphics g) { if (inUse == 1) { g.setColor(Color.black); g.fillRect(XYPosition.x + diffX, XYPosition.y + diffY, iWidth - 2 * diffX, iHeight - 2 * diffY); } } public void drawDiamonds(Graphics g) { g.setColor(Color.black); g.fillRect(XYPosition.x + diffX, XYPosition.y + diffY, iWidth - 2 * diffX, iHeight - 2 * diffY); } public int getInUse() // 返回當前的格子是否被使用 { return inUse; } public void setInUse(int tmpMode) // 參數tmpMode為0-未使用,為1-已使用 { inUse = tmpMode; } private int iHeight; // 格子在Y軸方向上的高度,以象素為單位 private int iWidth; // 格子在X軸方向上的寬度,以象素為單位 private Point XYPosition; // 格子左上角的實際坐標 private int diffX; // 格子中圖黑部分在X軸方向單邊縮進象素 private int diffY; // 格子中圖黑部分在Y軸方向單邊縮進象素 private int inUse; // 存放整型0或1.0表示格子已被占用,1表示格子未被占用 // 還要加個有關顏色的參數,可以由用戶設置格子顏色 } class board { public board(int tmpX, int tmpY, int tmpHeightGrid, int tmpWidthGrid, int tmpHeight, int tmpWidth, int tmpBufferHeightGrid, int tmpBufferHeight) // tmpX,tmpY是容器右上角的X,Y坐標.tmpHeightGrid,tmpWidthGrid是高占幾格和寬占幾格,以格子為單位.tmpHeight,tmpWidth是高和寬,以象素為單位.tmpBufferHeightGrid和tmpBufferHeight是緩衝區,讓方塊作進入容器的準備工作. { // System.out.println("in board() tmpX="+tmpX+" tmpY="+tmpY+" tmpHeight="+tmpHeight); origin = new Point(tmpX, tmpY + tmpHeight); // System.out.println("origin in board(): " // +origin.x+","+origin.y); iHeightGrid = tmpHeightGrid; iWidthGrid = tmpWidthGrid; iHeight = tmpHeight; iWidth = tmpWidth; iBufferHeightGrid = tmpBufferHeightGrid; iBufferHeight = tmpBufferHeight; aryGrids = new grid[iHeightGrid + iBufferHeightGrid][iWidthGrid]; // 包括緩衝行,便於進行GAMEOVER判斷. calGridToPosition(); objDiamonds = new diamonds(iHeightGrid, iWidthGrid / 2 - 1); objSystemStatus = new systemStatus(10, 10 + 300 + 20); } public void restart() // 把所有格子的狀態設為未使用. { for (int i = 0; i < iHeightGrid + iBufferHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) aryGrids[i][j].setInUse(0); } public int gameOverChk() // 檢查是否已經GAMEOVER;返回值=0,沒有GAMEOVER;=1,已經GAMEOVER. { int rtnGameOver = 0; for (int i = 0; i < iWidthGrid; i++) if (aryGrids[iHeightGrid][i].getInUse() == 1) { rtnGameOver = 1; break; } return rtnGameOver; } public int conflictChk() // 方塊旋轉後的衝突檢測.返回值=0,無衝突;=1,有衝突. { int isConflict = 0; // =0,無衝突;=1,有衝突 int[][] rtnRowColNos; rtnRowColNos = objDiamonds.diamondsPosition(); for (int i = 0; i < rtnRowColNos.length; i++) if (((rtnRowColNos[i][0] != -1) && (rtnRowColNos[i][1] != -1)) && aryGrids[rtnRowColNos[i][0]][rtnRowColNos[i][1]] .getInUse() == 1) { isConflict = 1; break; } return isConflict; } public void adjust() // 方塊在旋轉後,某部分超出了容器的邊界就要進行調整操作 { int[] rtnReferPoint; int tmpWidthGrid; tmpWidthGrid = objDiamonds.getWidthGrid(); rtnReferPoint = objDiamonds.getReferPoint(); if ((rtnReferPoint[1] + tmpWidthGrid) > iWidthGrid) objDiamonds.setReferPoint(rtnReferPoint[0], iWidthGrid - tmpWidthGrid); } public int removeRows() // 進行消行操作.返回值為消去的行數. { int[] rtnRowNos; // 存放方塊所占行的行號. int[] fullRowNos; // 存放已滿行的行號. int fullCount = 0; // 存放已滿行的行數. rtnRowNos = objDiamonds.getRowNos(); // System.out.print("In removeRows: "); // for(int i=0;i<rtnRowNos.length;i++) // { // System.out.print(rtnRowNos[i]+","); // } // System.out.println(); fullRowNos = new int[rtnRowNos.length]; for (int i = 0; i < fullRowNos.length; i++) fullRowNos[i] = 0; // 方塊所在行中,如果有行已滿,則取出此行的行號. for (int i = 0; i < rtnRowNos.length; i++) { int rowNo; int isFull; // 0-當前行未滿,1-當前行已滿. rowNo = rtnRowNos[i]; isFull = 1; for (int j = 0; j < iWidthGrid; j++) { // System.out.println("In removeRows: aryGrids["+rowNo+"]["+j+"].getInUse()="+aryGrids[rowNo][j].getInUse()); if (aryGrids[rowNo][j].getInUse() == 0) { isFull = 0; break; } } // System.out.println("In removeRows: isFull="+isFull); if (isFull == 1) { fullRowNos[fullCount] = rowNo; fullCount++; } } // System.out.println("In removeRows: fullCount="+fullCount); for (int i = 0; i < fullCount; i++) { int rowNo; rowNo = fullRowNos[i]; for (int j = rowNo; j < iHeightGrid; j++) { for (int k = 0; k < iWidthGrid; k++) { int tmpMode; tmpMode = aryGrids[j + 1][k].getInUse(); aryGrids[j][k].setInUse(tmpMode); } } } return fullCount; } public void calGridToPosition() // 計算出各個格子左上角的坐標. { // 對容器中的20*10個格子進行初始化. for (int i = 0; i < (iHeightGrid + iBufferHeightGrid); i++) { for (int j = 0; j < iWidthGrid; j++) { aryGrids[i][j] = new grid( (iHeight + iBufferHeight) / (iHeightGrid + iBufferHeightGrid), iWidth / iWidthGrid, origin.x + j * (iWidth / iWidthGrid), origin.y - i * ((iHeight + iBufferHeight) / (iHeightGrid + iBufferHeightGrid)), 2, 2, 0); } } } public void drawGrids(Graphics g) { // 顯示已經固定的格子. for (int i = 0; i < iHeightGrid; i++) for (int j = 0; j < iWidthGrid; j++) aryGrids[i][j].drawGrid(g); // 顯示方塊. int[][] rtnRowColNos; rtnRowColNos = objDiamonds.diamondsPosition(); // System.out.println("in drawGrids: rtnRowColNos.length=" // +rtnRowColNos.length); // for(int i=0;i<rtnRowColNos.length;i++) // { // System.out.println("rtnRowColNos["+i+"][0]="+rtnRowColNos[i][0]+","+"rtnRowColNos["+i+"][1]="+rtnRowColNos[i][1]); // } for (int i = 0; i < rtnRowColNos.length; i++) if ((rtnRowColNos[i][0] != -1) && (rtnRowColNos[i][1] != -1)) if (rtnRowColNos[i][0] < iHeightGrid) aryGrids[rtnRowColNos[i][0]][rtnRowColNos[i][1]] .drawDiamonds(g); // rtnRowColNos[i][0]是行號,rtnRowColNos[i][1]是列號. } public void drawGridFrame(Graphics g) { // 畫各個格子之間的分割線 g.setColor(Color.lightGray); // 畫格子的豎分隔線 for (int i = 1; i < iWidthGrid; i++) { g.drawLine(origin.x + i * (iWidth / iWidthGrid), origin.y, origin.x + i * (iWidth / iWidthGrid), origin.y - (iHeight)); } // 畫格子的橫分隔線 for (int i = 1; i < iHeightGrid; i++) { g.drawLine( origin.x, origin.y - i * ((iHeight + iBufferHeight) / (iHeightGrid + iBufferHeightGrid)), origin.x + iWidth, origin.y - i * ((iHeight + iBufferHeight) / (iHeightGrid + iBufferHeightGrid))); } // 畫容器的整個外框 g.setColor(Color.black); // System.out.println("origin in drawGridFrame(): " // +origin.x+","+origin.y); g.drawRect(origin.x, origin.y - iHeight, iWidth, iHeight); } public int getHeightGrid() { return iHeightGrid; } public int getWidthGrid() { return iWidthGrid; } public int getBufferHeightGrid() { return iBufferHeightGrid; } public int getAryGrids(int i, int j) // i是行號對應y軸;j是列號對應x軸. { return aryGrids[i][j].getInUse(); } public void setAryGrids(int i, int j, int tmpMode) // 設置矩陣中行號為i,列號為j的格子的狀態(使用或未使用);參數tmpMode=0表示把當前格設為未使用,=1表示把當前格設為使用. { aryGrids[i][j].setInUse(tmpMode); } private Point origin; // 原點是整個方塊容器左下角的坐標. private int iHeightGrid; // 存放高有幾格 private int iWidthGrid; // 存放寬有幾格 private int iHeight; // 存放容器的高度,以象素為單位 private int iWidth; // 存放容器的寬度,以象素為單位 private int iBufferHeightGrid; // iBufferHeightGrid和iBufferHeight是緩衝區,讓方塊作進入容器的準備工作. private int iBufferHeight; private grid[][] aryGrids; // 第1,2維是用於確定是平麵上的哪個格子.第1維對應行號,取值範圍0~iHeightGrid+iBufferHeightGrid-1;第2維對應列號,取值範圍是0~iWidthGrid-1. public diamonds objDiamonds; public systemStatus objSystemStatus; } class eluosiPanel extends JPanel implements KeyListener, ActionListener { public eluosiPanel() { b = new board(10, 10, 20, 10, 300, 150, 10, 150); objPreview = new preview(10 + 150 + 10, 10, 5, 5, 50, 50); objPreDiamonds = new diamonds(0, 0); addKeyListener(this); objScore = new score(10 + 150 + 10, 10 + 50 + 20); objCopyright = new copyright(10 + 150 + 10, 10 + 50 + 20 + 15 + 20 + 50); t = new Timer(delay, this); } // 覆蓋eluosiPanel類的isFocusTraversable方法,使麵板能夠獲得焦點. public boolean isFocusTraversable() { return (true); } // 通過方向鍵左右下,來控製方塊5的移動. public void keyPressed(KeyEvent evt) { int keyCode = evt.getKeyCode(); int[] rtnRowColNo; // 存放方塊中的參照格子的行號和列號. rtnRowColNo = b.objDiamonds.getReferPoint(); // 移動前要先判斷是否會超出容器的邊框. if (keyCode == KeyEvent.VK_LEFT) { if (b.objSystemStatus.getSystemStatus() != 0 && b.objSystemStatus.getSystemStatus() != 2 && b.objSystemStatus.getSystemStatus() != 3) { if (rtnRowColNo[1] - 1 >= 0) { t.stop(); // 方塊5向左移動時,如果遇到已使用的格子,就取消向左移動的情況. int isTouch = 0; // 為0表示未接觸,為1表示已接觸. int[][] aryLeftTouchGrids; // 存放方塊左側接觸麵上格子的行號和列號. aryLeftTouchGrids = b.objDiamonds.leftTouchGrids(); for (int i = 0; i < aryLeftTouchGrids.length; i++) { if (b.getAryGrids(aryLeftTouchGrids[i][0], aryLeftTouchGrids[i][1] - 1) == 1) { isTouch = 1; break; } } if (isTouch == 0) b.objDiamonds.setReferPoint(rtnRowColNo[0], rtnRowColNo[1] - 1); t.start(); } } } else if (keyCode == KeyEvent.VK_RIGHT) { if (b.objSystemStatus.getSystemStatus() != 0 && b.objSystemStatus.getSystemStatus() != 2 && b.objSystemStatus.getSystemStatus() != 3) { if (rtnRowColNo[1] + 1 < (b.getWidthGrid() - (b.objDiamonds .getWidthGrid() - 1))) { t.stop(); // 方塊5向右移動時,如果遇到已使用的格子,就取消向右移動的情況. int isTouch = 0; // 為0表示未接觸,為1表示已接觸. int[][] aryRightTouchGrids; aryRightTouchGrids = b.objDiamonds.rightTouchGrids(); for (int i = 0; i < aryRightTouchGrids.length; i++) { if (b.getAryGrids(aryRightTouchGrids[i][0], aryRightTouchGrids[i][1] + 1) == 1) { isTouch = 1; break; } } if (isTouch == 0) b.objDiamonds.setReferPoint(rtnRowColNo[0], rtnRowColNo[1] + 1); t.start(); } } } else // 按了"向下鍵"的事件處理比較特殊,如果位置合適,方塊5將變為固定的格子. if (keyCode == KeyEvent.VK_DOWN) { if (b.objSystemStatus.getSystemStatus() != 0 && b.objSystemStatus.getSystemStatus() != 2 && b.objSystemStatus.getSystemStatus() != 3) { // t.stop(); //按向下鍵時方塊不自動下落. // 方塊5已經沉底,要被固定的情況 if (rtnRowColNo[0] - 1 < 0) { int[][] rtnPosition; rtnPosition = b.objDiamonds.diamondsPosition(); // 把容器中與方塊的顯示部分位置相對應的格子設為已使用. for (int i = 0; i < rtnPosition.length; i++) if ((rtnPosition[i][0] != -1) && (rtnPosition[i][1] != -1)) b.setAryGrids(rtnPosition[i][0], rtnPosition[i][1], 1); // 對已滿的行要進行消行處理. int tmpLineNum; tmpLineNum = b.removeRows(); objScore.addScore(tmpLineNum); // 消行後要累加分數. if (b.gameOverChk() == 1) { // System.out.println("GAME OVER!!"); t.stop(); b.objSystemStatus.setSystemStatus(3); } else { // 重新生成一個新的方塊,實質是設定方塊的類型,並將其位置複位. b.objDiamonds.setSortNo(objPreDiamonds.getSortNo()); b.objDiamonds.setStatusNo(objPreDiamonds.getStatusNo()); b.objDiamonds.setAryDiamonds(); objPreDiamonds.createNew(); b.objDiamonds.setReferPoint(b.getHeightGrid(), b.getWidthGrid() / 2 - 1); // t.start(); } } else { // 方塊5向下移動遇到已使用的格子而固定的情況 int isTouch = 0; // 為0表示未接觸,為1表示已接觸. int[][] aryDownTouchGrids; aryDownTouchGrids = b.objDiamonds.downTouchGrids(); for (int i = 0; i < aryDownTouchGrids.length; i++) { if (b.getAryGrids(aryDownTouchGrids[i][0] - 1, aryDownTouchGrids[i][1]) == 1) { isTouch = 1; break; } } if (isTouch == 1) // 向下移動已發生了接觸. { int[][] rtnPosition; rtnPosition = b.objDiamonds.diamondsPosition(); // 把容器中與方塊5位置相對應的格子設為已使用. for (int i = 0; i < rtnPosition.length; i++) if ((rtnPosition[i][0] != -1) && (rtnPosition[i][1] != -1)) b.setAryGrids(rtnPosition[i][0], rtnPosition[i][1], 1); // 對已滿的行要進行消行處理. int tmpLineNum; tmpLineNum = b.removeRows(); objScore.addScore(tmpLineNum); if (b.gameOverChk() == 1) { t.stop(); System.out.println("GAME OVER!!"); b.objSystemStatus.setSystemStatus(3); } else { // 重新生成一個新的方塊,實質是設定方塊的類型,並將其位置複位. b.objDiamonds.setSortNo(objPreDiamonds.getSortNo()); b.objDiamonds.setStatusNo(objPreDiamonds .getStatusNo()); b.objDiamonds.setAryDiamonds(); objPreDiamonds.createNew(); b.objDiamonds.setReferPoint(b.getHeightGrid(), b.getWidthGrid() / 2 - 1); // t.start(); } } else { b.objDiamonds.setReferPoint(rtnRowColNo[0] - 1, rtnRowColNo[1]); // t.start(); } } } } else /* * if(keyCode==KeyEvent.VK_UP) { * if(b.objSystemStatus.getSystemStatus()!= * 0&&b.objSystemStatus.getSystemStatus * ()!=2&&b.objSystemStatus.getSystemStatus()!=3) { * if(rtnRowColNo[0]+1<(b.getHeightGrid()+b.getBufferHeightGrid()-1)) * b.objDiamonds.setReferPoint(rtnRowColNo[0]+1,rtnRowColNo[1]); } } * else */ if (keyCode == KeyEvent.VK_SPACE) { if (b.objSystemStatus.getSystemStatus() != 0 && b.objSystemStatus.getSystemStatus() != 2 && b.objSystemStatus.getSystemStatus() != 3) { t.stop(); // 翻轉時方塊不自動下落 b.objDiamonds.circumrotate(); b.adjust(); if (b.conflictChk() == 1) // 進行衝突檢查,如果旋轉後方塊與容器中已固定的方塊發生位置衝突,必須取消這次旋轉. b.objDiamonds.unCircumrotate(); t.start(); } } else if (keyCode == KeyEvent.VK_S) // 按S鍵,根據iSystemStatus判斷是開始或重新開始 { if (b.objSystemStatus.getSystemStatus() == 0) // 開始 { t.start(); // System.out.println("start..."); b.objSystemStatus.setSystemStatus(1); // 轉到玩家遊戲狀態. } else if (b.objSystemStatus.getSystemStatus() == 1 || b.objSystemStatus.getSystemStatus() == 2 || b.objSystemStatus.getSystemStatus() == 3) // 重新開始 { t.stop(); b.restart(); // System.out.println("restart..."); objScore.restart(); b.objDiamonds.restart(); b.objSystemStatus.setSystemStatus(1); t.start(); } } else if (keyCode == KeyEvent.VK_D) // 按P鍵,如果當前係統處於玩家遊戲狀態,就暫停(iSysStatus=2).如果處於暫停狀態,就恢複到玩家遊戲狀態. { if (b.objSystemStatus.getSystemStatus() != 0 && b.objSystemStatus.getSystemStatus() != 3) { if (b.objSystemStatus.getSystemStatus() == 1) { t.stop(); b.objSystemStatus.setSystemStatus(2); } else if (b.objSystemStatus.getSystemStatus() == 2) { t.start(); b.objSystemStatus.setSystemStatus(1); } } } repaint(); } public void keyReleased(KeyEvent evt) { } public void keyTyped(KeyEvent evt) { } // 計時器事件,與按下鍵的事件處理一致. public void actionPerformed(ActionEvent evt) { int[] rtnRowColNo; // 存放方塊中的參照格子的行號和列號. rtnRowColNo = b.objDiamonds.getReferPoint(); // 方塊5已經沉底,要被固定的情況 if (rtnRowColNo[0] - 1 < 0) { int[][] rtnPosition; rtnPosition = b.objDiamonds.diamondsPosition(); // 把容器中與方塊的顯示部分位置相對應的格子設為已使用. for (int i = 0; i < rtnPosition.length; i++) if ((rtnPosition[i][0] != -1) && (rtnPosition[i][1] != -1)) b.setAryGrids(rtnPosition[i][0], rtnPosition[i][1], 1); // 對已滿的行要進行消行處理. int tmpLineNum; tmpLineNum = b.removeRows(); objScore.addScore(tmpLineNum); // 消行後要累加分數. if (b.gameOverChk() == 1) System.out.println("GAME OVER!!"); if (b.gameOverChk() == 1) { t.stop(); // System.out.println("GAME OVER!!"); b.objSystemStatus.setSystemStatus(3); } else { // 重新生成一個新的方塊,實質是設定方塊的類型,並將其位置複位. b.objDiamonds.setSortNo(objPreDiamonds.getSortNo()); b.objDiamonds.setStatusNo(objPreDiamonds.getStatusNo()); b.objDiamonds.setAryDiamonds(); objPreDiamonds.createNew(); b.objDiamonds.setReferPoint(b.getHeightGrid(), b.getWidthGrid() / 2 - 1); } } else { // 方塊5向下移動遇到已使用的格子而固定的情況 int isTouch = 0; // 為0表示未接觸,為1表示已接觸. int[][] aryDownTouchGrids; aryDownTouchGrids = b.objDiamonds.downTouchGrids(); for (int i = 0; i < aryDownTouchGrids.length; i++) { if (b.getAryGrids(aryDownTouchGrids[i][0] - 1, aryDownTouchGrids[i][1]) == 1) { isTouch = 1; break; } } if (isTouch == 1) // 向下移動已發生了接觸. { int[][] rtnPosition; rtnPosition = b.objDiamonds.diamondsPosition(); // 把容器中與方塊5位置相對應的格子設為已使用. for (int i = 0; i < rtnPosition.length; i++) if ((rtnPosition[i][0] != -1) && (rtnPosition[i][1] != -1)) b.setAryGrids(rtnPosition[i][0], rtnPosition[i][1], 1); // 對已滿的行要進行消行處理. int tmpLineNum; tmpLineNum = b.removeRows(); objScore.addScore(tmpLineNum); if (b.gameOverChk() == 1) System.out.println("GAME OVER!!"); if (b.gameOverChk() == 1) { t.stop(); System.out.println("GAME OVER!!"); b.objSystemStatus.setSystemStatus(3); } else { // 重新生成一個新的方塊,實質是設定方塊的類型,並將其位置複位. b.objDiamonds.setSortNo(objPreDiamonds.getSortNo()); b.objDiamonds.setStatusNo(objPreDiamonds.getStatusNo()); b.objDiamonds.setAryDiamonds(); objPreDiamonds.createNew(); b.objDiamonds.setReferPoint(b.getHeightGrid(), b.getWidthGrid() / 2 - 1); } } else { b.objDiamonds.setReferPoint(rtnRowColNo[0] - 1, rtnRowColNo[1]); } } repaint(); } public void paintComponent(Graphics g) { super.paintComponent(g); b.drawGridFrame(g); b.drawGrids(g); objPreview.drawGridFrame(g); objPreview.drawGrids(g, objPreDiamonds.diamondsPosition()); objScore.drawScore(g); objCopyright.drawCopyright(g); b.objSystemStatus.drawSystemStatus(g); } private Timer t; private int delay = 200; private board b; private diamonds objPreDiamonds; private preview objPreview; private score objScore; private copyright objCopyright; } class eluosiFrame extends JFrame { public eluosiFrame() { setTitle("經典俄羅斯方塊"); setSize(240, 400); addWindowListener(new WindowAdapter() { public void windowClosing(WindowEvent e) { System.exit(0); } }); Container contentPane = getContentPane(); contentPane.add(new eluosiPanel()); } } public class Russia { public static void main(String[] args) { JFrame myEluosi = new eluosiFrame(); myEluosi.show(); } }
最後更新:2017-04-02 06:52:18