1

I'm making a checkers game with buttons. To kill another piece, you have to move your piece diagonally over the other piece, but I'm not sure how to ensure that your piece moved over the other piece.

The idea I have for solving this problem is getting the Row and Column of the second button, which is the button that your piece moves to, then subtracting 1 from each Row and Column, then getting the text from that button to test if it is "black" or "red".

first & second = buttons

System.out.println((GridPane.getColumnIndex(second) + " vs " + (GridPane.getColumnIndex(second) - 1)));


    if (GridPane.getColumnIndex(second) > 0) {
        System.out.println("checking if a button has been jumped");
        GridPane.setRowIndex(second, (GridPane.getRowIndex(second) - 1));
        GridPane.setColumnIndex(second, (GridPane.getColumnIndex(second) - 1));
        System.out.println("this is a printing of the second button name for location " + (GridPane.getColumnIndex(second)) + " " + (GridPane.getRowIndex(second)) + " " + second.getText());

        if (second.getText().contains("black")) {
            System.out.println("it's a kill");
        } 
        else {
            System.out.println("no kill");
            GridPane.setRowIndex(second, (GridPane.getRowIndex(second) + 1));
            GridPane.setColumnIndex(second, (GridPane.getColumnIndex(second) + 1));
        }
    }

I'm able to change the Row and Column to what would match the location of the other piece, but when I get the text from that button(second), it doesn't come back as the name "black" or "red", rather just the name of the blank buttons.
My guess is that GridPane's may not work like this, and I just need to come up with another solution, hopefully I won't have to redo my whole code as a 2d array or something.

Travelsbyfire
  • 35
  • 1
  • 10
  • There is nothing like a C++ reference in java. `setColumn/RowIndex` does not change the value passed as first parameter to another node... – fabian Aug 15 '19 at 22:15
  • So really, the only other way would be to have a 2d array of buttons to access a specific node? – Travelsbyfire Aug 16 '19 at 14:06
  • You could find the appropriate child in the child list, but this is imho more complex: https://stackoverflow.com/questions/20825935/javafx-get-node-by-row-and-column If you worry about having to update both the `GridPane` and the array every time you move a child, simply create a method responsible for updating both the layout parameters and the array. – fabian Aug 16 '19 at 18:30
  • I actually just found out how to do it, and I just posted it below. Oh that's a similar code to what I found too. Thanks for the help! – Travelsbyfire Aug 16 '19 at 18:46

2 Answers2

1

So it is possible, and I found the answer from this post. He just had to make his own method to find the specific location. javafx GridPane retrieve specific Cell content

private Node getNodeFromGridPane(GridPane gridPane, int col, int row) {
for (Node node : gridPane.getChildren()) {
    if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {
        return node;
    }
}
return null;

}

Although, for my own purposes, I still need to figure out how to be able to test if the node contains either "red" or "black", so I just added this, and now it all works!

private Boolean getNodeFromGridPane(GridPane gridPane, int col, int row) {

    for (Node node : gridPane.getChildren()) {
        if (GridPane.getColumnIndex(node) == col && GridPane.getRowIndex(node) == row) {

            if (node.toString().contains("black")) {

                System.out.println("The second button is black = " + node.toString().contains("black"));

                return true;
            }

            if (node.toString().contains("red")) {

                System.out.println("The second button is red = " + node.toString().contains("red"));

                return true;
            }

        }
    }
    return false;

}
Travelsbyfire
  • 35
  • 1
  • 10
1

You can get a reference to a node in GridPane by iterating over the GridPane children.
Add some simple calculation to find the diagonal between two buttons clicked, if any:

import java.awt.Toolkit;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.geometry.Insets;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.GridPane;
import javafx.scene.layout.Pane;
import javafx.scene.layout.VBox;
import javafx.scene.text.Text;
import javafx.stage.Stage;
import javafx.util.Duration;

public class FxMain extends Application {

    private static final int COLS = 5, ROWS = 5;
    private int clickCounter = 0;
    private GridPane grid;
    private Button first, second;

    @Override
    public void start(Stage primaryStage){

        VBox root = new VBox(10);
        root.setPadding(new Insets(10));
        root.getChildren().addAll(makeGrid(), 
                new Text("Click 2 buttons to find the \n diagonally between them"));
        primaryStage.setScene(new Scene(root));
        primaryStage.sizeToScene();
        primaryStage.show();
    }

    private Pane makeGrid() {

        grid = new GridPane();
        for(int rowIndex = 0; rowIndex < ROWS ; rowIndex++) {
            //an array to hold buttons of one row
            Node[] nodes = new Node[COLS];
            for(int colIndex = 0; colIndex < COLS ; colIndex++) {
                Button node= new Button(rowIndex+""+colIndex);
                node.setOnAction(e->buttonCliked(node)); //add action listener
                nodes[colIndex]= node;
            }
            grid.addRow(rowIndex, nodes);
        }
        return grid;
    }

    private void buttonCliked(Button button) {

        if(clickCounter == 0){
            first = button;
        }else{
            second = button;
            markNode(findMidDiagonalButton());
        }

        System.out.println(clickCounter + " " + button.getText()    );
        clickCounter=  ++clickCounter %2 ;  // changes values between 0 1
    }

    //change node background for a short while, and then reset it
    private void markNode(Node node) {

        if(node == null) return;
        String style = node.getStyle();
        node.setStyle("-fx-background-color: cornflowerblue;");
        PauseTransition pause = new PauseTransition(Duration.seconds(1));
        pause.play();
        pause.setOnFinished(e-> node.setStyle(style));
    }

    private Node findMidDiagonalButton() {

        int rowDelta = GridPane.getRowIndex(first) - GridPane.getRowIndex(second);
        int colDelta = GridPane.getColumnIndex(first) - GridPane.getColumnIndex(second);

        if( Math.abs(rowDelta) != 2 ||  Math.abs(colDelta) != 2 ){
            Toolkit.getDefaultToolkit().beep();
            return null;
        }

        int rowsSum = GridPane.getRowIndex(first) + GridPane.getRowIndex(second);
        int colsSum = GridPane.getColumnIndex(first) + GridPane.getColumnIndex(second);

        return  getNodeByRowCol(Math.abs(rowsSum / 2), Math.abs(colsSum / 2) );
    }

    public Node getNodeByRowCol (int row, int col) {

        for (Node node : grid.getChildren()) {
            if(GridPane.getRowIndex(node) == row && GridPane.getColumnIndex(node) == col)
                return node;
        }

        return null;
    }

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

enter image description here

c0der
  • 18,467
  • 6
  • 33
  • 65