MLDN 五子棋。笔记
MLDN 五子棋。
───────────────────────────────────────
———— Swing 知識準備。
(一)、Swing 的概念
Swing 是在java 的基礎圖形化用戶界面AWT 的基礎上擴展的API 集。
Swing 的功能:通過java 代碼編寫窗口程序,創建圖形化用戶界面(GUI)。
Swing 可以創建窗體,面版,在窗口中導入或繪制圖片,或輸入文本信息,
結合java 的JDBC或IO操作可以實現數據的保存。(記事本的保存功能)
(二)、JFrame 類。
JFrame 是創建窗體的swing 類,用來創建一個圖形界面的原始窗口,并設置其大小,
位置等屬性,是swing 編程的基礎類之一。
1.JFrame ————主要方法。
setTitle()??? ??? ??? ??? ??? ??? //窗體標題。
setSize(200, 100)??? ??? ??? ??? //窗體大小。
setLocation()??? ??? ??? ??? ??? //窗體位置。
setResizable()??? ??? ??? ??? ??? //窗體縮放。
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
??? ??? ??? ??? ??? ??? ??? ??? //窗體關閉,同時結束程序。
setVisible(true)??? ??? ??? ??? //窗體可見。
2.取得屏幕大小:
??? Toolkit.getDefaultToolkit().getScreenSize().width
??? Toolkit.getDefaultToolkit().getScreenSize().height
???
3.實現窗體顯示在屏幕正中間:
JFrame jf = new JFrame();
int w = Toolkit.getDefaultToolkit().getScreenSize().width
int h = Toolkit.getDefaultToolkit().getScreenSize().height
jf.setLocation((w - 200)/2, (h - 100)/2);???
4.創建一個類繼承JFrame
??? 創建一個構造方法,由構造方法初始化窗體。
??? this.setXXX
5.在main 方法中直接 new 一個繼承JFrame 的類就ok。
(三)、JOptionPane 類。
JOptionPane 用來彈出提示信息框,確認框和信息輸入框。
不用new,直接調用靜態方法就ok。
1.彈出提示信息框:
JOptionPane.showMessageDialog(jf, "要提示的信息。");
2.彈出確認框:
int result = JOptionPane.showConfirmDialog
??? ??? ??? ??? ??? (jf, "要確認的信息:正的要刪除?");
是:0,否:1,取消:2 。??? ??? ??? ??? ???
if(result == 0) {
??? //顯示一個提示框。已經刪除。
}
if...
if...??? ??? ??? ??? ???
3.彈出信息輸入框:
String message = JOptionPane.showInputDialog("請輸入你的信息:");
if(message != null) {
??? JOptionPane.showMessageDialog(jf, "信息:" + message);
} else {
??? JOptionPane.showMessageDialog(jf, "請輸入信息。");
}
??? ??? ??? 點取消的時候 message = null;
(四)、MouseListener 鼠標監聽器類。
MouseListener 接收用戶通過鼠標所做的操作。可以取得用戶點擊鼠標的坐標。
MouseListener 的使用方法:
??? 需要調用JFrame 的 addMouseListener 方法加入監聽。
MouseListener————主要方法:
1.mouseClicked(MouseEvent e)??? ??? 監聽鼠標點擊事件。(鼠標不移動)
2.mousePressed(MouseEvent e)??? ??? 監聽鼠標按下事件。(使用頻繁)
3.mouseReleased(MouseEvent e)??? ??? 監聽鼠標抬起事件。
4.mouseEntered(MouseEvent e)??? ??? 監聽鼠標進入事件。
5.mouseExited(MouseEvent e)??? ??? ??? 監聽鼠標離開事件。
鼠標點擊時執行的順序:
mousePressed->mouseReleased->mouseClicked(按下與抬起在同一位置)
得到鼠標點擊的坐標: MouseEvent 類。
public void mousePressed(MouseEvent e) {
??? System.out.println("點擊位置:X-->" + e.getX());
??? System.out.println("點擊位置:Y-->" + e.getY());
}
(五)、Graphics 類
Graphics 類似畫筆,用來在窗口中繪制文字和圖象。
通過重寫JFrame 的 paint() 方法來使用,通過repaint() 方法來調用。
Graphics————主要方法:
1.drawString() ??? ??? ??? ??? ??? ??? 繪制字符串
??? //字符串, x軸位置, y軸位置:3參數
2.drawOval()??? ??? ??? ??? ??? ??? 繪制一個空心圓
??? //x軸位置, y軸位置, 寬, 高:4參數???
3.fillOval()??? ??? ??? ??? ??? ??? 繪制一個實心圓
??? //參數同上。
4.drawLine()??? ??? ??? ??? ??? ??? 繪制一條線
??? //起點(x1, y1), 終點(x2, y2) 畫棋盤
5.drawRect()??? ??? ??? ??? ??? ??? 繪制一個空心矩形
6.fillRect()??? ??? ??? ??? ??? ??? 繪制一個實心矩形
7.drawImage()??? ??? ??? ??? ??? ??? 繪制一個已經存在的圖片,
??? ??? ??? ??? ??? ??? ??? ??? ??? 將一個圖片直接顯示到窗體中。
??? ??? ??? ??? ??? ??? ??? ??? ???
將硬盤中的圖片導入到窗口中:
通過ImageIO 輸入一個BufferedImage
通過drawImage() 方法將一個BufferedImage 對象繪制到窗口中。??? ???
實現導入一張圖片:
把硬盤中圖片讀到內存,程序把圖片從內存中取出,顯示到窗體中。
BufferedImage image = ImageIO.read(new File("文件路徑+文件"));
??? ??? ??? ??? ??? ??? ??? ??? ??? //IO要try,可能讀不到文件。
g.drawImage(image, 0, 0, this); ??? //this 繪制到當前窗體下。
??? ??? ??? ??? ??? ??? ??? ??? ??? //沒有背,景窗體是透明的。
??? ??? ??? ??? ???
其他會用到的方法:
setColor()??? ??? ??? ??? ??? ??? ??? 設置畫筆的顏色
setFont()??? ??? ??? ??? ??? ??? ??? 設置文字的字體
//g.setFont(new Font("黑體", 20, 20));? ??? //字體,大小
───────────────────────────────────────
(一)、五子棋游戲的功能:
1.在點擊鼠標時,可以在相應的位置顯示棋子。
2.可以自動判斷游戲是否結束,是否黑方或白方已經勝利。
3.對游戲時間進行設置,判斷是否超出規定時間。
───────────────────────────────────────
(二)、開發出游戲界面:
1.創建FiveChessFrame 類,繼承JFrame 實現MouseListener。
屬性:
??? 屏幕大小:
int w = Toolkit.getDefaultToolkit().getScreenSize().width
int h = Toolkit.getDefaultToolkit().getScreenSize().height
??? 背景圖片:
BufferedImage bgImage = null;???
FiveChessFrame 構造方法。
pubic FiveChessFrame() {
??? this.setTitle("五子棋");
??? this.setSize(500,500);??? ??? //背景圖片大小。
??? this.setLocation((w-500)/2, (h-500)/2);
??? this.setResizable(false);
??? this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
//加入鼠標監聽。
??? this.addMouseListener(this);???
??? this.setVisible(true);
???
??? bgImage = ImageIO.read(new File("文件路徑/文件"));
??? ??? ??? ??? ??? ??? ??? ??? //要try 。
}
//重寫paint 方法。顯示圖片。
public void paint (Graphics g) {
//繪制背景圖片。
??? g.drawImage(bgImage, 1, 20, this);
//游戲信息。???
??? g.setFont(new Font("黑體", Font.BOLD, 20));
??? g.drawString("游戲信息:", 130, 60);
//時間信息。
??? g.setFont(new Font("宋體", 0, 14));
??? g.drawString("黑方時間:無限制", 30, 470);???
??? g.drawString("白方時間:無限制", 260, 470);???
//繪制棋盤。
//在mousePressed(MouseEvent e)? 方法中打印坐標。
//System.out.println("X:" + e.getX());
//System.out.println("Y:" + e.getY());??? ??? ??? ???
計算棋盤中每一條線的間距:
使用19X19 的圍棋棋盤。
橫19 條線,縱19 條線。
總寬度:360 像素,分成:18 份,每份:20 像素。
總高度:360 像素......
//手繪棋盤。
??? for(int i=0; i<19; i++) {
??? ??? g.drawLine(10,70+20*i,370,70+20*i);
??? ??? g.drawLine(10+20*i,70,10+20*i,430);
??? }???
//標注點位。加粗。??? x, y 不是圓心哦!3X3 位置。
??? g.fillOval(68,128,4,4);??? ??? //四角
??? g.fillOval(308,128,4,4);
??? g.fillOval(308,368,4,4);
??? g.fillOval(68,368,4,4);??? ???
??? g.fillOval(308,248,4,4);??? //四邊
??? g.fillOval(188,128,4,4);
??? g.fillOval(68,248,4,4);
??? g.fillOval(188,368,4,4);
???
??? g.fillOval(188,248,4,4);??? //中心
}
public static void main(String [] args) {
??? FiveChessFrame ff = new FiveChessFrame();
}
───────────────────────────────────────
(三)、實現下棋功能:
在棋盤上的鼠標點擊位置,顯示一個棋子。
黑子:一個實心的黑圓。
白子:一個空心的黑圓 + 一個實心的白圓。
repaint() 方法:重新執行一次paint() 方法。
1.定義一個成員變量保存棋子的坐標。
int x = 0;
int y = 0;
2.通過二維數組保存之前下過的所有棋子的坐標。
//如果其中數據內容 ??? 0:表示這個點沒有棋子;
??? ??? ??? ??? 1:表示這個點是黑子;
??? ??? ??? ??? 2:表示這個點是白子。
int[][] allChess = new int[19][19];
3.判斷下一步下黑子,還是下白子。??? ??? 開局黑子先下。
boolean isBlack = true;
3.//在paint 方法中繪制全部棋子。
public void paint() {
......
//輸出二維數組中所有的數值。一重循環,循環行,二重循環,循環列。
//畫線的時候,已經循環了坐標。
//輸出二維數組中全部棋子。
??? for(int i=0; i<19; i++) {
??? ??? for(int j=0; j<19; j++) {
??? ??? ??? if(allChess[i][j] == 1) {
??? ??? ??? ??? //黑子
??? ??? ??? ??? int tempX = i*20+10;??? //10 是棋盤外空了10 像素。
??? ??? ??? ??? int tempY = j*20+70;
??? ??? ??? ??? g.fillOval(tempX-7, tempY-7, 14, 14);
??? ??? ??? }??? ???
??? ??? ??? if(allChess[i][j] == 2) {
??? ??? ??? ??? //白子
??? ??? ??? ??? int tempX = i*20+10;
??? ??? ??? ??? int tempY = j*20+70;
??? ??? ??? ??? g.setColor(Color.white);
??? ??? ??? ??? g.fillOval(tempX-7, tempY-7, 14, 14);
??? ??? ??? ??? g.setColor(Color.blach);
??? ??? ??? ??? g.drawOval(tempX-7, tempY-7, 14, 14);
??? ??? ??? }???
??? ??? }
??? }
}
//把棋子保存到相應的位置。
2.public void mousePressed(MouseEvent e) {
??? x = e.getX();
??? y = e.getY();???
??? if( x>= 10 && x <= 370 && y >= 70 && y <= 430) {
//判斷x, y 距離哪個交叉點最近。把坐標保存到二維數組中。
//一大難點。要下棋子的坐標。
??? ??? x = (x - 10) / 20;??? ??? //10 是棋盤外面多余部分。
??? ??? y = (y - 70) / 20;??? ??? //除后取整。不準確。
??? ???
//位置是空的才能下,不然會覆蓋原來下的棋子顏色。
??? ??? if(allChess[x][y] == 0) {??? ???
//判斷當前下什么顏色的棋子。??? ???
??? ??? ??? if(isBlack == true) {
??? ??? ??? ??? allChess[x][y] = 1;
??? ??? ??? ??? isBlack = false;
??? ??? ??? } else {
??? ??? ??? ??? allChess[x][y] = 2;
??? ??? ??? ??? isBlack = true;
??? ??? ??? }
??? ??? } else {
??? ??? ??? JOptionPane.showMessageDialog
??? ??? ??? ??? ??? (this,"當前位置已經有棋子, 請重新落子");
??? ??? }
??? ??? this.repaint(); ??? ???
??? }
}
分析 畫棋子部分:
顯示棋子分兩步,輸入(mousePressed)+輸出(paint)。
x = (x-10)/20 * 20 + 10;
(x-10)/20 保存
* 20 + 10 輸出
int tempX = i*20 + 10;
───────────────────────────────────────
(四)、判斷輸贏:
五子棋規則:判斷是否有同一顏色的棋子連成5 個。
判斷當前下的棋子,跟周圍相連的相同的棋子是否有5 個。
1.在mousePressed 方法中第一個if 最后面添加判斷。(保證能落子)
//判斷這個棋子是否和其他的棋子連成5連,即判斷游戲是否結束。
boolean winFlag = this.checkWin();
if(winFlag == true) {
??? JOptionPane.showMessageDialog(this, "游戲結束," +
??? (allChess[x][y]==1?"黑方":"白方") + "獲勝!"
??? );
??? canPlay = false;
}
2.//單獨寫成一個方法。要判斷4 個方向。
private boolean checkWin() {
??? boolean flag = false;
//保存共有相同顏色多少棋子相連
??? int count = 1;???
??? ???
??? ???
/*??? ??? 分析。。。。
//判斷橫向是否有5 個棋子相連,
//特點:縱坐標是相同的,即allChess[x][y]中y 值是相同的。
??? int color = allChess[x][y]; ??? //判斷顏色。
//通過循環來做棋子相連的判斷。
*/
??? count = this.checkCount(1, 0, color);??? ??? //橫判斷
??? if(count >= 5) {
??? ??? flag = true;
??? } else {
??? ??? count = this.checkCount(0, 1 ,color);??? //縱判斷
??? ??? if(count >= 5) {
??? ??? ??? flag = true;
??? ??? } else {
??? ??? ??? //判斷右上,左下,x 加,y 減。
??? ??? ??? count = this.checkCount(1, -1, color);
??? ??? ??? if(count >= 5) {
??? ??? ??? ??? flag = true;
??? ??? ??? } else {
??? ??? ??? ??? //判斷右下,左上,x 加, y 加;x 減, y 減。
??? ??? ??? ??? count = this.checkCount(1, 1, color);
??? ??? ??? ??? if(count >= 5) {
??? ??? ??? ??? ??? flag = true;
??? ??? ??? ??? }
??? ??? ??? }
??? ??? }
??? }
??? ???
//這種算法,經常使用(橫,豎,斜),如掃雷。
??? return flag;
}
3.添加一個成員變量:標識當前游戲是否可以繼續
boolean canPlay = true;
4.mousePressed 所有的代碼加一個判斷
if(canPlay == ture) {
??? ...所有代碼。
}
//也可以if(!canPlay) return;??? 馬士兵的風格。
到此為止,已經完成了五子棋游戲的核心算法。
───────────────────────────────────────
(五)、將判斷輸贏的方法整合成一個方法:
//判斷棋子連接的數量。參數:x軸,y軸變化的數字。
//重復的代碼總結成一個方法。
private int checkCount(int xChange, int yChange, int color) {
??? int count = 1;
??? int tempX = xChange;
??? int tempY = yChange;
??? while(color == allchess[x+xChange][y+yChange]) {
??? ??? count++;
??? ??? if(xChange != 0) xChange++;
??? ??? if(yChange != 0) {
??? ??? ??? if(yChange > 0) {
??? ??? ??? ??? yChange++;
??? ??? ??? } else {
??? ??? ??? ??? yChange--;
??? ??? ??? }??? ???
??? ??? }
??? }??? ???
???
??? xChange = tempX;
??? yChange = tempY;??? ??? //變回初始值,再判斷相反方向。
???
??? while(color == allchess[x-xChange][y-yChange]) {
??? ??? count++;
??? ??? if(xChange != 0) xChange++;
??? ??? if(yChange != 0) {
??? ??? ??? if(yChange > 0) {
??? ??? ??? ??? yChange++;??? ???
//yChange 如果是-1 加加就是0 了。多加了一個bug。
??? ??? ??? } else {
??? ??? ??? ??? yChange--;
??? ??? ??? }??? ???
??? ??? }
??? }???
???
??? return count;
}
───────────────────────────────────────
(六)、顯示游戲信息:輪到誰下了。
1.定義一個成員變量,保存顯示的提示信息。
??? String message = "黑方先落子 ";
???
2.paint 方法中 游戲信息字符串后面加上? 提示信息。
??? g.drawString("游戲信息:" + message, 130, 60);
???
3.根據走子,改變提示信息。
??? public void mousePressed(MouseEvent e) 方法中
??? if(isBlack == true) {
??? ??? ??? ??? allChess[x][y] = 1;
??? ??? ??? ??? isBlack = false;
??? ??? ??? ??? message = "輪到白方";
??? ??? ??? } else {
??? ??? ??? ??? allChess[x][y] = 2;
??? ??? ??? ??? isBlack = true;
??? ??? ??? ??? message = "輪到黑方";??? ??? ??? ???
??? ??? ??? }
???
───────────────────────────────────────
(七)、處理屏幕閃爍問題:
雙緩沖技術:用在手機游戲中用的是最多的。
??? ??? 原因是手機的內存相對較小,屏幕閃爍問題比較明顯。
??? ???
把所有要顯示到屏幕上的信息,先緩沖到內存中的圖片上,
再統一把內存中的圖片顯示到窗體中。??? ???
??? ???
paint 方法中添加雙緩沖。
BufferedImage bi = new BufferedImage
(500,500,BufferedImage.TYPE_INT_ARGB);??? ???
??? //傳入一個顏色類型
Graphics g2 = bi.createGraphics();??? //為內存中的bi 圖片創建畫筆。
下面的都用g2 畫到緩沖圖片上,g只畫bi。
....
g.drawImage(bi,0,0,this);
一次性繪制的東西太多,可以會先繪制一些,后繪制一些。
程序很快執行,就會出現閃爍。
雙緩沖,只畫一個,就把上面的內容一次性繪制到程序中。
───────────────────────────────────────
(八)、加入幾個按鈕功能:
1.打印出坐標。
System.out.println(e.getX() + "--" e.getY());
2.按鈕區域。??? ??? ??? ??? x 軸坐標不變。
public void mousePressed(MouseEvent e) 方法最后:
//點擊 開始游戲 按鈕
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=70 && e.getY() <= 100) {
int result = JOptionPane.showConfirmDialog(this,
??? ??? "是否重新開始游戲?");
??? ??? if(result == 0) {
//重新開始游戲:1.把棋盤清空,allChess數組中全部數據歸0。
//??? ??? ??? 2.將游戲信息的顯示改回到開始位置。
//??? ??? ??? 3.將下一步下棋的人改為黑方。???
1.??? ??? ??? for(int i=0; i<19; i++) {
??? ??? ??? ??? for(int j=0; j<19; j++) {
??? ??? ??? ??? ??? allChess[i][j] = 0;
??? ??? ??? ??? }
??? ??? ??? }
??? ??? ??? //另一種清空二維數組方式 allChess = new int[19][19];
??? ??? ???
2.??? ??? ??? message = "黑方先落子";
3.??? ??? ??? isBlack = true;
??? ??? ???
??? ??? ??? //清空棋盤。清空東西后,重新刷一遍,頁面顯示才會變化。
??? ??? ??? this.repaint();??? ??? ???
??? ??? }??? ???
??? }???
//點擊 游戲設置 按鈕???
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=120 && e.getY() <= 150) {
??? ??? String input = JOptionPane.showInputDialog("請輸入游戲的
??? ??? 最大時間(單位:分鐘),如果輸入0,表示沒有時間限制:");
??? ??? try {
??? ??? ??? maxTime = Integer.parseInt(input)*60;??? //添加try 塊。
??? ??? ??? if(maxTime < 0) {
??? ??? ??? ??? JOptionPane.showMessageDialog(this,
??? ??? ??? ??? "請輸入正確信息,不允許輸入負數!");
??? ??? ??? }
??? ??? ??? if(maxTime == 0) {
int result = JOptionPane.showConfirmDialog(this, "設置完成,
??? ??? ??? ??? 是否重新開始游戲?");
??? ??? ??? ??? if(result == 0) {
??? ??? ??? ??? ??? //代碼和游戲開始相同。
??? ??? ??? ??? ??? ......
??? ??? ??? ??? ??? blackTime = maxTime;
??? ??? ??? ??? ??? whiteTime = maxTime;??? ???
??? ??? ??? ??? ??? //給重新開始游戲那也加上2 行代碼
??? ??? ??? ??? ??? blackMessage = "無限制";
??? ??? ??? ??? ??? whiteMessage = "無限制";
??? ??? ??? ??? ??? this.canPlay = true; ??? ??? ??? ??? ???
??? ??? ??? ??? ??? this.repaint();
??? ??? ??? ??? }??? ??? ??? ???
??? ??? ??? }
??? ??? ??? if(maxTime > 0) {
int result = JOptionPane.showConfirmDialog(this, "設置完成,
??? ??? ??? ??? 是否重新開始游戲?");
??? ??? ??? ??? if(result == 0) {
??? ??? ??? ??? ??? //代碼和游戲開始相同。
??? ??? ??? ??? ??? ......
??? ??? ??? ??? ??? blackTime = maxTime;
??? ??? ??? ??? ??? whiteTime = maxTime;
??? ??? ??? ??? ??? blackMessage = maxTime/3600 + ":"
??? ??? ??? ??? ??? ??? ??? + (maxTime/60 - maxTime/3600*60) + ":"
??? ??? ??? ??? ??? ??? ??? + (maxTime - maxTime/60*60);
??? ??? ??? ??? ??? whiteMessage = maxTime / 3600 + ":"
??? ??? ??? ??? ??? ??? ??? + (maxTime/60 - maxTime/3600*60) + ":"
??? ??? ??? ??? ??? ??? ??? + (maxTime - maxTime/60*60);
??? ??? ??? ??? ??? t.resume();??? ??? ??? //啟動掛起的線程。
??? ??? ??? ??? ??? this.canPlay = true; ???
??? ??? ??? ??? ??? //開始游戲代碼中判斷,if(maxTime > 0) {} else {}
??? ??? ??? ??? ??? //有時間限制用這一段,沒有時間限制用maxTime == 0 那段。??? ??? ??? ???
??? ??? ??? ??? ??? this.repaint();
??? ??? ??? ??? }??? ??? ??? ??? ?
??? ??? ??? }
??? ??? } catch(NumberFormatException e) {
??? ??? ??? JOptionPane.showMessageDialog(this,"請正確輸入信息!")??? ;
??? ??? }
??? ???
??? }???
//點擊 游戲說明 按鈕???
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=170 && e.getY() <= 200) {
??? ??? JOptionPane.showMessageDialog(this,
??? ??? "這是一個五子棋游戲,黑白雙方輪流下棋,當某一方連到5 子時,
??? ??? 游戲結束。");
??? }???
//點擊 認輸?????? 按鈕???
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=270 && e.getY() <= 300) {
int result = JOption.showConfirmDialog(this, "是否確認認輸?");
??? ??? if(result == 0) {
??? ??? ??? if(isBlack) {
??? JOptionPane.showMessageDialog(this,"黑方已經認輸,游戲結束")??? ;
??? ??? ??? } else {
??? JOptionPane.showMessageDialog(this,"白方已經認輸,游戲結束")??? ;
??? ??? ??? }
??? ??? }
??? ??? canPlay = false;
??? }
//點擊 關于?????? 按鈕???
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=320 && e.getY() <= 350) {
??? ??? JOptionPane.showMessageDialog(this,
??? ??? "本游戲由MLDN制作,有相關問題可以訪問www.mldn.cn");
??? }
//點擊 退出?????? 按鈕???
??? if(e.getX() >= 400 && e.getX() <= 470 &&
??? e.getY() >=370 && e.getY() <= 400) {
??? ??? JOptionPane.showMessageDialog(this, "游戲結束");
??? ??? System.exit(0);
??? }???
3.實現各個按鈕的功能:
3.1.開始游戲:重新開始新的游戲。??? ???
3.2.游戲設置:設置倒計時。
3.3.游戲說明:說明游戲規則和操作。
3.4.認輸:??? 某一方放棄游戲,認輸。
3.5.關于:??? 顯示程序的作者或編寫單位的相關信息。
3.6.退出:??? 結束程序。
───────────────────────────────────────
(九)、游戲設置,倒計時,線程。
1.添加一個成員變量。
//保存最多擁有多少時間(秒)。
??? int maxTime = 0;
//保存黑方和白方的剩余時間。
??? int blackTime = 0;
??? int whiteTime = 0;???
//保存雙方剩余時間的顯示信息。
??? String blackMessage = "無限制";
??? String whiteMessage = "無限制";???
2.定義一個倒計時線程類。
??? Thread t = new Thread(this);??? //對當前窗體做線程控制。
???
??? 在構造方法中啟動線程。
??? t.start();
??? t.suspend();??? ??? ??? //掛起線程先。
???
??? 讓窗體實現 Runnable 接口。實現run() 方法。
??? public void run() {
//判斷是否有時間限制
??? ??? if(maxTime > 0) {
??? ??? ??? while(true) {
??? ??? ??? ??? if(isBlack) {
??? ??? ??? ??? ??? blackTime--;
??? ??? ??? ??? ??? //超時判斷。
??? ??? ??? ??? ??? if (blackTime == 0) {
??? ??? ??? ??? ??? ??? JOptionPane.showMessageDialog(this, "黑方超時,游戲結束!");
??? ??? ??? ??? ??? }
??? ??? ??? ??? } else {
??? ??? ??? ??? ??? whiteTime--;
??? ??? ??? ??? ??? //超時判斷。
??? ??? ??? ??? ??? if (whiteTime == 0) {
??? ??? ??? ??? ??? ??? JOptionPane.showMessageDialog(this, "白方超時,游戲結束!");
??? ??? ??? ??? ??? }
??? ??? ??? ??? }
??? ??? ??? ??? blackMessage = blackTime / 3600 + ":"
??? ??? ??? ??? ??? ??? + (blackTime / 60 - blackTime / 3600 * 60) + ":"
??? ??? ??? ??? ??? ??? + (blackTime - blackTime / 60 * 60);
??? ??? ??? ??? whiteMessage = whiteTime / 3600 + ":"
??? ??? ??? ??? ??? ??? + (whiteTime / 60 - whiteTime / 3600 * 60) + ":"
??? ??? ??? ??? ??? ??? + (whiteTime - whiteTime / 60 * 60);
??? ??? ??? ??? this.repaint();??? ??? ??? ??? //刷新屏幕,重新調用paint 方法。
??? ??? ??? ???
??? ??? ??? ???
??? ??? ??? ??? Thread.sleep(1000);??? ??? ??? //1000毫秒,即1秒。要try 。
??? ??? ??? ??? //cacth (InterruptException e)
??? ??? ??? }??? ???
??? ??? }
??? }???
3.顯示倒計時。修改paint 方法。
g2.drawString("黑方時間:"+blackMessage,30,470);
g2.drawString("白方時間:"+whiteMessage,260,470);???
───────────────────────────────────────
(十)、第一次運行出現黑屏,
原因:paint 方法不是最后執行的。
解決:在構造方法最后手工調用 repaint() 方法。刷新屏幕。
───────────────────────────────────────
(十一)、棋子下到最邊緣的位置,報數組下標越界錯誤。
原因:在checkCount 連接數量判斷的時候,沒有考慮位置為0。
??? ??? 位置為0 再減 1 就是 -1 下標越界了。
解決:多加一個判斷。
while(x+xChange>=0 && x+xChange<=18 && y+yChange>=0 &&
y+yChange<=18 && color == allChess[x+xChange][y+yChange])??? ???
下半部分判斷:加變成減去。
while(x-xChange>=0 && x-xChange<=18 && y-yChange>=0 &&
y-yChange<=18 && color == allChess[x-xChange][y-yChange])
總結
以上是生活随笔為你收集整理的MLDN 五子棋。笔记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [css] 举例说明attr()的使用
- 下一篇: [css] H5如何禁止显示系统菜单?