閱讀649 返回首頁    go 技術社區[雲棲]


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

  上一篇:go Android 近百個項目的源代碼,覆蓋Android開發的每個領域
  下一篇:go Hibernate三種狀態的區分