Vier gewinnt: GUI aktualisiert sich nicht

Anyone

Mitglied
Guten Abend,

im Rahmen meines Studiums müssen wir als Hausaufgabe ein Vier-Gewinnt spiel mit Java programmieren. Uns wurden zwei Möglichkeiten der Implementierung gegeben:

a) Vier-Gewinnt ohne Computerspieler (also zwei menschliche Spieler gegeneinander)
b) Vier-Gewinnt mit Computerspieler

Ich habe mich für die Variante mit dem Computerspieler entschieden. Zwei Schwierigkeitsgrade stehen zur Auswahl: Einfach und Mittel. Beim einfachen Schwierigkeitsgrad werden Steine durch den Computer per Zufall gesetzt. Die mittlere Schwierigkeitsstufe geht dabei folgendermaßen vor:

1. Kann der Computer durch setzen eines Steines gewinnen? Wenn ja, dann tut er dies.
2. Kann der Computer durch setzen eines Steines den Sieg des menschlichen Spielers verhindern? Wenn ja, dann tut er dies.
3. Falls 1. und 2. nicht zutreffen wird ein Stein zufällig gesetzt.

Das Spiel funktioniert tadellos. Nun möchte ich das Spiel auch grafisch ein wenig ansprechender machen. Momentan wird nach dem Stein setzen des menschlichen Spielers sofort der Stein des Computerspielers gesetzt. Ich würde gerne eine Zeitspanne von einer halben Sekunde dazwischen schalten. Das mit der halben Sekunde funktioniert auch prima, allerdings wartet das Programm die halbe Sekunde ab und setzt dann beide Steine (den des menschlichen Spielers und den des Computers).

Hier sind die entscheidenden Quellcodezeilen:

Klasse PitchModel
Java:
	public void set(int column, Player humanPlayer)
	{
		if (!this.areColumnsFull()) {
			if (!this.isColumnFull(column)) {
				// human Player turn
				boolean humanVictory = this.setStone(column, humanPlayer);
				
				if (!humanVictory) {
					try {
						// computer Player turn
						this.strategy.setPitch(this);
						this.setStone(this.strategy.perform(), this.strategy.getComputerPlayer());	
						Thread.sleep(500);
					}
					catch (InterruptedException e) {
						
					}
				}
			} 	
		}
		else {
			PitchEvent event = new PitchEvent();
			event.setState(ConnectFourConstants.TIED);
			this.notify(event);
		}
	}

	public boolean setStone(int column, Player player)
	{
		PitchEvent event = new PitchEvent();
		int affectedRow = 0;
		int affectedColumn = column;
		
		for (int i = 0; i < this.rows; i++) {
			if (i < this.rows-1) {
				if (pitch[i+1][column] == 0) {
					continue;
				}
				else {
					pitch[i][column] = player.getId();
					affectedRow = i;
					break;
				}
			}
			else {
				if (pitch[i][column] == 0) {
					pitch[i][column] = player.getId();
					affectedRow = i;
				}
			}
		}
		
		if (this.isWon(affectedRow, affectedColumn, player)) {
			event.setState(ConnectFourConstants.WIN);
			event.setPlayer(player);
			event.setAffectedRow(affectedRow);
			event.setAffectedColumn(affectedColumn);
			
			this.notify(event);
			return true;
		}
		
		event.setState(ConnectFourConstants.UNDECIDED);
		event.setPlayer(player);
		event.setAffectedRow(affectedRow);
		event.setAffectedColumn(affectedColumn);
		
		this.notify(event);
		return false;
	}

	public void notify(PitchEvent event)
	{
		this.view.refresh(event);
	}

und die Methode der View-Klasse, die für das visuelle Setzen der Steine verantwortlich ist:

Java:
	public void refresh(PitchEvent event)
	{
		if (event.getState() == ConnectFourConstants.WIN) {
			ImageIcon stone = event.getPlayer().getStone();
			JButton button = this.fields[event.getAffectedRow()][event.getAffectedColumn()];
			button.setEnabled(true);
			button.setIcon(stone);
			
			if (!event.getPlayer().getName().equals(this.playerNameText.getText())) {
				JOptionPane.showMessageDialog(null, "Sie haben leider verloren!");
				System.exit(0);
			}
			else {
				JOptionPane.showMessageDialog(null, "Herzlichen Glückwunsch, Sie haben gewonnen!");	
				System.exit(0);
			}
		}
		
		if (event.getState() == ConnectFourConstants.TIED) {
			JOptionPane.showMessageDialog(null, "Unentschieden!");
			System.exit(0);
		}
		
		if (event.getState() == ConnectFourConstants.UNDECIDED) {
			ImageIcon stone = event.getPlayer().getStone();
			JButton button = this.fields[event.getAffectedRow()][event.getAffectedColumn()];
			button.setEnabled(true);
			button.setIcon(stone);
		}
	}

Vielleicht könntet ihr mir helfen, warum der die GUI nicht vor dem Thread.sleep und danach aktualisiert, sondern erst nach dem Thread.sleep? Wäre euch sehr dankbar.
 
Zuletzt bearbeitet:

ruerob

Mitglied
Guten Abend,

ich glaube, deine bisherige Methode sorgt dafür, dass beide Steine gesetzt werden und dann der Thread für 500 millis eingeschläfert wird, was dazu führt, dass das Zeichnen des Spielfeldes auch nicht mehr erledigt werden kann, bis der Thread aufwacht. Leider kenn ich mich mit Buttons und so nicht so gut aus und weiß daher nichts darüber, ob da bei dir jetzt extra Threads fürs Zeichnen angelegt werden. Ich würde es jetzt erstmal über folgende Schleife probieren:


Java:
                        // computer Player turn
                        int time = System.currentTimeMillis()+500;
                        while(time>=System.currentTimeMillis()){
                            Thread.sleep(10);
                        }

                        this.strategy.setPitch(this);
                        this.setStone(this.strategy.perform(), this.strategy.getComputerPlayer());

Ich kann dir jetzt aber nicht versprechen, dass das funktioniert.

Viel Glück,

ruerob.
 

Volvagia

Top Contributor
Wird set in einen separaten Thread ausgeführt?
Falls nicht ist es wohl wieder das alte Problem. Der EDT ändert alles, kann aber wärend des Wartens nicht neu zeichnen.
 

Volvagia

Top Contributor
Wenn set von einen EventListener etc. abgearbeitet wird erledigt das der Event Dispatcher. Dieser arbeitet hintereinander eine Warteschlange von Events ab. Auch zeichnen. Falls dein Event ihn blockiert kann er in der Zwischenzeit das Zeichnen-Event nicht abarbeiten.

Du könntest es mal ganz grob so versuchen:

Java:
public void set(int column, Player humanPlayer)
{
	//Eingabe blockieren, damit in der Zwischenzeit nichts geändert werden kann
	
	if (!this.areColumnsFull()) {
    	if (!this.isColumnFull(column)) {
    		new SwingWorker<Void, Void>() {
    			protected Void doInBackground() throws Exception {
    				// human Player turn
                    boolean humanVictory = this.setStone(column, humanPlayer);
                    
                    if (!humanVictory) {
                        // computer Player turn
                    	try {
                            Thread.sleep(500);
                        }
                        catch (InterruptedException e) {
                            
                        }
                    	this.strategy.setPitch(this);
                        this.setStone(this.strategy.perform(), this.strategy.getComputerPlayer());
                    }
    	        }
    			protected void done() {
    				try {
    					get();
    				} catch(InterruptedException e) {
    				} catch (ExecutionException e) {
    					e.printStackTrace();
					}
    				
    				//Eingabe Freigeben
    			}
    		}.execute();
    	}
	} else {
		PitchEvent event = new PitchEvent();
		event.setState(ConnectFourConstants.TIED);
		this.notify(event);
	}
}

Dabei musst du aber aufpassen, dass alles, das GUI-Änderungen vornimmt auch im EDT durchgeführt wird.
 

Anyone

Mitglied
Ich danke dir vielmals, mit deinem Lösungsweg hat das prima funktioniert. Schön, dass man immer wieder neue Sachen dazu lernen kann. :)
 

ruerob

Mitglied
Ich habs, schreibe
Java:
button.paintImmediately(button.getBounds());
in Zeile 8, dann müsste es funktionieren, wenn du das Thread.sleep(500); ausführst, bevor du den Stein des Computerspielers setzt.

Viel Erfolg,

ruerob

EDIT: Viel zu spät...
 

Anyone

Mitglied
Ich habs, schreibe
Java:
button.paintImmediately(button.getBounds());
in Zeile 8, dann müsste es funktionieren, wenn du das Thread.sleep(500); ausführst, bevor du den Stein des Computerspielers setzt.

Viel Erfolg,

ruerob

EDIT: Viel zu spät...

Nein, das funktioniert nicht :D Trotzdem auch ein Danke an dich. :)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
F Konstruktor für "Vier Gewinnt" AWT, Swing, JavaFX & SWT 10
L Swing Vier Gewinnt Problem AWT, Swing, JavaFX & SWT 2
Private Void Swing "Vier Gewinnt"-Oberfläche AWT, Swing, JavaFX & SWT 7
F Eingabe in JPasswordField auf vier Zeichen beschränken AWT, Swing, JavaFX & SWT 3
M 4-Gewinnt mit Buttons AWT, Swing, JavaFX & SWT 1
Z Canvas in Frame einfügen. Problem mit 4-Gewinnt AWT, Swing, JavaFX & SWT 1
P Zeichnen von Ovalen in Swing (4 Gewinnt) AWT, Swing, JavaFX & SWT 3
F 4-Gewinnt als Applet AWT, Swing, JavaFX & SWT 24
S Ausgabe aktualisiert sich nur nach 2. Klick AWT, Swing, JavaFX & SWT 17
F JList aktualisiert nicht AWT, Swing, JavaFX & SWT 24
K Swing GUI aktualisiert nicht richtig AWT, Swing, JavaFX & SWT 5
J Meine ProgBar und ProgIndi werden nicht aktualisiert AWT, Swing, JavaFX & SWT 28
M JTextArea wird nicht aktualisiert (ActionListener-Problem) AWT, Swing, JavaFX & SWT 1
F AWT Grafik wird nicht richtig aktualisiert AWT, Swing, JavaFX & SWT 2
J AWT choice mit viel Auswahl aktualisiert sich nicht korrekt beim scrollen?! AWT, Swing, JavaFX & SWT 3
T Java Swing Oberfläche aktualisiert sich nicht AWT, Swing, JavaFX & SWT 2
J Swing Progressbar aktualisiert sich nicht AWT, Swing, JavaFX & SWT 17
C JLabel wird nicht aktualisiert AWT, Swing, JavaFX & SWT 3
D JTabke aktualisiert sich nicht AWT, Swing, JavaFX & SWT 4
El_Lobo Swing Swing TextArea und JTextField werden nicht aktualisiert AWT, Swing, JavaFX & SWT 2
N Tabellenzelle wird bei JCombBox mit eigenem Datentyp nicht aktualisiert AWT, Swing, JavaFX & SWT 7
F Timer welches JPanel aktualisiert AWT, Swing, JavaFX & SWT 6
N JLabel Text aktualisiert sich nicht AWT, Swing, JavaFX & SWT 2
K JTable wird nicht aktualisiert, wenn Filter gesetzt ist AWT, Swing, JavaFX & SWT 9
R AWT JList wird nur zufällig auf der GUI aktualisiert AWT, Swing, JavaFX & SWT 5
P Swing GUI aktualisiert sich nicht AWT, Swing, JavaFX & SWT 7
S Jtable wird nicht aktualisiert AWT, Swing, JavaFX & SWT 8
M Graphics-Objekt aktualisiert sich nicht AWT, Swing, JavaFX & SWT 2
C Swing JProgressBar Aktualisiert sich nicht. AWT, Swing, JavaFX & SWT 9
I Swing Warten, bis eine GUI-Komponente aktualisiert ist? AWT, Swing, JavaFX & SWT 4
C (Swing)GUI-Elemente werden nicht aktualisiert. AWT, Swing, JavaFX & SWT 2
S Swing JList in JScrollPane aktualisiert sich nicht AWT, Swing, JavaFX & SWT 6
PAX JList aktualisiert zu langsam beim Hinzufügen von Einträgen AWT, Swing, JavaFX & SWT 6
C JTree wird nicht aktualisiert AWT, Swing, JavaFX & SWT 3
A Gui Komponenten werden nicht von selbst aktualisiert! AWT, Swing, JavaFX & SWT 2
K Textfeld wird nur jedes zweite Mal aktualisiert AWT, Swing, JavaFX & SWT 3
T JPanel aktualisiert nicht AWT, Swing, JavaFX & SWT 3
C JTable aktualisiert die Anzeige nicht AWT, Swing, JavaFX & SWT 2
R GUI wird nicht richtig aktualisiert AWT, Swing, JavaFX & SWT 5
G JList wird in einem Applet nur teilweise aktualisiert AWT, Swing, JavaFX & SWT 12
G JTable (AbstractTableModel) wird nicht aktualisiert AWT, Swing, JavaFX & SWT 2
J JTextArea wird nicht aktualisiert bei Zugriff von außerhalb AWT, Swing, JavaFX & SWT 2
A JTree wird erst nach Klick aktualisiert AWT, Swing, JavaFX & SWT 2
S JLabel aktualisiert sich nicht AWT, Swing, JavaFX & SWT 4
G Tabelle aktualisiert sich erst, nachdem man auf sie klickt! AWT, Swing, JavaFX & SWT 4
B TreeViewer für das Dateisystem, der sich selbst aktualisiert AWT, Swing, JavaFX & SWT 8
J Dialogfenster wird nicht aktualisiert/CardLayout AWT, Swing, JavaFX & SWT 6
raptorrs JTextfelder werden in while-Schleife nicht aktualisiert AWT, Swing, JavaFX & SWT 5
L JProgressBar wird nicht mehr aktualisiert AWT, Swing, JavaFX & SWT 2
O Choice/Combobox wird nur 1x aktualisiert AWT, Swing, JavaFX & SWT 3
G Progressbar aktualisiert sich nicht (vernünftig). WIESO? AWT, Swing, JavaFX & SWT 2
G Mein JFrame aktualisiert sich nicht richtig AWT, Swing, JavaFX & SWT 3

Ähnliche Java Themen


Oben