2015-04-24 110 views
1

我試圖重新創建連接四個,並且我成功了。但我想通過每隔一段時間切換一次顏色,讓玩家指出獲勝的四張碟片在哪裏。我對線程和編程中的時間概念很陌生。程序在關閉應用程序後不停止

我也成功地給了用戶這個指示,但在關閉應用程序後,控制檯仍然給出輸出,同樣當我使用setOnCloseRequest時。

其他一些問題:
:對於顏色我使用了HTML的名字,是它更好地使用十六進制三重或沒有偏好。
:要阻止網格和其他元素擁抱屏幕的左側,我添加了與背景顏色相同的邊框,有沒有更好的方法來做到這一點?
:我沒有創建一個方法將keycode轉換爲整數,而是在init函數中創建。我這樣做是因爲我不知道如何傳遞關鍵事件。這個怎麼做?

下面是代碼:

import javafx.application.Application; 
import javafx.scene.Scene; 
import javafx.scene.control.Button; 
import javafx.scene.control.Label; 
import javafx.scene.layout.GridPane; 
import javafx.scene.layout.HBox; 
import javafx.scene.layout.VBox; 
import javafx.stage.Stage; 

import java.util.concurrent.Executors; 
import java.util.concurrent.ScheduledExecutorService; 
import java.util.concurrent.TimeUnit; 

public class FourInARow extends Application { 

GridPane boardGrid = new GridPane(); 

Label[][] labels = new Label[7][7]; 
Label statusLabel = new Label(); 
int[][] cell = new int[7][6]; 

int player = 0; 
int won = 0; 

String baseStyle = "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: "; 

ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor(); 

public static void main(String[] args){launch(args);} 

private void init(Stage window){ 

    createLabels(); 
    startGame(); 

    Label above = new Label("Try to connect four discs in a row!"); 
    above.setStyle("-fx-font-size: 30; -fx-alignment: center; -fx-min-width: 600"); 
    boardGrid.setStyle("-fx-background-color: silver;-fx-border-color: #F4F4F4;-fx-border-width: 0 20 0 20"); 
    Button newGame = new Button("New Game"); 
    newGame.setStyle("-fx-min-width: 100;-fx-font-size:20"); 
    newGame.setOnAction(e -> startGame()); 
    statusLabel.setStyle("-fx-font-size: 30;-fx-alignment: center; -fx-min-width: 300;"); 
    HBox below = new HBox(); 
    below.setStyle("-fx-border-width: 0 0 0 20;-fx-border-color: #F4F4F4"); 
    below.getChildren().addAll(newGame, statusLabel); 
    VBox layout = new VBox(); 
    layout.getChildren().addAll(above, boardGrid, below); 
    Scene scene = new Scene(layout, 600, 620); 
    scene.setOnKeyPressed(e -> { 
     if (won == 0) { 
      try { 
       String k = e.getCode().toString(); 
       int l = k.length(); 
       int col = Integer.parseInt(k.substring(l - 1, l)) - 1; 
       placeDisc(col, player); 
       switchPlayer(); 
       updateScreen(); 
      } catch (NumberFormatException | ArrayIndexOutOfBoundsException error) { 
       System.out.println("error: " + error); 
      } 
     } 
    }); 
    window.setScene(scene); 
    window.setTitle("Connect Four"); 

    threadThing(); 
} 

private void threadThing() { 
    service.scheduleAtFixedRate(() -> { 
     try { 
      wonStyle(); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    }, 0, 1, TimeUnit.SECONDS); 
} 

private void startGame() { 
    cell = new int[7][6]; 
    won = player = 0; 
    statusLabel.setText(""); 
    updateScreen(); 
} 

private void updateScreen() { 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 6; j++) { 
      labels[i][j].setStyle(baseStyle + addStyle(cell[i][j])); 
     } 
     labels[i][6].setText(Integer.toString(i+1)); 
     labels[i][6].setStyle("-fx-alignment: center;-fx-min-width: 80;-fx-background-color: #F4F4F4;-fx-font-size: 30;"); 
    } 

    switch(won) { 
     case 1: statusLabel.setText("Blue has won!");break; 
     case 2: statusLabel.setText("Yellow has won!");break; 
    } 
} 

private String addStyle(int cell) { 
    String style = "silver"; 
    switch(cell){ 
     case 1: style = "blue"; break; 
     case 2: style = "yellow"; break; 
     case 3: style = "darkblue"; break; 
     case 4: style = "gold;"; break; 
    } 
    return style; 
} 

private void placeDisc(int col, int player) { 
    for (int i = 5; i >= 0 ; i--) { 
     if(cell[col][i] == 0){ 
      cell[col][i] = 1; 
      if(player == 1) cell[col][i] = 2; 
      break; 
     }else{ 
      if(i==0) switchPlayer(); 
     } 
    } 
    checkWon(); 
} 

private void checkWon() { 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 6; j++) { 
      if (cell[i][j] != 0) { 
       try { 
        if (cell[i][j] == cell[i][j + 1] && cell[i][j] == cell[i][j + 2] && cell[i][j] == cell[i][j + 3]) { 
         won = cell[i][j]; 
         cell[i][j] = cell[i][j + 1] = cell[i][j + 2] = cell[i][j + 3] = cell[i][j] + 2; 
        } 
       }catch(ArrayIndexOutOfBoundsException error) {} 
       try { 
        if (cell[i][j] == cell[i + 1][j] && cell[i][j] == cell[i + 2][j] && cell[i][j] == cell[i + 3][j]) { 
         System.out.println("Horizontal win"); 
         won = cell[i][j]; 
         cell[i][j] = cell[i + 1][j] = cell[i + 2][j] = cell[i + 3][j] = cell[i][j] + 2; 
        } 
       }catch(ArrayIndexOutOfBoundsException error) {} 
       try { 
        if (cell[i][j] == cell[i + 1][j + 1] && cell[i][j] == cell[i + 2][j + 2] && cell[i][j] == cell[i + 3][j + 3]) { 
         won = cell[i][j]; 
         cell[i][j] = cell[i + 1][j + 1] = cell[i + 2][j + 2] = cell[i + 3][j + 3] = cell[i][j] + 2; 
        } 
       }catch(ArrayIndexOutOfBoundsException error) {} 
       try { 
        if (cell[i][j] == cell [i + 1][j - 1] && cell[i][j] == cell[i + 2][j - 2] && cell[i][j] == cell[i + 3][j - 3]) { 
         won = cell[i][j]; 
         cell[i][j] = cell[i + 1][j - 1] = cell[i + 2][j - 2] = cell[i + 3][j - 3] = cell[i][j] + 2; 
        } 
       }catch(ArrayIndexOutOfBoundsException error) {} 
      } 
     } 
    } 
} 

private void switchPlayer() { 
    if(player == 0) player = 2; 
    player--; 
} 

private void createLabels() { 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 7; j++) { 
      labels[i][j] = new Label(); 
      boardGrid.add(labels[i][j], i, j); 
     } 
    } 
} 

private void wonStyle() throws InterruptedException { 
    System.out.println("Test"); 
    boolean run = false; 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 6; j++) { 
      if(cell[i][j] > 2 && !run){ 
       Thread.sleep(500); 
       addStyleFlicker(); 
       run = true; 
      } 
     } 
    } 
} 

private void addStyleFlicker() throws InterruptedException { 
    String[] styleOne = {"-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: blue;", 
         "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: darkblue;"}; 
    String[] styleTwo = {"-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: yellow;", 
         "-fx-background-radius: 40; -fx-min-width: 80; -fx-min-height: 80; -fx-alignment: center; -fx-border-width: 2; -fx-border-color: #000000;-fx-background-color: gold;"}; 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 6; j++) { 
      if(cell[i][j] == 3){ 
       labels[i][j].setStyle(styleOne[0]); 
      }else if(cell[i][j] == 4){ 
       labels[i][j].setStyle(styleTwo[0]); 
      } 
     } 
    } 
    Thread.sleep(500); 
    for (int i = 0; i < 7; i++) { 
     for (int j = 0; j < 6; j++) { 
      if(cell[i][j] == 3){ 
       labels[i][j].setStyle(styleOne[1]); 
      }else if(cell[i][j] == 4) { 
       labels[i][j].setStyle(styleTwo[1]); 
      } 
     } 
    } 
} 

@Override 
public void start(Stage window) throws Exception { 
    init(window); 
    window.show(); 
} 
} 
+0

可能重複(http://stackoverflow.com/questions/12153622/how-to-close-a-javafx-application) –

+0

我查看過這篇文章,但沒有找到解決辦法。 –

+1

使用創建守護程序線程的線程工廠創建執行程序。 (如果沒有其他人在我回到我的計算機之前做過任何其他工作,我會發佈一個代碼答案。) –

回答

2

重寫從Applicationstop()方法可以讓你關閉你的控制檯應用程序:

@Override 
public void stop() { 
    System.exit(0); 
} 
+0

謝謝,這是:) –

+0

我猜kill -9也可以,但我強烈建議堅持優雅地吸所有線程。 – IceGlow

4

每在Java API文檔的Thread類。 ..

Java虛擬機繼續執行線程,直到以下任何一個ng發生:

  • Runtime類的退出方法已被調用且安全管理器已允許執行退出操作。
  • 所有不是守護進程線程的線程都已死亡,無論是從調用返回的run方法還是通過拋出傳播超出run方法的異常。

所以,你需要的是執行者創建守護線程會死當JVM準備退出。您可以使用自定義線程工廠來完成此任務這裏是一個非常簡單的例子:?如何關閉JavaFX應用程序]

Executors.newSingleThreadScheduledExecutor(new ThreadFactory() { 

     @Override 
     public Thread newThread(Runnable r) { 
      Thread t = new Thread(r); 
      t.setDaemon(true); 
      return t; 
     } 
    }); 
+0

感謝大衛,這也是有效的,兩個答案都比另一個更好?或者更適合這種情況? –

+2

我認爲它們都是有效的,但System.exit(0)IMO是真正原因的一個bandaid,它是保持JVM退出的非守護線程。無論如何,最好了解守護進程線程,以便在調用System.exit可能不是一個好主意的情況下使用它們,例如Web應用程序或第三方可能依賴的庫。 – David

+0

@RichardKoetchruyter得與大衛同意。這個答案鼓勵更好的做法。由於另一個線程仍處於活動狀態,您的應用程序仍在運行。將該線程設置爲'daemon'確保即使該線​​程仍在運行,VM仍然可以退出。 'System.exit'更像是一個廉價的修補程序,基本上寫着「我不知道什麼讓我的虛擬機運行,所以退出一切」。此答案指出「此線程不會導致虛擬機繼續運行」 –

相關問題