Создание слайд-игры, похожей на 2048, с использованием JavaFXJAVA

Программисты JAVA общаются здесь
Ответить Пред. темаСлед. тема
Anonymous
 Создание слайд-игры, похожей на 2048, с использованием JavaFX

Сообщение Anonymous »

Игра работает для размера доски по умолчанию 4 на 4, однако, когда я тестировал игру на разных размерах, которые не являются квадратными, например 6 x 4, 4 x 8 и т. д., игра не удалась. Точнее, ни одна из функций скольжения не работает, и я включил отладочные операторы печати, которые полностью игнорируются. Просматривая свой код несколько раз, я считаю, что моя логика верна, и не вижу причин, по которым я получаю такие результаты. Вы можете запустить игру самостоятельно, набрав java SlideGame 6 4 и т. д., но в результате некраевые кнопки иногда реализуют случайные методы, а краевые кнопки не работают должным образом, что делает игру невозможной.

Код: Выделить всё

/**
* SlideGame represents a simple sliding puzzle game.
* The game board consists of tiles with numbers that can be moved in four directions: up, down, left, and right.
* Tiles with the same value can merge when they collide, resulting in a new tile with twice the value.
*
* @author --------
*/
import java.util.List;
import java.util.Random;
import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.stage.Stage;
import javafx.scene.layout.BorderPane;
import javafx.scene.layout.GridPane;
import javafx.scene.control.Button;
import javafx.scene.Node;
import javafx.scene.paint.Color;
import javafx.scene.control.ColorPicker;

public class SlideGame extends Application {

// Fields
private int height; // Height of the game board
private int width; // Width of the game board
private int[][] gameBoard; // 2D array representing the game board
private GridPane board; // GridPane for displaying the game board
private ColorPicker colorPicker; // ColorPicker for selecting tile colors
private boolean moved = false; // Flag indicating if a move has been made

// Enum for representing different directions
public enum Direction {
UP, DOWN, LEFT, RIGHT, UPLEFT, UPRIGHT, DOWNLEFT, DOWNRIGHT
}

/**
* Constructs a SlideGame object with default dimensions.
* Default dimensions are 4x4.
*/
public SlideGame() {
this.height = 4; // Default height
this.width = 4; // Default width
this.colorPicker = new ColorPicker(Color.web("#003333"));
}

/**
* Constructs a SlideGame object with the specified dimensions.
*
* @param height The height of the game board.
* @param width  The width of the game board.
*/
public SlideGame(int width, int height) {
this.width = width;
this.height = height;
}

// Non-static methods
/**
* Starts the game and sets up the scene.
*
* @param primaryStage The primary stage for the application.
*/
@Override
public void start(Stage primaryStage) {
Parameters params = getParameters();
List raw = params.getRaw();
height = 4;
width = 4;

if (raw.size() >= 2) {
try {
width = Integer.parseInt(raw.get(0));
height = Integer.parseInt(raw.get(1));
// Proceed with the game initialization using valid height, width, and color
System.out.println("Creating game board with width " + width + " and height " + height);
} catch (NumberFormatException e) {
System.out.println("Invalid arguments. Please provide valid integer values for height and width.");
return;
}
} else {
// Default behavior when no command line arguments are provided
System.out.println("No command line arguments provided.  Using default settings.");
}

// Initialize the game board
board = new GridPane();
BorderPane borderPane = new BorderPane();
gameBoard = new int[width][height];
generateTile();
updateBoard(board);

// Set up the color picker
colorPicker = new ColorPicker(Color.web("#003333")); // Initialize the color picker with default color
borderPane.setBottom(board); // Add the color picker to the grid
borderPane.setTop(colorPicker); // Add the color picker to the

// Set up the color picker event handler
colorPicker.setOnAction(new EventHandler() {
@Override
public void handle(ActionEvent e) {
updateTileColors(colorPicker.getValue());
}
});

// Set up the scene
Scene scene = new Scene(borderPane, 400, 400);
primaryStage.setScene(scene);
primaryStage.setTitle("Slide Game");
primaryStage.show();
addButtons(board);
}

/**
* Checks if there are any empty spaces available on the game board.
*
* @return true if an empty space is available, false otherwise.
*/
public boolean isEmptySpaceAvailable() {
// Check if there are any empty spaces on the game board
for (int i = 0; i < height; i++) {
for (int j = 0; j < width; j++) {
if (gameBoard[i][j] == 0) {
return true; // Found an empty space
}
}
}
return false; // No empty spaces found
}

/**
* Generates a new tile on an empty space of the game board.
*/
public void generateTile() {
Random rn = new Random();

// Check if there are empty spaces available on the board
if (isEmptySpaceAvailable()) {
int start1;
int start2;
do {
start1 = rn.nextInt(height);
start2 = rn.nextInt(width);
} while (gameBoard[start1][start2] != 0);
gameBoard[start1][start2] = 1; // Assign value 1 to the empty space
} else {
// Handle the case where there are no empty spaces left
System.out.println("No empty spaces left.  Game over!");
}
}

/**
* Updates the game board with the current state of the game.
*
* @param gridPane The GridPane representing the game board.
*/
public void updateBoard(GridPane gridPane) {
gridPane.getChildren().clear();
Color selectedColor = colorPicker.getValue(); // Get the current selected color

for (int i = 0; i < gameBoard.length; i++) {
for (int j = 0; j < gameBoard[i].length; j++) {
Button b = new Button();
int value = gameBoard[i][j];
b.setText(String.valueOf(value));
b.setStyle(createGradientStyle(selectedColor, value)); // Update the tile color
gridPane.add(b, i, j);
}
}
if (moved) {
generateTile();
}
addButtons(gridPane);
}

/**
* Adds event handlers to the buttons on the game board.
*
* @param grid The GridPane representing the game board.
*/
public void addButtons(GridPane grid) {
Color selectedColor = colorPicker.getValue(); // Get the current selected color

for (Node node : grid.getChildren()) {
if (node instanceof Button) {
Button button = (Button) node;
button.setOnAction(new EventHandler() {
@Override
public void handle(ActionEvent e) {
click(button, grid);
}
});

int buttonSize = Math.min(750 / width, 750 / height);
button.setPrefSize(buttonSize, buttonSize);
button.setStyle("-fx-border-color: black; -fx-border-width: 1px;");

// Update the tile color
int value = Integer.parseInt(button.getText());
button.setStyle(createGradientStyle(selectedColor, value));
}
}
}

/**
* Handles the click event on a button in the game board.
*
* @param clicked The button that was clicked.
* @param grid    The GridPane representing the game board.
*/
public void click(Button clicked, GridPane grid) {
System.out.println("TesT");
Direction direction;
int row = GridPane.getRowIndex(clicked); // Row index of the clicked button
int col = GridPane.getColumnIndex(clicked); // Column index of the clicked button
int numRows = gameBoard[0].length - 1; // Number of rows in the game board
int numCols = gameBoard.length - 1; // Number of columns in the game board
boolean topEdge = row == 0; // Flag indicating if the clicked button is on the top edge
boolean bottomEdge = row == numRows; // Flag indicating if the clicked button is on the bottom edge
boolean leftEdge = col == 0; // Flag indicating if the clicked button is on the left edge
boolean rightEdge = col == numCols; // Flag indicating if the clicked button is on the right edge
boolean topLeft = topEdge && leftEdge; // Flag indicating if the clicked button is in the top-left corner
boolean topRight = topEdge && rightEdge; // Flag indicating if the clicked button is in the top-right corner
boolean bottomLeft = bottomEdge && leftEdge; // Flag indicating if the clicked button is in the bottom-left corner
boolean bottomRight = bottomEdge && rightEdge;  // Flag indicating if the clicked button is in the bottom-right corner

// Determine the direction of the slide
if (topLeft) {
direction = Direction.UPLEFT;
System.out.println("TOPLEFT");
} else if (topRight) {
direction = Direction.UPRIGHT;
System.out.println("TOPRIGHT");
} else if (bottomLeft) {
direction = Direction.DOWNLEFT;
System.out.println("DOWNLEFT");
} else if (bottomRight) {
direction = Direction.DOWNRIGHT;
System.out.println("DOWNRIGHT");
} else if (leftEdge) {
direction = Direction.LEFT;
System.out.println("LEFT");
} else if (rightEdge) {
direction = Direction.RIGHT;
System.out.println("RIGHT");
} else if (topEdge) {
direction = Direction.UP;
System.out.println("UP");
} else if (bottomEdge) {
direction = Direction.DOWN;
System.out.println("DOWN");
} else {
return;
}

move(direction);
updateBoard(grid);
}

/**
* Moves the tiles on the game board in the specified direction.
*
* @param direction The direction in which the tiles should be moved.
*/
public void move(Direction direction) {
moved = false; // Flag to determine whether a button click resulted in any tiles moving

/* Switch statement that implements the necessary slide function depending on the direction inputted */
switch (direction) {

case LEFT:
/* Loop through each column */
for (int j = 0; j < gameBoard[0].length; j++) {
int current = 0; // Track current position to place next tile
/* Loop through each row in the current column */
for (int i = 0; i < gameBoard.length; i++) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != i) { // There's a gap, move the tile
gameBoard[current][j] = value;
gameBoard[i][j] = 0;
moved = true;
}
current++; // Increment current position
}
}
// Merge adjacent identical tiles in the current column
for (int i = 0; i < gameBoard.length - 1; i++) {
if (gameBoard[i][j] == gameBoard[i + 1][j] && gameBoard[i][j] != 0) {
gameBoard[i][j] *= 2;
gameBoard[i + 1][j] = 0;
moved = true;
}
}
}
// Secondary slide without merge in the left direction
for (int j = 0; j < gameBoard[0].length; j++) {
int current = 0; // Track current position to place next tile
for (int i = 0; i < gameBoard.length; i++) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != i) { // There's a gap, move the tile
gameBoard[current][j] = value;
gameBoard[i][j] = 0;
moved = true;
}
current++; // Increment current position
}
}
}
break;

case RIGHT:
/* Loop through each column */
for (int j = 0; j < gameBoard[0].length; j++) {
int current = gameBoard.length - 1; // Track current position to place next tile
/* Loop through each row in the current column in reverse order */
for (int i = gameBoard.length - 1; i >= 0; i--) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != i) { // There's a gap, move the tile
gameBoard[current][j] = value;
gameBoard[i][j] = 0;
moved = true;
}
current--; // Decrement current position
}
}
// Merge adjacent identical tiles in the current column
for (int i = gameBoard.length - 1; i > 0; i--) {
if (gameBoard[i][j] == gameBoard[i - 1][j] &&  gameBoard[i][j] != 0) {
gameBoard[i][j] *= 2;
gameBoard[i - 1][j] = 0;
moved = true;
}
}
}
// Secondary slide without merge in the right direction
for (int j = 0; j < gameBoard[0].length; j++) {
int current = gameBoard.length - 1; // Track current position to place next tile
for (int i = gameBoard.length - 1; i >= 0; i--) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != i) { // There's a gap, move the tile
gameBoard[current][j] = value;
gameBoard[i][j] = 0;
moved = true;
}
current--; // Decrement current position
}
}
}
break;

case UP:
/* Loop through each row */
for (int i = 0; i < gameBoard.length; i++) {
int current = 0; // Track current position to place next tile
/* Loop through each column in the current row */
for (int j = 0; j < gameBoard[0].length; j++) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != j) { // There's a gap, move the tile
gameBoard[i][current] = value;
gameBoard[i][j] = 0;
moved = true;
}
current++; // Increment current position
}
}
// Merge adjacent identical tiles in the current row
for (int j = 0; j < gameBoard[0].length - 1; j++) {
if (gameBoard[i][j] == gameBoard[i][j + 1] && gameBoard[i][j] != 0) {
gameBoard[i][j] *= 2;
gameBoard[i][j + 1] = 0;
moved = true;
}
}
}
// Secondary slide without merge in the up direction
for (int i = 0; i < gameBoard.length; i++) {
int current = 0; // Track current position to place next tile
for (int j = 0; j < gameBoard[0].length; j++) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != j) { // There's a gap, move the tile
gameBoard[i][current] = value;
gameBoard[i][j] = 0;
moved = true;
}
current++; // Increment current position
}
}
}
break;

case DOWN:
/* Loop through each row */
for (int i = 0; i < gameBoard.length; i++) {
int current = gameBoard[0].length - 1; // Track current position to place next tile
/* Loop through each column in the current row in reverse order */
for (int j = gameBoard[0].length - 1; j >= 0; j--) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != j) { // There's a gap, move the tile
gameBoard[i][current] = value;
gameBoard[i][j] = 0;
moved = true;
}
current--; // Decrement current position
}
}
// Merge adjacent identical tiles in the current row
for (int j = gameBoard[0].length - 1; j > 0; j--) {
if (gameBoard[i][j] == gameBoard[i][j - 1] && gameBoard[i][j] != 0) {
gameBoard[i][j] *= 2;
gameBoard[i][j - 1] = 0;
moved = true;
}
}
}
// Secondary slide without merge in the down direction
for (int i = 0; i < gameBoard.length; i++) {
int current = gameBoard[0].length - 1; // Track current position to place next tile
/* Loop through each column in the current row in reverse order */
for (int j = gameBoard[0].length - 1; j >= 0; j--) {
int value = gameBoard[i][j];
if (value != 0) { // Non-zero tile
if (current != j) { // There's a gap, move the tile
gameBoard[i][current] = value;
gameBoard[i][j] = 0;
moved = true;
}
current--;  // Decrement current position
}
}
}
break;

case UPLEFT:
/* Loop through each row, starting from the second-to-last row */
for (int row = gameBoard.length - 1; row > 0; row--) {
/* Loop through each column, starting from the second-to-last column */
for (int col = gameBoard[0].length - 1; col > 0; col--) {
if (gameBoard[row][col] != 0) {
/* If the tile to the up-left has the same value, merge them */
if (gameBoard[row][col] == gameBoard[row - 1][col - 1]) {
gameBoard[row - 1][col - 1] *= 2;
gameBoard[row][col] = 0;
moved = true;
}
/* If the tile to the up-left is empty, move the current tile there */
else if (gameBoard[row - 1][col - 1] == 0) {
gameBoard[row - 1][col - 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
// Secondary slide without merge in the up-left direction
for (int row = gameBoard.length - 1; row > 0; row--) {
for (int col = gameBoard[0].length - 1; col > 0; col--) {
/* If the current tile is non-zero and the tile to the up-left is empty, move the current tile there */
if (gameBoard[row][col] != 0 && gameBoard[row - 1][col - 1] == 0) {
gameBoard[row - 1][col - 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
break;

case UPRIGHT:
/* Loop through each row */
for (int row = 0; row < gameBoard.length; row++) {
/* Loop through each column in reverse order, starting from the second-to-last column */
for (int col = gameBoard[0].length - 1; col >= 0; col--) {
if (row < gameBoard.length - 1 && col > 0) {
/* If the tile to the up-right has the same value, merge them */
if (gameBoard[row][col] == gameBoard[row + 1][col - 1] && gameBoard[row][col] != 0) {
gameBoard[row + 1][col - 1] *= 2;
gameBoard[row][col] = 0;
moved = true;
}
/* If the tile to the up-right is empty, move the current tile there */
else if (gameBoard[row + 1][col - 1] == 0 && gameBoard[row][col] != 0) {
gameBoard[row + 1][col - 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
/* Secondary slide without merge in the up-right direction */
for (int row = 0; row < gameBoard.length; row++) {
for (int col = gameBoard[0].length - 1; col >= 0; col--) {
if (row < gameBoard.length - 1 && col > 0) {
/* If the current tile is non-zero and the tile to the up-right is empty, move the current tile there */
if (gameBoard[row][col] != 0 && gameBoard[row + 1][col - 1] == 0) {
gameBoard[row + 1][col - 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
break;

case DOWNLEFT:
/* Loop through each row in reverse order, starting from the second-to-last row */
for (int row = gameBoard.length - 1; row >= 0; row--) {
/* Loop through each column, starting from the second column */
for (int col = 0; col < gameBoard[0].length - 1; col++) {
if (row > 0 && col < gameBoard[0].length - 1) {
/* If the tile to the down-left has the same value, merge them */
if (gameBoard[row][col] == gameBoard[row - 1][col + 1] && gameBoard[row][col] != 0) {
gameBoard[row - 1][col + 1] *= 2;
gameBoard[row][col] = 0;
moved = true;
}
/* If the tile to the down-left is empty, move the current tile there */
else if (gameBoard[row - 1][col + 1] == 0 &&  gameBoard[row][col] != 0) {
gameBoard[row - 1][col + 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
/* Secondary slide without merge in the down-left direction */
for (int row = gameBoard.length - 1; row >= 0; row--) {
for (int col = 0; col < gameBoard[0].length - 1; col++) {
if (row > 0 && col < gameBoard[0].length - 1) {
/* If the current tile is non-zero and the tile to the down-left is empty, move the current tile there */
if (gameBoard[row][col] != 0 && gameBoard[row - 1][col + 1] == 0) {
gameBoard[row - 1][col + 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
break;

case DOWNRIGHT:
/* Loop through each row in reverse order */
for (int row = gameBoard.length - 1; row >= 0; row--) {
/* Loop through each column in reverse order */
for (int col = gameBoard[0].length - 1; col >= 0; col--) {
if (row >= 0 && col >= 0) {
if (col < gameBoard[0].length - 1 && row < gameBoard.length - 1) {
/* If the tile to the down-right has the same value, merge them */
if (gameBoard[row][col] == gameBoard[row + 1][col + 1] && gameBoard[row][col] != 0) {
gameBoard[row + 1][col + 1] *= 2;
gameBoard[row][col] = 0;
moved = true;
}
/* If the tile to the down-right is empty, move the current tile there */
else if (gameBoard[row + 1][col + 1] == 0 && gameBoard[row][col] != 0) {
gameBoard[row + 1][col + 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
}
/* Secondary slide without merge in the down-right direction */
for (int row = gameBoard.length - 1; row >= 0; row--) {
for (int col = gameBoard[0].length - 1; col >= 0; col--) {
if (row >= 0 && col >= 0) {
if (col < gameBoard[0].length - 1 && row < gameBoard.length - 1) {
/* If the current tile is non-zero and the tile to the down-right is empty, move the current tile there */
if (gameBoard[row][col] != 0 && gameBoard[row + 1][col + 1] == 0) {
gameBoard[row + 1][col + 1] = gameBoard[row][col];
gameBoard[row][col] = 0;
moved = true;
}
}
}
}
}
break;

default:
/* If a move has been made, generate a new tile and update the board */
if (moved) {
generateTile();
updateBoard(board);
}
break;
}
}

/**
* Creates a CSS style string for a tile with a gradient background color based on the provided base color and value.
*
* @param baseColor The base color to use for the gradient.
* @param value     The value of the tile, used to calculate the gradient color.
* @return The CSS style string for the tile.
*/
public String createGradientStyle(Color baseColor, int value) {
Color tileColor = calculateColor(baseColor, value); // Calculate the final color for the tile based on the base color and value

return "-fx-background-color: rgba(" +
Math.round(tileColor.getRed() * 255) + "," + // Red component of the tile color
Math.round(tileColor.getGreen() * 255) + "," + // Green component of the tile color
Math.round(tileColor.getBlue() * 255) + "," + // Blue component of the tile color
tileColor.getOpacity() + ");" + // Opacity of the tile color
"-fx-background-radius: 5px;" + // Rounded corners for the tile background
"-fx-effect: dropshadow(three-pass-box, rgba(0,0,0,0.4), 5, 0, 0, 1);" + // Drop shadow effect for the tile
"-fx-border-color: #ccc;"  + // Border color for the tile
"-fx-border-width: 1px;" + // Border width for the tile
"-fx-font-family: \"Arial Black\";" + // Font family for the tile text
"-fx-font-size: 24px;" + // Font size for the tile text
"-fx-text-fill: white;" + // Text color for the tile text
"-fx-font-weight: bold;" + // Font weight for the tile text
"-fx-padding: 10px;" + // Padding around the tile text
"-fx-min-width: 75px;" + // Minimum width for the tile
"-fx-min-height: 75px;" + // Minimum height for the tile
"-fx-max-width: 75px;" + // Maximum width for the tile
"-fx-max-height: 75px;"; // Maximum height for the tile
}

/**
* Calculates the color for a tile based on the provided base color and value.
*
* @param baseColor The base color to use for the tile.
* @param value     The value of the tile, used to calculate the final color.
* @return The calculated color for the tile.
*/
public Color calculateColor(Color baseColor, int value) {
if (value 

Подробнее здесь: [url]https://stackoverflow.com/questions/78355898/creating-a-slidegame-similar-to-2048-using-javafx[/url]
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «JAVA»