Frage zu Programmarchitektur

Status
Nicht offen für weitere Antworten.

Ishildur

Bekanntes Mitglied
Hallo zusammen
Ich programmiere gerade ein Mühlespiel und habe ein Riesenproblem mit der Programmarchitektur. Ich habe eine Klasse "Game" welche das Spielbrett sowie die Steine repräsentiert und hauptsächlich zwei Methode "isMoveValid" und "move" bereitstellt. Schliesslich habe ich eine abstrakte Klasse Player, von welcher dann HumanPlayer, RandomPlayer sowie AIPlayer abgeleitet werden. Das Ziel ist, dass ich jeden Typ Player gegen jeden anderen Typ Player spielen lassen kann. Also HumanPlayer gegen AIPlayer, AIPlayer gegen AIPlayer usw. Ich hatte mir das ungefähr so vorgestellt:

while(true){
p1.nextMove();
p2.nextMove();
}

Wenn ich RandomPlayer gegen RandomPlayer, AIPlayer gegen RandomPlayer oder AIPlayer gegen AIPlayer spielen lasse, funktioniert dies auch ganz gut. Das Problem ist nun der Humanplayer, weil der HumanPlayer anders als die beiden anderen Spieltypen ja nicht einfach einen Algorithums abarbeitet und schliesslich zurückkehrt, sondern stattdessen auf Benutzereingaben wartet.

Vielleicht kennt jemand von euch das Problem und kann mir einen Tipp geben?

Mfg Ishildur
 

Marco13

Top Contributor
Beschreib' das Problem mal genauer. Läuft das ganze in einem eigenen Thread, mit GUI ... wie passiert das "Warten auf eine Eingabe"... etc....
 

Niki

Top Contributor
in deiner nextMove Methode vom Player musst du halt so lange warten bis der Benutzer eine Eingabe gemacht hat. Das könnte so aussehen:
Code:
private Move move = null;

public synchronized void nextMove(){
  while(move == null){
    try{
      wait();
    }catch(InterruptedException ex){  
    }
  }

  //mach was mit dem move
  move = null;
}

public synchronized void setMove(Move move){
  this.move = move;
  notify();
}

In der Gui musst du dann bei einem Event dem Player den Move mit teilen:
Code:
public void mousePressed(MouseEvent e){
  Move move = ....;
  //Zuerst muss ermittelt werden welcher Player gerade dran ist...
  player.setMove(move);
}
 

Ishildur

Bekanntes Mitglied
Hmmm naja, aber gibt es da nicht auch eine Variante ohne Threads?
Ich habe mirüberlegt, ob ich so ein Master - Slave Verfahren anwenden soll:

Also einer der Spieler ist der Master und ruft dann einfach den Slave spieler auf, nachdem er (der Master) seinen Zug gemacht hat.

while(true){
// ich bin der Masterspieler und mache meinen Zug
this.getSlavePlayer().nextMove();
}

Wenn mehrere AIPlayer oder RandomPlayer beteiligt sind, spielt es keine Rolle, wer Master und wer Slave ist, sobald allerdings ein HumanPlayer im Spiel ist, muss dieser der Master sein. Diese Architektur löst aber nicht das Problem, wenn beide Spieler HumanPlayers sind... :-(
 

Marco13

Top Contributor
Ishildur hat gesagt.:
Das Problem ist nun der Humanplayer, weil der HumanPlayer anders als die beiden anderen Spieltypen ja nicht einfach einen Algorithums abarbeitet und schliesslich zurückkehrt, sondern stattdessen auf Benutzereingaben wartet.

Das ist kein Problem, sondern das gewünschte Verhalten. Beschreib' genauer, was das Problem ist.
 
M

Michael...

Gast
ohne Threads brauchst Du für jede Spielvariante eine eigene Logik.
KI vs. KI: Schleife, wie gehabt
KI vs. Mensch: Mensch initiert nach eigenem Zug, Zug der KI
Mensch vs. Mensch: jeder macht seinen eigenen Zug und muss auf den Zug des Gegners warten.
 

Marco13

Top Contributor
Die Schleife sollte nur so aussehen, dass alle Spieler nacheinander ihre Züge machen. Wer da auf wen wartet (und was für Spieler-Arten das sind) sollte die Hauptschleife nicht interessieren....
 

Ishildur

Bekanntes Mitglied
@Marco13
Genau das habe ich mir auch gedacht, aber wie kann ich das realisieren? Ich meine ich kann ja nicht das Hauptprogramm so lange unterbrechen, bis der menschliche Spieler seinen Zug getätigt hat, oder? Ich möchte das Ganze ohne Threads realisieren, weil das Spiel zu einem späteren Zeitpunkt auf eine Plattform portieren möchte, die kein Multithreading kennt. Somit würde ich das Problem nur hinauszögern.
 

Marco13

Top Contributor
:roll: Was soll das "Hauptprogramm" (was auch immer das ist) machen, solange ein Benutzer noch nichts eingegeben hat? Einfach mal pauschal weiterspielen oder was...?
 

Ishildur

Bekanntes Mitglied
Hehe, nein natürlich nicht :lol:
Aber die Frage ist, wie kann der HumanPlayer der Applikation mitteilen, dass es nun seinen Zug getätigt hat? Bei den ComputerPlayern gibt es einfach eine Method "nextMove" welche zurückkehrt, sobald der entsprechende Algorithmus durchgearbeitet ist. Das Problem beim HumanPlayer jedoch ist, dass ein Zug erst dann "möglicherweise" getätigt wurde, nachdem der Event "mouseReleased" abgefeuert wurde. Irgendwie passt da alles überhaupt nicht zusammen! :(
 

Marco13

Top Contributor
Ja, die nextMove-Methode muss halt warten, bis die Eingabe gemacht wurde - das ist genau das, was Niki gepostet hatte!
 

parabool

Bekanntes Mitglied
vielleicht über einen "MoveListener"



Code:
interface MoveListener
{
  public  void nextMove(Move move)
}


class Game implements MoveListener
...

game registriert sich dann bei den Spielern als Listener:

Code:
player1.addMoveListener(game)
player2.addMoveListener(game)
...
usw.

egal ob AI-Gegner oder nicht, beide informieren die Game-Klasse mittels Callback-Methode über den Zug

Müsste natürlich noch kontrolliert werden, welcher Spieler am Zug ist (sperren der gegn. Spielers)
 

Ishildur

Bekanntes Mitglied
@parabool
OK, die Spieler informieren die Gameklasse über denn Move, aber wie gehts dann weiter? Wer initiiert schliesslich den nächsten Move? Die Gameklasse kann es ja wohl nicht sein, weil man sonst einen Stackoverflow riskiert, weil die Methoden nie mehr zurückkehren?

Mfg Ishildur
 

Marco13

Top Contributor
Manchen Leuten muss man echt alles vorkauen. Wenn du in folgendem Codestück irgendwas findest, was du noch NICHT selbst geschrieben hattest, und was noch NICHT hier gepostet wurde, sag' bescheid....
Code:
import javax.swing.*;
import java.awt.event.*;




class NineMensMorrisTest
{
    public static void main(String args[])
    {
        //new NineMensMorrisTest(new ComputerPlayer(), new ComputerPlayer()).startGame();
        new NineMensMorrisTest(new ComputerPlayer(), new HumanPlayer()).startGame();
    }

    private Player player0;
    private Player player1;

    public NineMensMorrisTest(Player player0, Player player1)
    {
        this.player0 = player0;
        this.player1 = player1;
    }

    public void startGame()
    {
        for (int i=0; i<5; i++)
        {
            System.out.println("--- Move of player0: "+player0.doMove());
            System.out.println("----Move of player1: "+player1.doMove());
        }
    }
}


interface Player
{
    String doMove();
}

class HumanPlayer extends JFrame implements Player
{
    private String currentMove = null;

    public HumanPlayer()
    {
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JButton b = new JButton("doMove");
        b.addActionListener(new ActionListener()
        {
            public void actionPerformed(ActionEvent e)
            {
                setMove();
            }
        });
        getContentPane().add(b);
        pack();
        setVisible(true);
    }

    private synchronized void setMove()
    {
        currentMove = "HumanPlayerMove";
        notify();
        System.out.println("Got for input from HumanPlayer");
    }


    public synchronized String doMove()
    {
        while (currentMove == null)
        {
            System.out.println("Waiting for input of HumanPlayer");
            try
            {
                wait();
            }
            catch (InterruptedException e)
            {
                e.printStackTrace();
            }
        }
        System.out.println("HumanPlayer returning move...");
        String theMove = currentMove;
        currentMove = null;
        return theMove;
    }
}


class ComputerPlayer implements Player
{
    public String doMove()
    {
        System.out.println("ComputerPlayer computing move...");
        try
        {
            Thread.sleep(2000);
        }
        catch (InterruptedException e)
        {
            e.printStackTrace();
        }
        System.out.println("ComputerPlayer returning move...");
        return "ComputerPlayerMove";
    }

}
 

xysawq

Bekanntes Mitglied
Ach du lieber Schreck...

hab mir die ganze Krankheit hier mal durchgelesen und verstehe nicht, was das Problem sein soll...

Wenn das Programm ohne Threads in einer Schleife läuft und es nur 2 Spieler gibt, wobei jeder entweder AI, Random oder Human sein kann, dann würde ich eine abstrakte Oberklasse Player machen und 3 verschiedene Arten, nämlich Ai, Random und Human die Player erweitern (extends), wobei Player die Methode nextMove() hat und diese abstrahiert.

Code:
public abstract class Player
{
	public abstract Move nextMove();
}

Code:
public class AI extends Player
{
	public Move nextMove()
	{
		//Was deine künstliche Intelligenz eben so macht.
	}
}

Code:
public class Random extends Player
{
	public Move nextMove()
	{
		//Die Generierung deiner zufälligen Moves.
	}
}

Code:
public class Human extends Player implements java.awt.event.MouseListener
{
	Move move = null;
	
	public Move nextMove()
	{		
		while(move == null)
		{
			try
			{
				wait();
			}
			catch(InterruptedException ex)
			{ 
			}
		}
		
		Move temp = move;
		move = null;
		
		return temp;
	}
	
	public void mouseReleased(MouseEvent e)
	{
		//Rumrechnen und
		move = ...;
		//etwas zuweisen;
	}
}


Jetzt kannst du je nach Sielerart die Spieler zuweisen und deine schöne Schleife abarbeiten, aber dein "Hauptprogramm" muss logischerweise immer auf den HumanPlayer warten... es wartet ja auch, bis AI oder Random ihre Berechnungen beendet haben.

Code:
Player player1 = null;
Player player2 = null;

//je nach Auswahl dann später z.B.:
player1 = Human();
player2 = AI();

//und nun kannst du ohne Probleme deine Schleife abarbeiten
while(true)
{
	player1.nextMove();
	//Auswertung des Moves von Player1//
	
	player2.nextMove();
	//Auswertung des Moves von Player2//
}

Ist teilweise aber auch nur das, was die Anderen schon gesagt haben.
 

xysawq

Bekanntes Mitglied
Kurz nachdem ich angefangen habe mir mal darüber Gedanken zu machen kommt wieder Marco und programmiert fast das ganze Spiel...

Vielleicht konnte ich ja trotzdem helfen ;).

(Und ich hab echt fast ne halbe Stunde (mit Klopause) für meine Antwort gebraucht... *schäm*)
 

parabool

Bekanntes Mitglied
EDIT: Ishildur wollte es ja ohne Threads...


Ja natürlich muss da noch eine Steuerung rein.

vielleicht so in etwa (nur prinzipiell):

Code:
class Steuerung implements MoveListener
{
  
   private int counter = 0;
   private Player player0;
   private Player player1; 
   private Game game; 
   private ArrayList<Player> players; 


   public Steuerung(Game game)
  {   
    this.game = game;
    players = ArrayList<Player>();
    players.add(player0);
    players.add(player1);
    player0.addMoveListener(game);
    player1.addMoveListener(game);
    player0.addMoveListener(this);  //auch die Steuerungsklasse wird benachrichtigt
    player1.addMoveListener(this);
  }

  
  //callback-Methode 
  public void nextMove(Move move)  
  {
   
     // player wird benachrichtigt das er am Zug ist // bei Humanplayer zB ev. Buttons  aktivieren ..oder so..
     players.get(counter).duBistDran(); 
     counter++
     if(counter>players.size()-1)counter=0; //erster Spieler wieder am Zug
  }

}


Wer stellt eigentlich fest wann das Spiel beendet/gewonnen ist?
Der Spieler selbst?
Dann die callback-Methode etwas modifizieren:

Code:
 public void nextMove(Move move)  
  {
   
    if(!move.isLastMove())
    {
     // player wird benachrichtigt das er am Zug ist // bei Humanplayer zB ev. Buttons  aktivieren ..oder so..
     players.get(counter).duBistDran(); 
     counter++
     if(counter>players.size-1)counter=0; //erster Spieler wieder am Zug
    }
    else
    {
       //wenn Spielende irgendwas tun, Spieler benachrichtigen usw
    }
  }

}

Game und Steuerung sind als Listener registriert.
Game wird bei jeden Zug benachrichtigt.
Steuerung hält die Spieler als Member in einer Liste und informiert sie wenn sie am Zug sind.
Wird ein Zug getätigt, so wird die Game-Klasse und die Steuerungsklasse informiert wobei
dadurch zugleich der nächste Spieler aktiviert wird.


Ist wirklich nur die Grundidee und schnell mal skizziert...
 

Marco13

Top Contributor
Ich finde die Sache mit dem MoveListener ... hm :? also, das wirkt so, als würden die Player unkoordiniert moves in die Welt schleudern, und das Spiel würde beiden Zuhören, und versuchen, was sinnvolles draus zu machen. Ich finde, der ablauf ist klar: Der Spielablauf gibt vor, dass ein Spieler einen Zug abliefern muss. Und das macht man dann: Das Spiel sagt dem Spieler: "GIB MIR DEINEN ZUG! (ich wart's so lang auf dich)". Hm.
 

xysawq

Bekanntes Mitglied
Greifen wir uns das doch mal aus dem richtigen Leben...

Marco und ich spielen Mühle...

Nach 3 Minuten schnellen Spielens habe ich eine schwerwiegende Entscheidung zu treffen und überlege... das ist das erste Mal, dass Marco wirklich warten muss.

Natürlich mag er nicht warten und macht seinen nächsten Zug ohne mir Zeit für meinen zu geben... das Spiel ist hin, keiner gewinnt, Error, imaginäre Bluescreen, Explosion, Weltuntergang... so siehts doch aus.

Was macht das Spiel für einen Sinn, wenn nicht gewartet wird???
 

parabool

Bekanntes Mitglied
Das Spiel sagt dem Spieler: "GIB MIR DEINEN ZUG! (ich wart's so lang auf dich)

Find ich nicht gut.
Das Spiel(brett) ist nur für die Darstellung der Züge und Validierung der Züge zuständig (siehe Eingansposting).


als würden die Player unkoordiniert moves in die Welt schleudern

quatsch... die Koordinierung erfolgt ja über die Steuerung.

ev. könnte die Benachrichtigung des Spiels über die Steuerung gehen.

es ist ein anderer Ansatz der nicht unbedingt besser oder schlechter ist...
und er wollte eben ohnr Threads...



[...]Was macht das Spiel für einen Sinn, wenn nicht gewartet wird???
schaut ihr eigentlich richtig hin?
Die Steuerung benachrichtigt den Spieler das er am Zug ist.
wenn nicht ist z.B die "Zugfunktion" nicht aktiviert.
 

Marco13

Top Contributor
"Ohne Threads" hast du jetzt schon zweimal erwähnt. Einer läuft mindestens, aber spätestens bei einem GUI läuft auch noch der Event-Dispatch-Thread, da kommt man nicht drumrum - und zwischen dem main Thread und dem EDT muss man irgendwie synchronisieren.

Trotzdem könntest du - wenn du so einen Vorschlag mit listenern machst - (mir) mal genauer beschreiben, wie der Ablauf dann sein sollte - also WAS genau die Methoden machen sollen.

Code:
class SomePlayer
{
    void duBistDran()
    {
        // >>>>>>>>>>>> was soll hier passieren? <<<<<<<<<<<<<<<
        
        // (Hint: Wenn diese Methode nicht blockiert, hat man ein Problem...)
    }

    void actionPerformedOderSo()
    {
        ...
        for (listener...) listener.nextMove(move); // Wird im EDT aufgerufen
        ...
    }

}


class Game
{
    public void nextMove(Move move)  
    {
        ...
        players.get(counter).duBistDran(); 
        ...
    }
}

:!: :?: :!:

Man könnte da irgendwas mit irgendwelchen flags rum-murksen, aber wie das deiner Meinung nach aussehen würde, würde mich jetzt schon interessieren.

FALLS(!) ich das richtig verstanden habe, wäre das ja sowas wie
game.sagEinemSpielerBescheidDassErMirBescheidSagenDarfDassErEinenZugGemachtHat();
und dieses gegenseitige "bescheid sagen" müßte man irgendwie in eine vernünftige Reihenfolge bringen - da wäre sowas wie
game.holeDirZugVonSpieler();
irgendwie einfacher...
Aber vielleicht habe ich das auch falsch interpretiert.

BTW: ... ob ein ZUG tatsächlich die Kompetenz haben sollte, zu entscheiden, ob er der "istLastMove" (d.h. ob das Spiel zuende ist) ist, ist IMHO aber SEHR fraglich....
 

parabool

Bekanntes Mitglied
:gaen:

Ja natürlich läuft das mindestens 1 Thread.
Die eigentliche Spielsteuerung wollte er jedoch ohne Threads machen oder ?

Aber vielleicht habe ich das auch falsch interpretiert.
hast Du. bzw. da gibt es nichts falsch zu interpretieren.

Code:
players.get(counter).duBistDran();
wird in Steuerung aufgerufen in der implementierung der Methode nextMove() des
MoveListener-Interfaces

Game wird NUR über die Züge benachrichtigt.

Code:
game.sagEinemSpielerBescheidDassErMirBescheidSagenDarfDassErEinenZugGemachtHat();
kommt also überhaupt nicht vor

uob ein ZUG tatsächlich die Kompetenz haben sollte, zu entscheiden, ob er der "istLastMove" (d.h. ob das Spiel zuende ist) ist, ist IMHO aber SEHR fraglich....
stimmt


Trotzdem könntest du - wenn du so einen Vorschlag mit listenern machst - (mir) mal genauer beschreiben, wie der Ablauf dann sein sollte - also WAS genau die Methoden machen sollen

naja ist doch alles irgendwie klar. Aber am WE finde ich vllt etwas Zeit aber jetzt...
 

xysawq

Bekanntes Mitglied
Also ich finde, man kann ein Spiel mit mehreren Spielern nur auf 2 Arten lösen:

1. ohne Threads... linearer Ablauf bei dem gerechnet wird bis der HumanPlayer einen Zug machen muss (zu diesem Zeitpunkt wartet das Programm auf den Spieler, bis der seine Entscheidung getroffen hat).

2. mit Threads... dort läuft das Spiel an sich ununterbrochen und es wird immer nur einem Spieler die Möglichkeit gegeben etwas zu tun... macht aber IMHO nur Sinn, wenn es entscheident ist, dass während der Spieler überlegt etwas passieren muss (z.B. ein Countdown der zeigt, wieviel Zeit der Spieler noch für seinen Zug hat bevor er verliert, oder eine witzige Spielbrett-Animation)... ansonsten ist das sehr sinnfrei.


Warum sollte das Programm, wenn keine Threads erlaubt sind, nicht auch warten?
 

Ishildur

Bekanntes Mitglied
Guten Abend allerseits
Als erstes möchte ich sagen, dass ich sehr überrascht und auch begeistert bin von den vielen Post und die grosse Mühe, die ihr euch gebt, um mir zu helfen.

Ich habe mir nun sämtliche Post einmal aufmerksam durchgelesen und muss einige Punkte richtigstellen beziehungsweise bekräftigen:

1. Wie man das Problem mit mehreren Threads lösen kann, ist mir völlig klar! Allerdings muss die Applikation zu einem späteren Zeitpunkt auf eine Plattform portiert werden, die KEIN Multithreading unterstützt!

2. Das eigentliche PROBLEM besteht darin, dass die "nextMove" Methode des Humanplayers nicht blockiert!

Code:
public abstract class Player{
 public Move nextMove(Game gam);
}

public class AI extends Player{
 public Move nextMove(Game gam){
  // Spielbaum mit Minimax Algorithmus und Alpha-Beta Pruning sowie dynamischer Suchtiefen optierung
  return new Move(6,5); // oder so, der springende Punkt ist, diese Methode blockiert, bis der entsprechende Move berechnet ist
 }
}

public class Human extends Player implements MouseListener,MouseMotionListener{
 public Move nextMove(Game gam){
  // was zum Teufel soll ich hier machen??? KEINE THREADS!!!!!!
 }

 public void mouseReleased(){
  // weil der Move wird ja in dieser Methode berechnet
  if(this.gam.isMoveValid(4,5)) this.mov = new Move(4,5); 
 }
}

public void GameLoop(){
 while(game.getWinner() == Game.PLAYER_NONE){
  game.setMove(p1.nextMove());
  game.setMove(p2.nextMove());
 }
}

Die Variante mit den Listeners habe ich mir natürlich ebenfalls durch den Kopf gehen lassen, aber hier gibt es meiner Meinung nach einen Stackoverflow infolge von Zirkulären Methodenaufrufen:

Code:
interface MoveListener{
 public void moveExecuted();
}

class Game{
 public MoveListener lstMov; 

 public void setMove(byte src,byte dst){
  // validiere und führe den gewünschten Spielzug aus  

 this.lstMov.moveExecuted(); // informiere wen auch immer darüber, dass ein Zug getan wurde
}

public abstract class Player{
 public void nextMove(Game gam);
}

public class AI extends Player{
 public Move nextMove(Game gam){
  // Spielbaum mit Minimax Algorithmus und Alpha-Beta Pruning sowie dynamischer Suchtiefen optierung
  this.gam.setMove(4,5); // der Move wird direkt auf der Game klasse ausgeführt ausgeführt
 }
}

public class Human extends Player implements MouseListener,MouseMotionListener{
 public Move nextMove(Game gam){
  // OK, hier aktiviere ich einfach die GUI: JComponent.setEntabled(true);
 }

 public void mouseReleased(){
  // weil der Move wird ja in dieser Methode berechnet
  if(this.gam.isMoveValid(4,5)) this.gam.setMove();
 }
}

public class GameLogic implement MoveListener{
 public void moveExecuted(){
  this.pa.nextMove();
  this.pa = this.pa == this.p1 ? this.p2 : this.p1;
 }
}
Wie gesagt, dies führt aber über kurz oder lang zu einem Stackoverflow, ist also auch keine Lösung!

Ich hoffe, ihr seht das Problem, die Probleme! :?

Mfg Ishildur
 

SebiB90

Top Contributor
also hab jetzt nicht alle Beiträge durchgelesen, nur überflogen.
Zu der letzten Variante hab ich eine Frage:
Wo wird GameLoop() aufgerufen? Wenn es im EDT aufgerufen wird, kannst du es nicht mit blockieren lösen, weil sonst die GUI einfriert. Beim blockieren brauchst du ein weiteren Thread neben dem EDT. Ich hab es bei meinem Spiel so gelöst, dass das Warten auf die User Eingabe in einem extra Thread läuft mit einer blockierung mithilfe des Concurrency package.

Was mir noch einfällt:
Du kannst einfach die GUI immer verfügbar machen für den Spieler und bei jedem Klick erst überprüfen, ob der Spieler dran ist und nur dann was machen. Wenn der Gegner ein menschlicher Spieler ist, dann einfach umstellen das nächster Klick für den anderen Spieler ist. Wenn der Gegner der Computer ist, dann nach dem Klick die Computer-Logik aufrufen.

Edit:
Wie gesagt, dies führt aber über kurz oder lang zu einem Stackoverflow, ist also auch keine Lösung!
Das doch aber nur wenn beide Spieler Computer sind.
Sonst seh ich da keinen Stackoverflow.

Edit2:
jetzt seh ich den Stackoverflow.
Du musst den Spieler erst ändern und dann nextMove() Aufrufen.
Weil wenn bei dir der Computer einmal dran ist, er immer dran ist.
Code:
public void moveExecuted(){ 
  this.pa = this.pa == this.p1 ? this.p2 : this.p1; 
  this.pa.nextMove();  
}
so muss das sein ;)
 

SebiB90

Top Contributor
Code:
public void moveExecuted(){  
  SwingUtilities.invokeLater(new Runnable() {
  public void run() {
   this.pa = this.pa == this.p1 ? this.p2 : this.p1; 
   this.pa.nextMove(); 
  }
 });
}
so...ich hoffe da is kein syntax fehler drinne, aber so sollte es möglich sein ohne stackoverflow.
 

SebiB90

Top Contributor
bevor du meckerst, ließ die API.
Das Game wird sicha über die GUI gestartet, also im EventDispatcherThread(EDT).
Die Methode verlagert die ausführung nur an Ende des EDT..also das die bischen später ausgeführt ist, sobald alle Events abgearbeitet sind. Es wird also KEIN Thread erzeugt, sondern die Methode in einem BEREITS EXISTIERENDEN Thread ausgeführt.
 

Ishildur

Bekanntes Mitglied
@SebiB90
"Meckern" ist ein bisschen ein hartes Wort! :)
Ich bin dir doch dankbar, dass du versuchst mir zu helfen. Also ich lasse nun mal die Katze aus dem Sack. Ich muss dasselbe Spiel später zu lernzwecken noch in 16-Bit Assembler schreiben und ich mache mir halt jetzt schon Gedanken über eine Architektur, die ich dann auch in Assembler umsetzen kann. Und glaube mir, da gibts kein InvokeLater und ähnliche Dinge :? Da werde ich einen Main-Loop haben und fertig.
 

SebiB90

Top Contributor
naja...ich kann kein assembler und kenn mich daher damit nicht aus.
aber du kannst schlecht java mit einer maschienensprache vergleichen, denke ich.
da wirds wohl sprachen spezifische lösungen geben.
 

SebiB90

Top Contributor
wie willste es denn da machen?
auch mit ner gui? weil hab da ka man sowas in Assembler macht.
kenn da nur befehle wie "mov al, 61h" oder so.
daher wo werden da die Events von der GUI bearbeitet...da muss es doch sowas ähnliches geben wie den EDT oder so ;)
 

diggaa1984

Top Contributor
ich glaube schon das man n grossen unterschied in der architektur zwischen einer OOP-sprache machen kann und Assembler .. einfach mal schon von der abstraktion her. warum sollte man sich in Java mit etwas quälen wofür es gar nicht gedacht ist. Die denkweise OOP zu programmieren is denk ich mal nicht mit Assembler vereinbar :D

Ich hab auch ma minimalst was in Assembler programmiert, das war mir zu abstrakt um dort ein derartiges komplexes konzept aufbauen zu können. In OOP fällt einem das mit sicherheit viel leichter
 

BjörnBu

Aktives Mitglied
Sorry ich bin zu faul so viel Arbeti zu investieren wie die andern.

hier aber ein vorschlag:
schluss mit GUI.

So weit ch das mitbekommen habe ist es eh keine Verteile Applikation sondern läuft auf einem Rechner. Also Kommandozeile, das Spiel kennt zwei player (eventell ein Spielfeld und eventuell Methoden um zu überprüfen ob Züge valide sind, obs es einen gewinner gibt und was weiß ich nich alles. lass am besten erstmal alles weg)

Ein Spieler kann Human oder Computer Spieler sein. Das Spiel macht nichts anderes als awechselnd p1.makeMove() und p2.makeMove(). Dazwischen ggf überprüfen ausgaben usw.
Computer laufen direkt durch, auf menschen wartet meinen wegen einfach ein BufferedReader br.readln() oder was auch immer.

Danach kannst du das Ganze in einem iterativen Prozess erweitern. Sobald du GUIs machst, brauchst du zwangsläufig Threads. Ich kenne mich mit modernem Assembler leider auch nicht aus (hab nur mal in ner vorlesung was mit 8086 machen müssen), aber da MUSS es sowas zwangsläufig auch geben. Und auf den alten Prozessoren gäbe es auch niemals Swing GUIs.
 

Marco13

Top Contributor
Hmgl - wenn du ein GUI hast, hast du Threads, und dann must du synchronisieren, weil sonst die getMove-Methode des HumanPlayers nicht blockiert.
Wenn du in Assembler programmierst, wirst du sicher kein GUI haben, und dann brauchst du auch keine synchronisation, weil DANN die getMove-Methode des HumanPlayers blockieren wird. Da wirst du kaum was dagegen machen können.
 

Ishildur

Bekanntes Mitglied
Ja lasst uns nicht darüber streiten, was man in Assembler machen kann und was nicht, kommen wir zurück zum Kernproblem! :lol:

Also ich kann nun möglicherweise das Problem noch ein wenig anders definieren: Es ist klar, dass auf den HumanPlayer gewartet werden muss, die Frage ist jedoch, wie!

Möglichkeit 1: Eine Funktion mit einer Schleife überprüft in regelmässigen Abständen, ob denn nun der Move getan wurde und kehrt schliesslich zum Hauptprogramm zurück. Problem: Diese Variante benötigt Multithreading, weil ansonsten die komplette GUI einfriert!

Möglichkeit 2: Irgendwas mit Notifikationen: Bsp. Spieler 1 ruft Spieler 2 auf, nachdem er den Zug gemacht hat. Spieler 2 ruft schliesslich wieder Spieler 1 auf. Das Problem hierbei sind die zirkulären Methodenaufrufe, welche mit Sicherheit in einem Stackoverflow enden.

Möglichkeit 3: Ich habe noch an ein Master/Slave System gedacht, aber dies funktioniert nicht mehr, sobald man 2 HumanPlayers hat.

Es ist doch zum wahnsinnig werden! :?

Nehmen wir mal an, man würde dieses Spiel in einem C++ Programm ohne Multithreading programmieren, dass muss doch verdammt noch mal möglich sein:

Eingabeverarbeitung -> Spiellogik -> Rendering -> Eingabeverarbeitung

Wie würde man es da machen?
 

SebiB90

Top Contributor
Also ich würde dir raten dich damit an ein Assembler Forum zu wenden.
Die wenigstens werden hier wissen, wie Assembler richtig funktioniert und was seine besonderheiten sind, die beachtet werden müssen.

Wenn du eine GUI in Java nutzt wirkt es zwingend ein Multithreadprogramm (der Thread indem main() aufgerufen wird + EDT). Also nimms so hin, wenn du java nutzen willst. Du kannst es eben nicht 1:1 kopieren in eine andere Programmiersprache.
 

Marco13

Top Contributor
Irgendwie wird mir das jetzt zu albern - man würde auch nicht in einem Forum über Webdesign fragen, wie man seine Homepage gestalten könnte, und dann alle Verschläge, die mit HTML zusammenhängen, abschmettern, weil man die Homepage ja auch später noch als Ölgemälde erstellen will :? Ich bin dann mal weg.
 

BjörnBu

Aktives Mitglied
Ishildur hat gesagt.:
Also ich kann nun möglicherweise das Problem noch ein wenig anders definieren: Es ist klar, dass auf den HumanPlayer gewartet werden muss, die Frage ist jedoch, wie!

Meiner Meinung nach liegt genau hier das Problem. Explizit warten musst du überhaupt nur bei multi Threading. An sonsten nutzt du einfach 'ne Eingabe, die blockiert. Wie das lesen aus der Kommandozeile z.B., oder das warten auf 'ne Nachrichit über 'nen Socket, oder oder oder.
 

SebiB90

Top Contributor
Ishildur hat gesagt.:
Hehe und genau hier liegt der Hund begraben: Eine Eingabe über die Gui blockiert nun mal nicht!
Doch, teilweise schon. Ein modaler Dialog wie z.b. auch JOptionPane blockiert bis das Fenster wieder geschlossen ist.

Irgendwie wird mir das jetzt zu albern - man würde auch nicht in einem Forum über Webdesign fragen, wie man seine Homepage gestalten könnte, und dann alle Verschläge, die mit HTML zusammenhängen, abschmettern, weil man die Homepage ja auch später noch als Ölgemälde erstellen will Ich bin dann mal weg.
Jo, ich glaub ich schließ mich dir an.
 

parabool

Bekanntes Mitglied
ok, jetzt bei genaueren hinsehen: bei meiner Idee tritt Rekursion auf.
Hätte es eigentlich sehen müssen. ???:L
 

xysawq

Bekanntes Mitglied
Will auch noch mal meinen Senf dazu geben und sagen, dass der liebe Herr Ishildur mit seinem ständigen blockiert nicht und keine Threads mehr als verwirrt hat.

Gibt es keine Threads dann wird automatisch blockiert. Gibt es Threads braucht man ein spezielles vorgehen zum Blockieren wie eine while(boolean)-Schleife die erst verlassen wird, wenn der Zug getan und der boolean auf false gelegt wurde, jedoch soll es ja keine Threads geben.

Im Assembler habe ich schon viel Programmiert (deswegen tue ich mich gelegentlich in Java schwer, weil man in Assembler sein Ziel meist nur über Umwege erreicht und Java wesentlich komplexer ist), und ich muss zugeben, eine GUI in Assembler ist sauschwer... da gibts maximal Textausgabe.

Wenn du dein GUI-Java-Programm in Assembler haben willst, kompilier es in Assembler!


Aber führe hier nicht alle an der Nase herum nur weil du nicht wahr haben willst, dass es eine GUI mit HumanPlayer nur in Verbindung mit Threads gibt.
 
Status
Nicht offen für weitere Antworten.
Ähnliche Java Themen
  Titel Forum Antworten Datum
J Frage zum Quellcode - Zusammhänge und Ablauf. Java Basics - Anfänger-Themen 2
D Erste Schritte Frage eines absoluten Anfängers Java Basics - Anfänger-Themen 3
Zrebna Frage zu Test-Driven Development (TDD) Java Basics - Anfänger-Themen 3
I Frage Thymeleaf -> Fehler ignorieren und mit "" ersetzen? Java Basics - Anfänger-Themen 15
I Frage Thymeleaf -> Prefix / Suffix ändern? Java Basics - Anfänger-Themen 11
D Rekursions Probleme / frage Java Basics - Anfänger-Themen 4
T Frage zu Parse Java Basics - Anfänger-Themen 2
H Frage an die Profis Java Basics - Anfänger-Themen 4
J Eine konzeptionelle Frage zu OOP Java Basics - Anfänger-Themen 3
P Frage zu Rekursion und Backtracking Java Basics - Anfänger-Themen 2
H Frage zur Ausgabe Java Basics - Anfänger-Themen 4
H Frage zu arithmetischen Operationen Java Basics - Anfänger-Themen 20
F Kurze Frage zu replace() Java Basics - Anfänger-Themen 19
JavaSchmecktLecker Polymorphie Frage zur Methodenüberschreibung Java Basics - Anfänger-Themen 21
J Frage zu einem "Taschenrechner" code Java Basics - Anfänger-Themen 9
B Erste Schritte Frage zu Instanzierung und Referenzen Java Basics - Anfänger-Themen 8
DoubleM Runtime.getRuntime().exec Frage Java Basics - Anfänger-Themen 2
J Eine theoretische Frage zur Praxis - JPanel oder Canvas Java Basics - Anfänger-Themen 5
O Frage: Formaler Typbezeichner? Java Basics - Anfänger-Themen 3
I BlueJ Queue Frage für Klausur Java Basics - Anfänger-Themen 2
N Verständnis Frage zu Variablen Java Basics - Anfänger-Themen 3
N Spezielle frage zum Comparator Java Basics - Anfänger-Themen 6
L Frage zum Array Java Basics - Anfänger-Themen 1
A Frage zum UML Design Java Basics - Anfänger-Themen 1
I Hilfe bei Klausur Frage Java Basics - Anfänger-Themen 8
izoards Drucken Frage zu FAQ Beitrag Java Basics - Anfänger-Themen 2
J Frage zu meinem Code (OOP) Java Basics - Anfänger-Themen 4
sserio Split() -> Regex Frage. Java Basics - Anfänger-Themen 7
A OCA Study Guide: 2. Frage aus Kapitel 3 Java Basics - Anfänger-Themen 9
sserio Date Library Frage Java Basics - Anfänger-Themen 9
Max246Sch Frage zu Währungsrechner Code Java Basics - Anfänger-Themen 2
sserio Frage zu HashMaps Java Basics - Anfänger-Themen 20
sserio Frage zu Threading - Multithreading Java Basics - Anfänger-Themen 2
sserio Frage zu Lambda Ausdrücken Java Basics - Anfänger-Themen 7
sserio Frage zu BigInteger Java Basics - Anfänger-Themen 1
D Frage bzgl. Enum-Handhabung Java Basics - Anfänger-Themen 16
xxx12 Frage Java Basics - Anfänger-Themen 2
I Generelle Frage zu Mikroservices (Spring Boot?), Docker... Java Basics - Anfänger-Themen 7
R Frage zu Methoden (Rückgabewert u. ohne.) Java Basics - Anfänger-Themen 2
A Frage zur programmierung Java Basics - Anfänger-Themen 12
M Frage zur Methode split der Klasse String Java Basics - Anfänger-Themen 32
R Input/Output Frage zu Java IO Java Basics - Anfänger-Themen 6
M Frage zu printWriter Java Basics - Anfänger-Themen 5
C Frage zu OLSMultipleLinearRegression Java Basics - Anfänger-Themen 31
KogoroMori21 Frage zum Euklidischen Algorithmus Java Basics - Anfänger-Themen 11
S Verständnis-Frage zu einer HÜ? Java Basics - Anfänger-Themen 1
F Frage betreff Programm mit dem man C++-Code in JAVA-Code übersetzen lassen kann Java Basics - Anfänger-Themen 2
L Frage zur Ticket Maschine Java Basics - Anfänger-Themen 1
J Frage zu OOP-Klassendiagramm Java Basics - Anfänger-Themen 8
OSchriever Frage zu Compiler Java Basics - Anfänger-Themen 8
H Frage zu Throw Exception Java Basics - Anfänger-Themen 2
TimoN11 Frage zu Java-Vererbung (Cast) Java Basics - Anfänger-Themen 5
Bademeister007 Hallo Leute ich hab eine Frage zur ArrayList Java Basics - Anfänger-Themen 8
F Frage betreff Programmierbücher zu Lagerverwaltung als Konsolenprogramm Java Basics - Anfänger-Themen 3
dieter000 Kurze Frage kann mir ejmand kurz diesen Code erklären, bzw wie man die zeilen erklärt und so Java Basics - Anfänger-Themen 1
I String.split regex Frage Java Basics - Anfänger-Themen 2
N Best Practice Frage zum MVC-Pattern Java Basics - Anfänger-Themen 2
dieter000 Frage zu einem Beispiel... Java Basics - Anfänger-Themen 5
J Frage zum Loggen Java Basics - Anfänger-Themen 18
J Methoden Frage: Array-Werte in anderer Methode ändern Java Basics - Anfänger-Themen 4
Zrebna Frage zum "Referenzen-konzept" in Java Java Basics - Anfänger-Themen 8
JD_1998 Array-Position aus einer Methode in einer anderen ausgeben (Kurze Frage) Java Basics - Anfänger-Themen 2
marcooooo Frage zu bestimmten Beispiel Java Basics - Anfänger-Themen 31
NeoLexx equals()-Methode Verständnis Frage anhand Code Beispiel Java Basics - Anfänger-Themen 22
N Input/Output Eine Frage über system.out.println. Java Basics - Anfänger-Themen 10
B Erste Schritte Learning Coding (!) Frage an erfahrene Programmierer. Java Basics - Anfänger-Themen 23
M konzeptuelle Frage: In welcher Klasse definiert man am Besten Methoden, die die Kommunikation mit dem User regeln? Java Basics - Anfänger-Themen 8
B Frage zum Code verständnis im Resultat Java Basics - Anfänger-Themen 10
C Exception-Frage Java Basics - Anfänger-Themen 3
J Eine Frage zur Schreibweise == ? : Java Basics - Anfänger-Themen 3
S Frage des Designs Java Basics - Anfänger-Themen 1
JavaTalksToMe Extends/Implements Frage Java Basics - Anfänger-Themen 3
pkm Frage zu Servletfunktion Java Basics - Anfänger-Themen 0
B Frage zur Währungsumrechnung Java Basics - Anfänger-Themen 3
S Allgemeine Frage über Generics und Vererbungen Java Basics - Anfänger-Themen 5
Kirby.exe Frage zur Verwendung von Interfaces Java Basics - Anfänger-Themen 6
D Frage zu Strings einer Exception Java Basics - Anfänger-Themen 4
L Wie frage ich ab, ob in einem Array, Werte doppelt vorkommen? Java Basics - Anfänger-Themen 4
D Frage zur IDE IntelliJ IDEA Java Basics - Anfänger-Themen 6
H Frage zum 2d Array Java Basics - Anfänger-Themen 1
N Frage zum Newton-Fraktal Java Basics - Anfänger-Themen 1
H Frage zu interfaces Java Basics - Anfänger-Themen 1
J Frage dazu Variablen klassenübergreifend zu verändern Java Basics - Anfänger-Themen 22
I Frage zu SkipList Java Basics - Anfänger-Themen 4
G Frage zu JScrollPane Java Basics - Anfänger-Themen 12
Kirby.exe Allgemeine Frage Java Basics - Anfänger-Themen 3
W Frage zu anonymen Klassen Java Basics - Anfänger-Themen 4
J Kleine Frage zu OOP Java Basics - Anfänger-Themen 371
S Frage Klasse und Objekte Java Basics - Anfänger-Themen 2
F Frage zu Iteratoren Java Basics - Anfänger-Themen 2
C Erste Schritte Frage zur ArrayList Java Basics - Anfänger-Themen 15
J Frage zur Vererbung Java Basics - Anfänger-Themen 1
H Frage zur ermittlung eines doppelte Paars aus Sotieralgorithmus Java Basics - Anfänger-Themen 4
H Frage zum Array Java Basics - Anfänger-Themen 17
G Schach -Frage 2- Maussteuerung Java Basics - Anfänger-Themen 7
G Schach in Java - Allgemeine Frage zur Architektur Java Basics - Anfänger-Themen 7
B Fachliche Frage bei Rechnungen Java Basics - Anfänger-Themen 16
B Frage zu: String... strings -> Ungleiche Anzahl an Parameter? Java Basics - Anfänger-Themen 4
B Frage zu Datenbank Design - Rechnungen, Angebote... und deren Positionen Java Basics - Anfänger-Themen 4
H Frage zu Parameter einer Methode Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben