2015-04-24 60 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'更像是一个廉价的修补程序,基本上写着“我不知道什么让我的虚拟机运行,所以退出一切”。此答案指出“此线程不会导致虚拟机继续运行” –

相关问题