?? ersblocksgame.java
字號:
/**
* File: ErsBlocksGame.java
* User: Administrator
* Date: Dec 15, 2003
* Describe: 俄羅斯方塊的 Java 實現
*/
package game;
import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
/**
* 游戲主類,繼承JFrame類,負責游戲的全局控制。 內含 1, 一個GameCanvas畫布類的實例引用, 2,
* 一個保存當前活動塊(ErsBlock)實例的引用, 3, 一個保存當前控制面板(ControlPanel)實例的引用;
*/
public class ErsBlocksGame extends GameMenu {
/**
* 每填滿一行計多少分
*/
public final static int PER_LINE_SCORE = 100;
/**
* 積多少分以后能升級
*/
public final static int PER_LEVEL_SCORE = PER_LINE_SCORE * 20;
/**
* 最大級數是10級
*/
public final static int MAX_LEVEL = 10;
/**
* 默認級數是5
*/
public final static int DEFAULT_LEVEL = 5;
public static int selfFail = 0;
public static int otherFail = 0;
// 一個GameCanvas畫布類的實例引用,
private GameCanvas canvas;
// 一個保存當前活動塊(ErsBlock)實例的引用,
private ErsBlock block;
// 一個保存當前控制面板(ControlPanel)實例的引用;
private ControlPanel ctrlPanel;
private boolean playing = false;
/**
* 主游戲類的構造函數
*
* @param title
* String,窗口標題
*/
public ErsBlocksGame(String title) {
super(title);
// 初始窗口的大小,用戶可調控
setSize(315, 392);
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
// 將游戲窗口置于屏幕中央
setLocation((scrSize.width - getSize().width) / 2,
(scrSize.height - getSize().height) / 2);
Container container = getContentPane();
// 布局的水平構件之間有6個象素的距離
container.setLayout(new BorderLayout(6, 0));
// 建立20個方塊高,12個方塊寬的游戲畫布
canvas = new GameCanvas();
// 建立一個控制面板
ctrlPanel = new ControlPanel(this);
ctrlPanel.setPlayButtonEnable(false);
// 游戲畫布和控制面板之間左右擺放
container.add(canvas, BorderLayout.CENTER);
container.add(ctrlPanel, BorderLayout.EAST);
// 增加窗口監聽器
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent we) {
System.exit(0);
}
});
show(); // setVisiable
// 根據窗口的大小,自動調整方格的尺寸
canvas.fanning();
setResizable(false);
}
/**
* 讓游戲“復位”
*/
public void reset() {
ctrlPanel.reset(); // 控制窗口復位
canvas.reset(); // 游戲畫板復位
}
public void gameReset() {
ctrlPanel.setPlayButtonEnable(false);
// ctrlPanel.setPauseButtonLabel(true);
getMGame().setEnabled(true);
getMControl().setEnabled(true);
getMInfo().setEnabled(true);
getMiNewGame().setEnabled(true);
getMiConnectGame().setEnabled(true);
}
/**
* 判斷游戲是否還在進行
*
* @return boolean, true-還在運行,false-已經停止
*/
public boolean isPlaying() {
return playing;
}
/**
* 得到當前活動的塊
*
* @return ErsBlock, 當前活動塊的引用
*/
public ErsBlock getCurBlock() {
return block;
}
/**
* 得到當前畫布
*
* @return GameCanvas, 當前畫布的引用
*/
public GameCanvas getCanvas() {
return canvas;
}
/**
* 開始游戲
*/
public void playGame() {
play();
ctrlPanel.setPlayButtonEnable(false);
// miPlay.setEnabled(false);
ctrlPanel.requestFocus();
}
/**
* 得到當前游戲者設置的游戲難度
*
* @return int, 游戲難度1-MAX_LEVEL=10
*/
public int getLevel() {
return ctrlPanel.getLevel();
}
/**
* 讓用戶設置游戲難度系數
*
* @param level
* int, 游戲難度系數為1-MAX_LEVEL=10
*/
public void setLevel(int level) {
if (level < 11 && level > 0)
ctrlPanel.setLevel(level);
}
/**
* 得到游戲積分
*
* @return int, 積分。
*/
public int getScore() {
if (canvas != null)
return canvas.getScore();
return 0;
}
/**
* 得到自上次升級以來的游戲積分,升級以后,此積分清零
*
* @return int, 積分。
*/
public int getScoreForLevelUpdate() {
if (canvas != null)
return canvas.getScoreForLevelUpdata();
return 0;
}
/**
* 當分數累計到一定的數量時,升一次級
*
* @return boolean, ture-更新成功, false-更新失敗
*/
public boolean levelUpdate() {
int curLevel = getLevel();
if (curLevel < MAX_LEVEL) {
setLevel(curLevel + 1);
canvas.resetScoreForLevelUpdata();
return true;
}
return false;
}
/**
* 游戲開始
*/
private void play() {
reset();
playing = true;
Thread thread = new Thread(new Game());
thread.start();
}
private void reportGameWin() {
JOptionPane.showMessageDialog(this, "你贏了");
}
private void reportGameLose() {
JOptionPane.showMessageDialog(this, "你輸了");
}
/**
* 一輪游戲過程,實現了Runnable接口 一輪游戲是一個大循環,在這個循環中,每隔100毫秒, 檢查游戲中的當前塊是否已經到底了,如果沒有,
* 就繼續等待。如果到底了,就看有沒有全填滿的行, 如果有就刪除它,并為游戲者加分,同時隨機產生一個 新的當前塊,讓它按所定級別的速度,自動下落。
* 當新產生一個塊時,先檢查畫布最頂端的一行是否已經 被占了,如果是,可以顯示“游戲結束”了。
*/
private JDialog serverSuc() {
JDialog dialog = new JDialog(this, "提示信息", false);
JLabel label = new JLabel(" 端口有效,等待其他玩家中......");
dialog.getContentPane().setLayout(new BorderLayout());
dialog.setSize(300, 90);
dialog.setResizable(false);
dialog.getContentPane().add(label);
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
dialog.setLocation((scrSize.width - getSize().width) / 2,
(scrSize.height - getSize().height) / 2);
return dialog;
}
private JDialog socketSuc() {
JDialog dialog = new JDialog(this, "提示信息", false);
JLabel label = new JLabel("與玩家連接建立成功,10s后開始游戲!");
dialog.getContentPane().setLayout(new BorderLayout());
dialog.setSize(300, 90);
dialog.setResizable(false);
dialog.getContentPane().add(label);
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
dialog.setLocation((scrSize.width - getSize().width) / 2,
(scrSize.height - getSize().height) / 2);
return dialog;
}
private JDialog showException(Exception e) {
JDialog dialog = new JDialog(this, "提示信息", false);
JLabel label = new JLabel(e.toString());
dialog.getContentPane().setLayout(new BorderLayout());
dialog.setSize(300, 90);
dialog.setResizable(false);
dialog.getContentPane().add(label);
Dimension scrSize = Toolkit.getDefaultToolkit().getScreenSize();
dialog.setLocation((scrSize.width - getSize().width) / 2,
(scrSize.height - getSize().height) / 2);
return dialog;
}
private class Game implements Runnable {
public void run() {
int col = canvas.getCols() - 8;
int style = ErsBlock.STYLES[(int) (Math.random() * 7)][(int) (Math
.random() * 4)];
ServerSocket server = getServer();
JDialog serverSuc = serverSuc();
JDialog socketSuc = socketSuc();
Socket socketOut = null;
Socket socketIn = null;
ObjectInputStream in = null;
ObjectOutputStream out = null;
selfFail = 0;
otherFail = 0;
int numLose = 0;
boolean serverSign = false;
boolean clienSign = false;
int[][] failData;
if (getAddress() != null) {
serverSign = false;
clienSign = true;
try {
socketIn = new Socket(getAddress(), getPortNum());
socketOut = new Socket(getAddress(), getPortNum());
in = new ObjectInputStream(socketIn.getInputStream());
out = new ObjectOutputStream(socketOut.getOutputStream());
} catch (Exception e) {
System.out.println(e.toString());
// TODO: handle exception
}
} else {
if (server != null) {
serverSign = true;
clienSign = false;
try {
serverSuc.setVisible(true);
// Thread.sleep (1000*3);
socketOut = server.accept();
socketIn = server.accept();
Thread.sleep(1000 * 2);
serverSuc.setVisible(false);
socketSuc.setVisible(true);
Thread.sleep(1000 * 2);
socketSuc.setVisible(false);
out = new ObjectOutputStream(socketOut
.getOutputStream());
in = new ObjectInputStream(socketIn.getInputStream());
} catch (Exception e) {
showException(e).setVisible(true);
}
}
}
while (playing) {
if (otherFail == 1) {
try {
} catch (Exception e) {
System.out.println("對方玩家失敗");
System.out.println(e.toString());
}
reportGameWin();
try {
if (in != null)
in.close();
if (out != null)
out.close();
if (serverSign) {
if (server != null) {
server.close();
getServer().close();
}
}
if (socketIn != null)
socketIn.close();
if (socketOut != null)
socketOut.close();
setAddress(null);
setServer(null);
} catch (Exception e) {
}
gameReset();
reset();
return;
}
if (selfFail == 1) {
failData = new int[GameCanvas.CANVAS_ROWS][GameCanvas.CANVAS_COLS];
try {
out.writeObject(new Data(failData, selfFail,0));
} catch (Exception e) {
System.out.println(e.toString());
}
reportGameLose();
try {
if (in != null)
in.close();
if (out != null)
out.close();
if (serverSign) {
if (server != null) {
server.close();
getServer().close();
}
}
if (socketIn != null)
socketIn.close();
if (socketOut != null)
socketOut.close();
setAddress(null);
setServer(null);
} catch (Exception e) {
}
gameReset();
reset();
return;
}
if (block != null) { // 第一次循環時,block為空
if (block.isAlive()) {
try {
Thread.currentThread().sleep(100);
} catch (InterruptedException ie) {
ie.printStackTrace();
}
continue;
}
}
numLose = checkFullLine(); // 檢查是否有全填滿的行
if (isGameOver()) { // 檢查游戲是否應該結束了
selfFail = 1;
}
// 創建一個游戲塊
block = new ErsBlock(style, -1, col, getLevel(), canvas,
ctrlPanel, in, out,numLose);
// 作為線程開始運行
block.start();
// 隨機生成下一個塊的初始列的位置
// 隨機生成下一個塊的初始形態(28種之一)
style = ErsBlock.STYLES[(int) (Math.random() * 7)][(int) (Math
.random() * 4)];
// 在控制面板中提示下一個塊的形狀
ctrlPanel.setTipStyle(style);
}
}
/**
* 檢查畫布中是否有全填滿的行,如果有就刪除之
*/
public int checkFullLine() {
int num = 0;
for (int i = 0; i < canvas.getRows(); i++) {
int row = -1;
boolean fullLineColorBox = true;
for (int j = 0; j < canvas.getCols(); j++) {
// 檢查第i行,第j列是否為彩色方塊
if (!canvas.getBox(i, j).isColorBox()) {
// 非彩色方塊,
fullLineColorBox = false;
break;
// 退出內循環,檢查下一行
}
}
if (fullLineColorBox) {
row = i--;
canvas.removeLine(row);
num++;
// 該行已填滿,移去
}
}
return num;
}
/**
* 根據最頂行是否被占,判斷游戲是否已經結束了。
*
* @return boolean, true-游戲結束了,false-游戲未結束
*/
private boolean isGameOver() {
for (int i = 0; i < canvas.getCols(); i++) {
ErsBox box = canvas.getBox(0, i);
if (box.isColorBox())
return true;
}
return false;
}
}
/**
* 程序入口函數
*
* @param args
* String[], 附帶的命令行參數,該游戲 不需要帶命令行參數
*/
public static void main(String[] args) {
new ErsBlocksGame("俄羅斯方塊游戲");
}
public void actionPerformed(ActionEvent e) {
super.actionPerformed(e);
if (e.getSource() == miNewGame || e.getSource() == miConnectGame) {
ctrlPanel.setPlayButtonEnable(true);
}
}
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -