GUI für Vier-Gewinnt.

malo.3

Mitglied
Hallo, ich stehe vor folgendem Problem. Ich habe bereits ein Vier Gewinnt für die Konsole programmiert, scheitere jetzt aber, eine GUI darüber zu legen. Ich weiß zu diesem Thema gab es schon ältere Posts, jedoch konnte mir keiner so richtig weiterhelfen, weshalb ich jetzt einen eigenen erstelle. Zur Information, ich programmiere erst seit ca. 2 1/2 Monaten mit Java, entschuldigt deshalb die eventuell schlechte Qualität meines Codes. Ich poste hier mal meinen Code von meinem aktuellen Konsolen-Programm und das Spielfeld, welches ich schon mit GUI erstellt habe. Nun zu meinem Problem. Ich weiß einfach nicht, wie ich meine Tokens in die Buttons gesetzt bekomme. Ich muss meine setToken Methode in der Klasse Field darauf anpassen, weiß aber wirklich nicht wie. Ich habe mir das ganze so gedacht, dass man nur die Buttons 1-7 drücken kann, und der Spielstein entsprechend der Spalte im untersten freien Button erscheint. In dem weißen leeren JPanel möchte ich später den Gewinner ausgeben, aber soweit bin ich noch nicht. Die Spielsteine sollen erstmal korrekt gesetzt werden, vielleicht kann ich mir die Gewinnbedingung dann selbst herleiten und auf mein Feld anwenden. Ich bin wirklich dankbar für jede Hilfe.
Die Main Klasse
Java:
public class Main {

    public static void main(String[] args) {
        Field fieldObject = new Field();
        UserInput userInput = new UserInput();
        Rules rules = new Rules(fieldObject, userInput);
        Procedure procedure = new Procedure(fieldObject, userInput, rules);
        procedure.startMenue();

    }
}

Die Procedure Klasse

Code:
import java.util.Scanner;

public class Procedure {
    private final Field fieldObject;
    private final UserInput userInput;
    private final Rules rules;
    private final Player player1;
    private final Player player2;

    public Procedure(Field fieldObject, UserInput userInput, Rules rules) {
        this.fieldObject = fieldObject;
        this.userInput = userInput;
        this.rules = rules;
        this.player1 = new Player('X', this.userInput.getInputNameOne());
        this.player2 = new Player('O', this.userInput.getInputNameTwo());
    }

    public void startGame() {

        Player currentPlayer = player1;

        System.out.println('\n' + userInput.getInputNameOne() + " beginnt." + '\n');
        this.fieldObject.drawNewField();
        System.out.println('\n' + " Bitte gib die Spalte an, in der du deinen Spielstein setzen möchtest.");
        while (!(this.userInput.getInputColumn() > 0 && this.userInput.getInputColumn() <= 7)) {
            this.userInput.getColumn();
            if (this.userInput.getInputColumn() <= 0 || this.userInput.getInputColumn() > 7) {
                System.out.println("Eingabe ungültig, Spielstein konnte nicht gesetzt werden");
            }
            while (this.userInput.getInputColumn() > 0 && this.userInput.getInputColumn() <= 7) {
                this.fieldObject.setToken(currentPlayer.getSymbol(), this.userInput.getInputColumn());
                this.userInput.setInputColumn();
                this.fieldObject.drawField();
                rules.checkForWinOrDraw();
                System.out.println('\n' + " Bitte gib die Spalte an, in der du deinen Spielstein setzen möchtest.");
                if (currentPlayer.getSymbol() == 'X') {

                    currentPlayer = player2;
                } else {
                    currentPlayer = player1;
                }
[CODE]

Die Field Klasse
[CODE]public class Field {

    private final int row = 6;
    private final int column = 7;
    private final char[][] field = new char[row][column];

    public void columnName(int n) {
        for (int i = 1; i <= n; i++) {
            System.out.print(i + "   ");
        }
        System.out.println();
    }

    public void drawNewField() {
        columnName(7);

        for (int i = 0; i < this.field.length; i++) {
            char[] row = this.field[i];
            for (int j = 0; j < row.length; j++) {
                char underline = '_';
                this.field[i][j] = underline;
                System.out.print(row[j] + " | ");
            }
            System.out.println();
        }
    }

    public void drawField() {
        columnName(7);

        for (int i = 0; i < this.field.length; i++) {
            char[] row = this.field[i];
            for (int j = 0; j < row.length; j++) {
                char underline = this.field[i][j];
                this.field[i][j] = underline;
                System.out.print(row[j] + " | ");
            }
            System.out.println();
        }
    }

    public void setToken(char symbol, int column) {
        int x = this.field.length - 1;
        boolean keepGoing = true;

        while (x >= 0 && keepGoing) {
            if (this.field[x][column - 1] == '_') {
                this.field[x][column - 1] = symbol;
                keepGoing = false;
            }
            x--;
        }
    }

    public char[][] getField() {
        return field;
    }
}

Die UserInput Klasse
Code:
import java.util.Scanner;

public class UserInput {
    private int columnInput;
    private String player1;
    private String player2;

    private final Scanner sc = new Scanner(System.in);


    public void getNameOne() {
        this.player1 = sc.nextLine();
    }

    public void getNameTwo() {
        this.player2 = sc.nextLine();
    }

    public String getInputNameOne() {
        return this.player1;
    }

    public String getInputNameTwo() {
        return this.player2;
    }


    public void getColumn() {
        this.columnInput = sc.nextInt();
    }

    public int getInputColumn() {
        return this.columnInput;
    }

    public void setInputColumn() {
        this.columnInput = 0;
    }
}

Die Rules Klasse
Code:
public class Rules {
    final Field field;
    final UserInput userInput;

    public Rules(Field field, UserInput userInput) {
        this.field = field;
        this.userInput = userInput;
    }

    public void checkForWinOrDraw() {  // Überprüfen, ob es horizontal, vertikal oder diagonale Gewinner gibt
        Procedure procedure = new Procedure(field, userInput, null);

        for (int i = 0; i <= 2; i++) { //horizontal
            for (int j = 0; j <= 6; j++) {
                if (field.getField()[i][j] == 'X' && field.getField()[i + 1][j] == 'X' && field.getField()[i + 2][j] == 'X' && field.getField()[i + 3][j] == 'X') {
                    System.out.println('\n' + procedure.getPlayer1().getName() + " hat gewonnen.");
                    System.exit(0);
                }
                if (field.getField()[i][j] == 'O' && field.getField()[i + 1][j] == 'O' && field.getField()[i + 2][j] == 'O' && field.getField()[i + 3][j] == 'O') {
                    System.out.println('\n' + procedure.getPlayer2().getName() + " hat gewonnen.");
                    System.exit(0);
                }
            }
        }
        for (int i = 0; i <= 5; i++) { //vertikal
            for (int j = 0; j <= 3; j++) {
                if (field.getField()[i][j] == 'X' && field.getField()[i][j + 1] == 'X' && field.getField()[i][j + 2] == 'X' && field.getField()[i][j + 3] == 'X') {
                    System.out.println('\n' + procedure.getPlayer1().getName() + " hat gewonnen.");
                    System.exit(0);
                }
                if (field.getField()[i][j] == 'O' && field.getField()[i][j + 1] == 'O' && field.getField()[i][j + 2] == 'O' && field.getField()[i][j + 3] == 'O') {
                    System.out.println('\n' + procedure.getPlayer2().getName() + " hat gewonnen.");
                    System.exit(0);
                }
            }
        }
        for (int i = 0; i < 3; i++) { // diagonal nach oben
            for (int j = 6; j > 2; j--) {
                if (field.getField()[i][j] == 'X' && field.getField()[i + 1][j - 1] == 'X' && field.getField()[i + 2][j - 2] == 'X' && field.getField()[i + 3][j - 3] == 'X') {
                    System.out.println('\n' + procedure.getPlayer1().getName() + " hat gewonnen.");
                    System.exit(0);
                }
                if (field.getField()[i][j] == 'O' && field.getField()[i + 1][j - 1] == 'O' && field.getField()[i + 2][j - 2] == 'O' && field.getField()[i + 3][j - 3] == 'O') {
                    System.out.println('\n' + procedure.getPlayer2().getName() + " hat gewonnen.");
                    System.exit(0);
                }
            }
        }
        for (int i = 0; i < 3; i++) { //diagonal nach unten
            for (int j = 0; j < 4; j++) {
                if (field.getField()[i][j] == 'X' && field.getField()[i + 1][j + 1] == 'X' && field.getField()[i + 2][j + 2] == 'X' && field.getField()[i + 3][j + 3] == 'X') {
                    System.out.println('\n' + procedure.getPlayer1().getName() + " hat gewonnen.");
                    System.exit(0);
                }
                if (field.getField()[i][j] == 'O' && field.getField()[i + 1][j + 1] == 'O' && field.getField()[i + 2][j + 2] == 'O' && field.getField()[i + 3][j + 3] == 'O') {
                    System.out.println('\n' + procedure.getPlayer2().getName() + " hat gewonnen.");
                    System.exit(0);
                }
            }
        }
        for (int i = 0; i < field.getField().length; i++) { // Spielfeld voll
            for (int j = 0; j < field.getField()[i].length; j++) {
                if (field.getField()[i][j] == '_') {
                    return;
                }
            }
        }
        System.out.println('\n' + "Das Spielfeld ist voll. Das Spiel endet unentschieden.");
    }
}

Und die Player Klasse
Code:
public class Player {
    char symbol;
    String name;

    public Player(char symbol, String name) {
        this.symbol = symbol;
        this.name = name;
    }

    public char getSymbol() {
        return symbol;
    }
    public String getName(){
        return name;
    }
}

Und hier der Code meines mit GUI erstellten Spielbretts
Code:
public class Gameboard {
    public void Draw() {
        // Erstelle den Frame
        JFrame frame = new JFrame("Vier Gewinnt");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setUndecorated(true);

        frame.setLayout(new BorderLayout());


        // Erstelle das Panel mit einem Grid Layout
        JPanel topPanel = new JPanel(new GridLayout(7, 7, 5, 5));
        topPanel.setPreferredSize(new Dimension(1080, 600));

        // Füge die Buttons hinzu
        for (int i = 1; i <= 7; i++) {
            JButton button = new JButton(String.valueOf(i));
            button.setForeground(Color.GREEN);
            button.setFont(new Font("arial", Font.BOLD, 20));
//                button.addActionListener(this::buttonaction);
            button.setBackground(Color.BLACK);
            button.setFocusPainted(false);
            topPanel.add(button);
        }

        // Deaktiviere die restlichen Buttons
        for (int i = 8; i <= 49; i++) {
            JButton button = new JButton();
            button.setEnabled(false);
            button.setForeground(Color.black);
//                button.addActionListener(this::buttonaction);
            button.setBackground(Color.BLACK);
            button.setFocusPainted(false);
            topPanel.add(button);
        }


        frame.setPreferredSize(new Dimension(1080, 720));
        topPanel.setBackground(Color.DARK_GRAY);
        // Füge das Panel dem Frame hinzu
        JPanel bottomPanel = new JPanel();
        frame.add(topPanel, BorderLayout.NORTH);
        frame.add(bottomPanel, BorderLayout.SOUTH);

        // Zeige den Frame an
        frame.pack();
        frame.setVisible(true);

    }
}
 
entschuldigt deshalb die eventuell schlechte Qualität meines Codes.
LOL, das kommt anscheinend falsch rüber. Wir stellen (so gut wie) keine Anforderung an die Qualität des Codes, sondern geben diesbezüglich Hinweise. Die einzige Anforderung, die ich habe: ich muss das noch entziffern können und zwar ohne, dass ich mich jetzt stundenlang einlesen oder den Spaß erstmal in eine IDE laden muss, um die Formatierung anzupassen (das betrifft dann eher die Qualität des Postings). Dann kommt schon mal ein entsprechender Kommentar 🙂


Nun zu meinem Problem. Ich weiß einfach nicht, wie ich meine Tokens in die Buttons gesetzt bekomme. Ich muss meine setToken Methode in der Klasse Field darauf anpassen, weiß aber wirklich nicht wie.
Nein, die setTokens-Methode ist in Klasse Field, die hat nichts mit dem GUI zu tun und muss nicht angepasst werden. Deine Buttons dienen nur der Visualisierung von Field (und der Benutzereingabe, das ist dann ein anderes Thema). Nach welcher Logik setToken() Field ändert, muss die Buttons nicht interessieren.

Du könntest Dir eine Methode anlegen, die sich von Field alle Felder holt und die Inhalte auf die Buttons überträgt.

Ich habe mir das ganze so gedacht, dass man nur die Buttons 1-7 drücken kann, und der Spielstein entsprechend der Spalte im untersten freien Button erscheint.
Ja, warum auch nicht? Diese sieben Buttons ersetzen einfach die Konsoleneingabe.
 
LOL, das kommt anscheinend falsch rüber. Wir stellen (so gut wie) keine Anforderung an die Qualität des Codes, sondern geben diesbezüglich Hinweise. Die einzige Anforderung, die ich habe: ich muss das noch entziffern können und zwar ohne, dass ich mich jetzt stundenlang einlesen oder den Spaß erstmal in eine IDE laden muss, um die Formatierung anzupassen (das betrifft dann eher die Qualität des Postings). Dann kommt schon mal ein entsprechender Kommentar 🙂



Nein, die setTokens-Methode ist in Klasse Field, die hat nichts mit dem GUI zu tun und muss nicht angepasst werden. Deine Buttons dienen nur der Visualisierung von Field (und der Benutzereingabe, das ist dann ein anderes Thema). Nach welcher Logik setToken() Field ändert, muss die Buttons nicht interessieren.

Du könntest Dir eine Methode anlegen, die sich von Field alle Felder holt und die Inhalte auf die Buttons überträgt.


Ja, warum auch nicht? Diese sieben Buttons ersetzen einfach die Konsoleneingabe.
Also könnte man die Eingabe bzw das Click Event Parsen und dann die entsprechende Zahl an die setToken übergeben. Diese setzt den Spielstein in mein 2D Array. Von dort aus müsste ich mir dann den aktuell eingegebenen Spielstein holen und ihn auf den entsprechenden Button printen
 
Also könnte man die Eingabe bzw das Click Event Parsen und dann die entsprechende Zahl an die setToken übergeben.
Ja, Du kannst z. B. setActionCommand verwenden, um den Buttons die "Zahl" mitzugeben und den Spaß anhand des Events abrufen (https://docs.oracle.com/javase/8/docs/api/java/awt/event/ActionEvent.html#getActionCommand--)

Diese setzt den Spielstein in mein 2D Array.
Wie bisher.

Von dort aus müsste ich mir dann den aktuell eingegebenen Spielstein holen und ihn auf den entsprechenden Button printen
"Von dort aus" ist etwas ungünstig formuliert. Du rufst nach setToken() in Deinem ActionListener einfach eine neue Methode auf (updateField() oder etwas in der Richtung). Die Methode holt sich dann die Felder und aktualisiert die Button-Texte/Icons (was auch immer). Wäre jetzt mal eine einfache Möglichkeit.
 
Ja, Du kannst z. B. setActionCommand verwenden, um den Buttons die "Zahl" mitzugeben und den Spaß anhand des Events abrufen (https://docs.oracle.com/javase/8/docs/api/java/awt/event/ActionEvent.html#getActionCommand--)


Wie bisher.


"Von dort aus" ist etwas ungünstig formuliert. Du rufst nach setToken() in Deinem ActionListener einfach eine neue Methode auf (updateField() oder etwas in der Richtung). Die Methode holt sich dann die Felder und aktualisiert die Button-Texte/Icons (was auch immer). Wäre jetzt mal eine einfache Möglichkeit.
Ich danke dir schon mal bei deiner Hilfe für den Ansatz. Werde mich morgen dran setzen und versuchen das ganze umzusetzen xD
 

Zurück
Oben