- 参考博客:https://blog.csdn.net/qq_42370146/article/details/84842168#commentBox
- 在原博主的拼图游戏上添加了键盘控制系统,即通过方向键上下左右进行交换。
- 思路很简单,就是通过GridPane获取坐标的功能计算出上下左右的坐标,然后通过已经实现的交换方法进行交换,但是交换方法必须获得两个源,而:
- GridPane不支持通过坐标访问源,所以算出坐标后并不能直接访问来进行交换,所以如何通过坐标来联系上在那个位置的那张图片的源就是难点。
- 解决方法:
n[]
这个随机数组中值虽然是随机的,但是n[1],n[2]
却是依次排列的,比如imageview[n[5]]
就代表第5张图,这样就可以通过以n[5]的值作为ImageView的索引来实现访问第几张图了。然后就可以进行交换了。
- 但是交换过去后有一个很严重的问题,比如在向上交换后再向下交换,就是把第九张图和第六张图交换之后想再换回去时,现在空白方块在地址5,通过计算下面的方块地址为8,应该和n[8]交换,但是n[8]其实还是刚刚的第九张图,因此就会一直和自己交换,程序看上去就一动不动。
- 其实我们交换的是图片的源,和
n[]
并没有关系,所以n[]
还是原来的样子,并没有跟着一起交换,这样就导致算出来的新坐标对应的还是老的索引,因此我们应该把n[]
也跟着一起交换,达到一致。而n[]
中只有8个元素,我们要交换的话,需要九个元素都在,因此要创建一个新数组,前八个元素一样,把缺了的元素m补在最后。
- 实现:使用一个
int[] ncopy = new int[9]
来拓展随机数组n[8]
。通过遍历将前八个元素复制,并将m添加到ncopy最后。在源图片交换后,将数组里的元素也交换。
switch (arg0.getCode()) {
case DOWN:
int nrow = mrow + 1;
int ncol = mcol;
int nindex = nrow * 3 + ncol;
if (nindex >= 0 && nindex <= 8) {
myevent1.swapimg(imageViews[m], imageViews[ncopy[nindex]]);
int temp2 = ncopy[mindex];
ncopy[mindex] = ncopy[nindex];
ncopy[nindex] = temp2;
}
break;
package application;
import java.util.Random;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.geometry.Rectangle2D;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.input.KeyEvent;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import java.util.Arrays;
public class Game_1 extends Application {
public int m;
ImageView[] imageViews = new ImageView[9];
Image image2 = new Image("application/test.jpg", 800, 800, false, false);
public int partImagewidth = (int) image2.getHeight() / 3;
public int[] ncopy;
@Override
public void start(Stage primaryStage) {
init(primaryStage);
}
public void init(Stage primaryStage) {
VBox vBox = new VBox();
GridPane gridPane = new GridPane();
HBox hbox = new HBox();
hbox.setPadding(new Insets(10));
hbox.setAlignment(Pos.CENTER);
Button home = new Button("返回首页");
home.setOnAction(e -> {
Start start = new Start();
start.start(new Stage());
primaryStage.close();
});
Button again = new Button("重新游戏");
again.setOnAction(e -> {
Game_1 game = new Game_1();
game.start(new Stage());
primaryStage.close();
});
Button look = new Button("查看原图");
look.setOnAction(e -> {
OnImage_1 OnImage = new OnImage_1();
OnImage.start(new Stage());
});
home.setPrefSize(200, 50);
again.setPrefSize(200, 50);
look.setPrefSize(200, 50);
hbox.setSpacing(100);
hbox.getChildren().addAll(home, again, look);
int[] n = random();
m = findnum(n);
ncopy = new int[9];
for (int i = 0; i < 9; i++) {
if (i == 8) {
ncopy[8] = m;
} else {
ncopy[i] = n[i];
}
}
for (int i = 0; i < 9; i++) {
imageViews[i] = new ImageView(image2);
imageViews[i].setOnMouseClicked(new myevent());
imageViews[i].setOnKeyPressed(new myKeyEvent());
}
for (int i = 0, k = 0; i <= 2; i++) {
for (int j = 0; j <= 2; j++, k++) {
imageViews[k].setViewport(
new Rectangle2D(partImagewidth * j, partImagewidth * i, partImagewidth, partImagewidth));
}
}
gridPane.add(imageViews[n[0]], 0, 0);
gridPane.add(imageViews[n[1]], 1, 0);
gridPane.add(imageViews[n[2]], 2, 0);
gridPane.add(imageViews[n[3]], 0, 1);
gridPane.add(imageViews[n[4]], 1, 1);
gridPane.add(imageViews[n[5]], 2, 1);
gridPane.add(imageViews[n[6]], 0, 2);
gridPane.add(imageViews[n[7]], 1, 2);
Image image1 = new Image("file:C:\\Users\\CharlesChen\\Desktop\\empty.png");
imageViews[m].setImage(image1);
gridPane.add(imageViews[m], 2, 2);
gridPane.setGridLinesVisible(true);
gridPane.setPrefWidth(800);
gridPane.setPrefHeight(800);
vBox.getChildren().add(gridPane);
vBox.getChildren().add(hbox);
Scene scene = new Scene(vBox, 800, 850);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("智障拼图");
primaryStage.setScene(scene);
primaryStage.setResizable(true);
primaryStage.show();
imageViews[m].requestFocus();
}
public int[] random() {
int[] ran = new int[8];
while (iso(ran) == false) {
ran = random_num();
}
return ran;
}
public int[] random_num() {
int r[] = new int[8];
Random random = new Random();
for (int i = 0; i < 8; ++i) {
r[i] = random.nextInt(9);
for (int j = 0; j < i; ++j) {
while (r[i] == r[j]) {
i--;
break;
}
}
}
return r;
}
public boolean iso(int[] num) {
int sum = 0;
for (int i = 0; i <= 6; ++i) {
for (int j = i; j <= 7; j++) {
if (num[i] > num[j]) {
sum++;
}
}
}
if ((sum % 2) == 0 && sum != 0) {
return true;
}
return false;
}
class myevent implements EventHandler<MouseEvent> {
@Override
public void handle(MouseEvent arg0) {
ImageView img = (ImageView) arg0.getSource();
double sx = img.getLayoutX();
double sy = img.getLayoutY();
double dispx = sx - imageViews[m].getLayoutX();
double dispy = sy - imageViews[m].getLayoutY();
if ((dispx == -partImagewidth) && (dispy == 0)) {
swapimg(img, imageViews[m]);
if (issucc(imageViews)) {
Alert alert = new Alert(AlertType.WARNING, "恭喜你,拼图成功!");
alert.show();
}
} else if ((dispx == 0) && (dispy == -partImagewidth)) {
swapimg(img, imageViews[m]);
if (issucc(imageViews)) {
Alert alert = new Alert(AlertType.WARNING, "恭喜你,拼图成功!");
alert.show();
}
} else if ((dispx == partImagewidth) && (dispy == 0)) {
swapimg(img, imageViews[m]);
if (issucc(imageViews)) {
Alert alert = new Alert(AlertType.WARNING, "恭喜你,拼图成功!");
alert.show();
}
} else if ((dispx == 0) && (dispy == partImagewidth)) {
swapimg(img, imageViews[m]);
if (issucc(imageViews)) {
Alert alert = new Alert(AlertType.WARNING, "恭喜你,拼图成功!");
alert.show();
}
}
}
public void swapimg(ImageView i1, ImageView i2) {
int row1 = GridPane.getRowIndex(i1);
int colu1 = GridPane.getColumnIndex(i1);
int row2 = GridPane.getRowIndex(i2);
int colu2 = GridPane.getColumnIndex(i2);
GridPane.setRowIndex(i1, row2);
GridPane.setColumnIndex(i1, colu2);
GridPane.setRowIndex(i2, row1);
GridPane.setColumnIndex(i2, colu1);
}
}
class myKeyEvent implements EventHandler<KeyEvent> {
@Override
public void handle(KeyEvent arg0) {
myevent myevent1 = new myevent();
int mrow = GridPane.getRowIndex(imageViews[m]);
int mcol = GridPane.getColumnIndex(imageViews[m]);
int mindex = mrow * 3 + mcol;
switch (arg0.getCode()) {
case DOWN:
int nrow = mrow + 1;
int ncol = mcol;
int nindex = nrow * 3 + ncol;
if (nindex >= 0 && nindex <= 8) {
myevent1.swapimg(imageViews[m], imageViews[ncopy[nindex]]);
int temp2 = ncopy[mindex];
ncopy[mindex] = ncopy[nindex];
ncopy[nindex] = temp2;
}
break;
case UP:
nrow = mrow - 1;
ncol = mcol;
nindex = nrow * 3 + ncol;
if (nindex >= 0 && nindex <= 8) {
myevent1.swapimg(imageViews[m], imageViews[ncopy[nindex]]);
int temp2 = ncopy[mindex];
ncopy[mindex] = ncopy[nindex];
ncopy[nindex] = temp2;
}
break;
case LEFT:
nrow = mrow;
ncol = mcol - 1;
nindex = nrow * 3 + ncol;
if (nindex >= 0 && nindex <= 8 && nindex != 2 && nindex != 5) {
myevent1.swapimg(imageViews[m], imageViews[ncopy[nindex]]);
int temp2 = ncopy[mindex];
ncopy[mindex] = ncopy[nindex];
ncopy[nindex] = temp2;
}
break;
case RIGHT:
nrow = mrow;
ncol = mcol + 1;
nindex = nrow * 3 + ncol;
if (nindex >= 0 && nindex <= 8 && nindex != 3 && nindex != 6) {
myevent1.swapimg(imageViews[m], imageViews[ncopy[nindex]]);
int temp2 = ncopy[mindex];
ncopy[mindex] = ncopy[nindex];
ncopy[nindex] = temp2;
}
break;
default:
break;
}
}
}
public boolean issucc(ImageView[] imageViews) {
for (int i = 0; i <= 8; ++i) {
if (i != 3 * GridPane.getRowIndex(imageViews[i]) + GridPane.getColumnIndex(imageViews[i])) {
return false;
}
}
return true;
}
public int findnum(int[] n) {
for (int j = 0; j <= 8; ++j) {
if ((j == n[0]) || (j == n[1]) || (j == n[2]) || (j == n[3]) || (j == n[4]) || (j == n[5]) || (j == n[6])
|| (j == n[7])) {
} else {
return j;
}
}
return -1;
}
}
package application;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.stage.Stage;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
public class Start extends Application {
@Override
public void start(Stage primaryStage) {
try {
VBox vBox = new VBox();
HBox hBox_1 = new HBox();
HBox hBox_2 = new HBox();
Button start_1 = new Button("简单");
start_1.setOnAction(e -> {
Game_4 game_4 = new Game_4();
game_4.start(new Stage());
primaryStage.close();
});
Button start_2 = new Button("困难");
start_2.setOnAction(e -> {
Game_2 game_2 = new Game_2();
game_2.start(new Stage());
primaryStage.close();
});
Button start_3 = new Button("地狱");
start_3.setOnAction(e -> {
Game_3 game_3 = new Game_3();
game_3.start(new Stage());
primaryStage.close();
});
Label label = new Label("@余氏出品,必属渣品");
label.setFont(new Font("Arial", 30));
label.setTextFill(Color.web("black"));
hBox_1.getChildren().addAll(start_1, start_2, start_3);
hBox_2.getChildren().add(label);
vBox.getChildren().addAll(hBox_1, hBox_2);
start_1.setPrefSize(100, 60);
start_2.setPrefSize(100, 60);
start_3.setPrefSize(100, 60);
hBox_1.setPadding(new Insets(650, 100, 0, 175));
hBox_2.setPadding(new Insets(50, 50, 500, 260));
hBox_1.setSpacing(100);
Scene scene = new Scene(vBox, 800, 800);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setTitle("智障拼图");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}