Spiel controller (#22)

* spielcontroller

* refactoring

* added http server for frontend

* added javaFx
This commit is contained in:
Valentin Heiserer
2024-04-16 18:40:20 +02:00
committed by GitHub
parent d4deabfde9
commit fb7ae31a0d
62 changed files with 504 additions and 249 deletions

16
pom.xml
View File

@@ -6,7 +6,11 @@
<build>
<finalName>schafkopf-backend-build</finalName>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<artifactId>maven-checkstyle-plugin</artifactId>
@@ -147,6 +151,16 @@
<groupId>pn532</groupId>
<version>1.0.2</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-controls</artifactId>
<version>17</version>
</dependency>
<dependency>
<groupId>org.openjfx</groupId>
<artifactId>javafx-web</artifactId>
<version>17</version>
</dependency>
</dependencies>
<groupId>org.example</groupId>

View File

@@ -1,15 +1,22 @@
package org.schafkopf;
import com.google.gson.JsonObject;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpServer;
import io.github.cdimascio.dotenv.Dotenv;
import jakarta.servlet.DispatcherType;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.URI;
import java.net.URL;
import java.time.Duration;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import javafx.application.Application;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.FilterHolder;
@@ -24,13 +31,16 @@ import org.schafkopf.cardreader.UsbCardReader;
public class BackendServer {
private final Server server;
private final ServerConnector connector;
private final Schafkopf schafkopfGame;
private final CardReader nfcLeser;
private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>();
private CountDownLatch nfcLatch = new CountDownLatch(1);
private Boolean readingMode = false;
private String uidString = "";
/** Important variables. */
public final Schafkopf schafkopfGame;
private final CardReader nfcLeser;
private final List<FrontendEndpoint> frontendEndpoints = new ArrayList<>();
/** Creates an Instance of the Backend Server. */
public BackendServer() {
Dotenv dotenv = Dotenv.configure().directory("./").load();
@@ -42,7 +52,7 @@ public class BackendServer {
server.addConnector(connector);
schafkopfGame = new Schafkopf(this);
// nfcLeser = new RaspberryKartenLeser(this);
String osName = System.getProperty("os.name").toLowerCase();
if (osName.contains("win")) {
// Windows
@@ -66,6 +76,16 @@ public class BackendServer {
// Configure CORS settings
configureCors(context);
URL webContentUrl = getClass().getClassLoader().getResource("web-content");
if (webContentUrl == null) {
throw new RuntimeException("Unable to find 'web-content' directory");
}
String webContentPath = webContentUrl.toExternalForm();
context.setResourceBase(webContentPath);
System.out.println("Web Content Path: " + webContentPath);
// Configure specific websocket behavior
JettyWebSocketServletContainerInitializer.configure(
context,
@@ -76,6 +96,70 @@ public class BackendServer {
// Add websockets
wsContainer.addMapping("/schafkopf-events/*", new FrontendEndpointCreator(this));
});
// Integrate simple HTTP server
startHttpServer();
new Thread(this::launchJavaFx).start();
}
private void launchJavaFx() {
Application.launch(JavaFxApp.class);
}
private void startHttpServer() {
try {
HttpServer httpServer = HttpServer.create(new InetSocketAddress(8081), 0);
httpServer.createContext("/", new MyHandler());
httpServer.setExecutor(null);
httpServer.start();
System.out.println("HTTP Server started on port 8081");
} catch (IOException e) {
e.printStackTrace();
}
}
static class MyHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
String path = t.getRequestURI().getPath();
if ("/".equals(path)) {
path = "/index.html"; // default to index.html
}
try {
InputStream fileStream =
getClass().getClassLoader().getResourceAsStream("web-content" + path);
if (fileStream != null) {
byte[] data = fileStream.readAllBytes();
// Set the appropriate MIME type for JavaScript files
String mimeType = getMimeType(path);
t.getResponseHeaders().set("Content-Type", mimeType);
t.sendResponseHeaders(200, data.length);
try (OutputStream os = t.getResponseBody()) {
os.write(data);
}
} else {
// File not found
t.sendResponseHeaders(404, -1);
}
} catch (IOException e) {
e.printStackTrace();
t.sendResponseHeaders(500, -1);
}
}
private String getMimeType(String path) {
if (path.endsWith(".js")) {
return "application/javascript";
} else if (path.endsWith(".html")) {
return "text/html";
} else if (path.endsWith(".css")) {
return "text/css";
}
// Add more MIME types as needed
return "application/octet-stream";
}
}
/** The main entrypoint of the Application. */
@@ -100,23 +184,15 @@ public class BackendServer {
context.addFilter(cors, "*", types);
}
public void setPort(int port) {
private void setPort(int port) {
connector.setPort(port);
}
public void start() throws Exception {
private void start() throws Exception {
server.start();
}
public URI getUri() {
return server.getURI();
}
public void stop() throws Exception {
server.stop();
}
public void join() throws InterruptedException {
private void join() throws InterruptedException {
server.join();
}
@@ -150,24 +226,14 @@ public class BackendServer {
}
}
public void startSchafkopfGame() {
schafkopfGame.startGame();
}
public void stopSchafkopfGame() {
schafkopfGame.stopGame();
}
public void showTrumpf() {
schafkopfGame.showTrumpf();
}
public void showFarbe() {
schafkopfGame.showFarbe();
}
public void setGame(String message) {
schafkopfGame.setGame(message);
/** method to call to wait for NFC input. */
public String waitForCardScan() throws InterruptedException {
this.readingMode = true;
nfcLatch.await();
Thread.sleep(20);
this.readingMode = false;
nfcLatch = new CountDownLatch(1);
return this.uidString;
}
/**
@@ -186,14 +252,4 @@ public class BackendServer {
this.uidString = uidString;
nfcLatch.countDown();
}
/** method to call to wait for NFC input. */
public String waitForCardScan() throws InterruptedException {
this.readingMode = true;
nfcLatch.await();
Thread.sleep(20);
this.readingMode = false;
nfcLatch = new CountDownLatch(1);
return this.uidString;
}
}

View File

@@ -30,23 +30,23 @@ public class FrontendEndpoint extends WebSocketAdapter {
System.out.println("Received TEXT message:" + message);
if (message.contains("startsimulation")) {
backendServer.startSchafkopfGame();
backendServer.schafkopfGame.startGame();
}
if (message.contains("stopsimulation")) {
backendServer.stopSchafkopfGame();
backendServer.schafkopfGame.stopGame();
}
if (message.contains("showtrumpf")) {
backendServer.showTrumpf();
backendServer.schafkopfGame.showTrumpf();
}
if (message.contains("showfarben")) {
backendServer.showFarbe();
backendServer.schafkopfGame.showFarbe();
}
if (message.contains("setgame")) {
backendServer.setGame(message);
backendServer.schafkopfGame.setGame(message);
}
}

View File

@@ -0,0 +1,80 @@
package org.schafkopf;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
/** GameState. */
public class GameState {
public GamePhase getGamePhase() {
return this.gamePhase;
}
/** GamePhase. */
public enum GamePhase {
CHOOSE_GAME("Spiel muss gewählt werden"),
GAME_START("Warten auf das Legen einer Karte"),
TRICK_START("Warten auf das Legen einer Karte"),
WAIT_FOR_CARD("Warten auf das Legen einer Karte"),
PLAYER_CARD("Warten auf das Legen einer Karte"),
PLAYER_TRICK("Spieler sticht"),
GAME_STOP("Spieler sticht");
// Add more phases as needed
private final String description;
GamePhase(String description) {
this.description = description;
}
public String getDescription() {
return description;
}
}
private GamePhase gamePhase;
private Integer currentPlayer; // Using Integer to allow for null
private Karte card;
private KartenFarbe color;
private boolean trumpf;
// Constructors, getters, and setters
public GameState(GamePhase phase) {
this.gamePhase = phase;
}
public GameState(GamePhase phase, Integer player) {
this.gamePhase = phase;
this.currentPlayer = player;
}
/** GameState. */
public GameState(GamePhase phase, Integer player, Karte card, KartenFarbe color, boolean trumpf) {
this.gamePhase = phase;
this.currentPlayer = player;
this.card = card;
this.color = color;
this.trumpf = trumpf;
}
/** GameState. */
public GameState(GamePhase phase, Integer player, Karte card) {
this.gamePhase = phase;
this.currentPlayer = player;
this.card = card;
}
/** GameState. */
public JsonObject getJson() {
Gson gson = new Gson();
JsonObject jsonObject = new JsonObject();
jsonObject.add("gamestate", gson.toJsonTree(this));
return jsonObject;
}
}

View File

@@ -0,0 +1,50 @@
package org.schafkopf;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.input.KeyCode;
import javafx.scene.web.WebView;
import javafx.stage.Stage;
/** Frontend Window. */
public class JavaFxApp extends Application {
private static final String FRONTEND_URL =
"http://localhost:8081"; // Replace with your frontend URL
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
// Create a WebView
WebView webView = new WebView();
// Load the frontend URL
webView.getEngine().load(FRONTEND_URL);
// Create a Scene with the WebView
Scene scene = new Scene(webView, 800, 600);
// Set up the Stage
primaryStage.setTitle("Schafkopfen");
primaryStage.setScene(scene);
primaryStage.setFullScreenExitHint("");
// Set the stage to fullscreen
primaryStage.setFullScreen(true);
// Add event handler for the Escape key to toggle fullscreen
scene.setOnKeyPressed(
event -> {
if (event.getCode() == KeyCode.F11) {
primaryStage.setFullScreen(!primaryStage.isFullScreen());
}
});
// Show the Stage
primaryStage.show();
}
}

View File

@@ -1,5 +1,6 @@
package org.schafkopf;
import org.schafkopf.GameState.GamePhase;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
@@ -26,13 +27,9 @@ public class Schafkopf {
new BotPlayer(), new LocalPlayer(this), new LocalPlayer(this), new LocalPlayer(this)
};
private boolean gameState = false;
private GameState gameState = new GameState(GamePhase.GAME_STOP);
private Thread spielThread;
public Player[] getPlayer() {
return player;
}
/**
* Constructor for the Schafkopf class.
*
@@ -43,6 +40,10 @@ public class Schafkopf {
System.out.println("SchaffKopfGame erstellt");
}
public Player[] getPlayer() {
return player;
}
/** Sends all Trumpf Karten of the current GameType to the Frontend. */
public void showTrumpf() {
server.sendMessageToAllFrontendEndpoints(spiel.getTrumpfKarten().getJson());
@@ -69,7 +70,6 @@ public class Schafkopf {
System.out.println("Ungültige Karte");
return wartetAufKarte();
}
server.sendMessageToAllFrontendEndpoints(karte.getJson());
System.out.println("Karte gescannt: " + karte.getName());
System.out.println("Beende Warten auf Karte");
return karte;
@@ -77,22 +77,24 @@ public class Schafkopf {
/** Set GameState to "started" and start Game Thread. */
public void startGame() {
if (gameState) {
if (gameState.getGamePhase() != GamePhase.GAME_STOP) {
System.out.println("Game already started!");
server.sendMessageToAllFrontendEndpoints("Game already started!");
} else {
gameState = true;
gameState = new GameState(GamePhase.GAME_START);
setAndSendGameState(gameState);
System.out.println("Start Game");
// KartenListe botHand = KartenUtil.zieheZufallsHand(8);
KartenListe botHand = new KartenListe();
botHand.addKarten(Karte.EICHEL_7);
botHand.addKarten(Karte.EICHEL_8);
botHand.addKarten(Karte.EICHEL_9);
botHand.addKarten(Karte.EICHEL_K);
botHand.addKarten(Karte.SCHELL_7);
botHand.addKarten(Karte.BLATT_7);
botHand.addKarten(Karte.EICHEL_X);
botHand.addKarten(Karte.EICHEL_A);
botHand.addKarten(Karte.HERZ_X);
botHand.addKarten(Karte.HERZ_7);
botHand.addKarten(Karte.EICHEL_U);
botHand.addKarten(Karte.EICHEL_O);
for (Player currentPlayer : player) {
@@ -102,13 +104,6 @@ public class Schafkopf {
}
}
server.sendMessageToAllFrontendEndpoints("Start Game");
server.sendMessageToAllFrontendEndpoints(botHand.getJson());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
spielThread = new Thread(() -> new Spielablauf(this, spiel));
spielThread.start();
@@ -117,13 +112,12 @@ public class Schafkopf {
/** Set GameState to "stopped" and interrupt Game Thread. */
public void stopGame() {
if (!gameState) {
if (gameState.getGamePhase() == GamePhase.GAME_STOP) {
System.out.println("no active Game!");
server.sendMessageToAllFrontendEndpoints("no active Game!");
} else {
gameState = false;
System.out.println("Stop Game");
server.sendMessageToAllFrontendEndpoints("Stop Game");
gameState = new GameState(GamePhase.GAME_STOP);
setAndSendGameState(gameState);
}
spielThread.interrupt();
@@ -188,7 +182,12 @@ public class Schafkopf {
}
}
public BackendServer getServer() {
return this.server;
public void setAndSendGameState(GameState gameState) {
this.gameState = gameState;
this.server.sendMessageToAllFrontendEndpoints(this.gameState.getJson());
}
public GameState getGameState() {
return this.gameState;
}
}

View File

@@ -1,5 +1,7 @@
package org.schafkopf;
import org.schafkopf.GameState.GamePhase;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.player.Player;
import org.schafkopf.spielcontroller.SpielController;
@@ -10,7 +12,7 @@ import org.slf4j.LoggerFactory;
public class Spielablauf {
private static final Logger logger = LoggerFactory.getLogger(Spielablauf.class);
private final KartenListe gespielteKarten;
private final KartenListe gespielteKarten = new KartenListe();
private final KartenListe tischKarten = new KartenListe();
@@ -20,56 +22,65 @@ public class Spielablauf {
private final Schafkopf schafkopf;
private int gemachteStiche;
Spielablauf(Schafkopf schafkopf, SpielController spiel) {
this.schafkopf = schafkopf;
this.spiel = spiel;
this.players = schafkopf.getPlayer();
gespielteKarten = new KartenListe();
gemachteStiche = 0;
try {
einStich();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
playRound();
}
/** Method to Handle flow of one Game. */
public void einStich() throws InterruptedException {
private void playRound() {
int startingPlayer = 0;
logger.info("Starte Stiche");
int rauskommer = 0;
while (gemachteStiche < 8) {
schafkopf.getServer().sendMessageToAllFrontendEndpoints(gespielteKarten.getJson());
logger.info("Stich: {}", gemachteStiche);
for (int i = 0; i < 4; i++) {
schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson());
int nextPlayer = (i + rauskommer) % 4;
logger.info("Spieler ist dran: {}", nextPlayer);
tischKarten.addKarten(players[nextPlayer].play(spiel, tischKarten));
schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson());
}
schafkopf.getServer().sendMessageToAllFrontendEndpoints(tischKarten.getJson());
int stichSpieler = SpielController.welcheKarteSticht(tischKarten);
Thread.sleep(2000);
logger.info("Stiche ende");
rauskommer = (rauskommer + stichSpieler) % 4;
logger.warn("Karte sticht: {}", rauskommer);
//rauskommer = 0;
gespielteKarten.addKarten(tischKarten);
tischKarten.clear();
gemachteStiche++;
for (int i = 0; i < 8; i++) {
logger.info("Stich: {}", i);
startingPlayer = playTrick(startingPlayer);
}
schafkopf.getServer().sendMessageToAllFrontendEndpoints(gespielteKarten.getJson());
schafkopf.stopGame();
}
private int playTrick(int startingPlayer) {
schafkopf.setAndSendGameState(new GameState(GamePhase.TRICK_START));
for (int i = 0; i < 4; i++) {
int currentPlayer = (i + startingPlayer) % 4;
logger.info("Spieler ist dran: {}", currentPlayer);
schafkopf.setAndSendGameState(new GameState(GamePhase.WAIT_FOR_CARD, currentPlayer));
Karte playedCard = players[currentPlayer].play(spiel, tischKarten, gespielteKarten);
tischKarten.addKarten(playedCard);
schafkopf.setAndSendGameState(
new GameState(
GamePhase.PLAYER_CARD,
currentPlayer,
playedCard,
tischKarten.getByIndex(0).getFarbe(),
spiel.isTrumpf(tischKarten.getByIndex(0))));
}
int stichSpieler = SpielController.welcheKarteSticht(tischKarten);
logger.info("Stiche ende");
int winningPlayerIndex = (startingPlayer + stichSpieler) % 4;
logger.warn("Karte sticht: {}", winningPlayerIndex);
schafkopf.setAndSendGameState(
new GameState(
GamePhase.PLAYER_TRICK, winningPlayerIndex, tischKarten.getByIndex(stichSpieler)));
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
logger.error("error sleep");
}
gespielteKarten.addKarten(tischKarten);
tischKarten.clear();
return winningPlayerIndex;
}
}

View File

@@ -30,7 +30,7 @@ public class UsbCardReader extends CardReader {
SerialPort selectedPort = null;
for (SerialPort port : ports) {
if (port.getSystemPortName().equals("COM16")) {
if (port.getSystemPortName().equals("COM13")) {
selectedPort = port;
break;
}

View File

@@ -5,38 +5,40 @@ import com.google.gson.JsonObject;
/** enum to represent all cards in the game. */
public enum Karte {
EICHEL_7(KartenFarbe.EICHEL, KartenSymbol.SEVEN),
EICHEL_8(KartenFarbe.EICHEL, KartenSymbol.EIGHT),
EICHEL_9(KartenFarbe.EICHEL, KartenSymbol.NINE),
EICHEL_X(KartenFarbe.EICHEL, KartenSymbol.TEN),
EICHEL_K(KartenFarbe.EICHEL, KartenSymbol.KOENIG),
EICHEL_A(KartenFarbe.EICHEL, KartenSymbol.ASS),
EICHEL_U(KartenFarbe.EICHEL, KartenSymbol.UNTER),
EICHEL_O(KartenFarbe.EICHEL, KartenSymbol.OBER),
BLATT_7(KartenFarbe.BLATT, KartenSymbol.SEVEN),
BLATT_8(KartenFarbe.BLATT, KartenSymbol.EIGHT),
BLATT_9(KartenFarbe.BLATT, KartenSymbol.NINE),
BLATT_X(KartenFarbe.BLATT, KartenSymbol.TEN),
BLATT_K(KartenFarbe.BLATT, KartenSymbol.KOENIG),
BLATT_A(KartenFarbe.BLATT, KartenSymbol.ASS),
BLATT_U(KartenFarbe.BLATT, KartenSymbol.UNTER),
BLATT_O(KartenFarbe.BLATT, KartenSymbol.OBER),
SCHELL_7(KartenFarbe.SCHELL, KartenSymbol.SEVEN),
SCHELL_8(KartenFarbe.SCHELL, KartenSymbol.EIGHT),
SCHELL_9(KartenFarbe.SCHELL, KartenSymbol.NINE),
SCHELL_X(KartenFarbe.SCHELL, KartenSymbol.TEN),
SCHELL_K(KartenFarbe.SCHELL, KartenSymbol.KOENIG),
SCHELL_A(KartenFarbe.SCHELL, KartenSymbol.ASS),
SCHELL_U(KartenFarbe.SCHELL, KartenSymbol.UNTER),
SCHELL_O(KartenFarbe.SCHELL, KartenSymbol.OBER),
SCHELL_K(KartenFarbe.SCHELL, KartenSymbol.KOENIG),
SCHELL_X(KartenFarbe.SCHELL, KartenSymbol.TEN),
SCHELL_A(KartenFarbe.SCHELL, KartenSymbol.ASS),
HERZ_7(KartenFarbe.HERZ, KartenSymbol.SEVEN),
HERZ_8(KartenFarbe.HERZ, KartenSymbol.EIGHT),
HERZ_9(KartenFarbe.HERZ, KartenSymbol.NINE),
HERZ_X(KartenFarbe.HERZ, KartenSymbol.TEN),
HERZ_K(KartenFarbe.HERZ, KartenSymbol.KOENIG),
HERZ_A(KartenFarbe.HERZ, KartenSymbol.ASS),
HERZ_U(KartenFarbe.HERZ, KartenSymbol.UNTER),
HERZ_O(KartenFarbe.HERZ, KartenSymbol.OBER);
HERZ_O(KartenFarbe.HERZ, KartenSymbol.OBER),
HERZ_K(KartenFarbe.HERZ, KartenSymbol.KOENIG),
HERZ_X(KartenFarbe.HERZ, KartenSymbol.TEN),
HERZ_A(KartenFarbe.HERZ, KartenSymbol.ASS),
BLATT_7(KartenFarbe.BLATT, KartenSymbol.SEVEN),
BLATT_8(KartenFarbe.BLATT, KartenSymbol.EIGHT),
BLATT_9(KartenFarbe.BLATT, KartenSymbol.NINE),
BLATT_U(KartenFarbe.BLATT, KartenSymbol.UNTER),
BLATT_O(KartenFarbe.BLATT, KartenSymbol.OBER),
BLATT_K(KartenFarbe.BLATT, KartenSymbol.KOENIG),
BLATT_X(KartenFarbe.BLATT, KartenSymbol.TEN),
BLATT_A(KartenFarbe.BLATT, KartenSymbol.ASS),
EICHEL_7(KartenFarbe.EICHEL, KartenSymbol.SEVEN),
EICHEL_8(KartenFarbe.EICHEL, KartenSymbol.EIGHT),
EICHEL_9(KartenFarbe.EICHEL, KartenSymbol.NINE),
EICHEL_U(KartenFarbe.EICHEL, KartenSymbol.UNTER),
EICHEL_O(KartenFarbe.EICHEL, KartenSymbol.OBER),
EICHEL_K(KartenFarbe.EICHEL, KartenSymbol.KOENIG),
EICHEL_X(KartenFarbe.EICHEL, KartenSymbol.TEN),
EICHEL_A(KartenFarbe.EICHEL, KartenSymbol.ASS);
private final String id;
private final KartenFarbe farbe;

View File

@@ -121,7 +121,7 @@ public class KartenListe {
/**
* A Class that represents a list of Cards.
*/
private boolean containsKarte(Karte karte) {
public boolean containsKarte(Karte karte) {
for (Karte karteInListe : this.kartenListe) {
if (karteInListe.getId().equals(karte.getId())) {
return true;

View File

@@ -1,16 +1,11 @@
package org.schafkopf.player;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenSymbol;
import org.schafkopf.karte.KartenUtil;
import org.schafkopf.spielcontroller.SauSpielController;
import org.schafkopf.spielcontroller.SpielController;
/**
* Player that represents the Bot.
*/
/** Player that represents the Bot. */
public class BotPlayer extends Player {
private KartenListe eigeneKarten;
@@ -21,22 +16,23 @@ public class BotPlayer extends Player {
}
@Override
public Karte play(SpielController spiel, KartenListe tischKarten) {
public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) {
Karte cardIndex = eigeneKarten.getByIndex(spiel.welcheKarteSpielIch(0,
eigeneKarten,
eigeneKarten,
tischKarten));
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
eigeneKarten.removeKarten(cardIndex);
Karte card = spiel.welcheKarteSpielIch(true, gespielteKarten, eigeneKarten, tischKarten);
eigeneKarten.removeKarten(card);
System.out.println("Eigene Karte legen");
return cardIndex;
return card;
}
/**
* Set the Cards of the Player.
*/
/** Set the Cards of the Player. */
public void setCards(KartenListe cards) {
System.out.println("Eigene Karte setzen");
this.eigeneKarten = cards;

View File

@@ -19,7 +19,7 @@ public class LocalPlayer extends Player {
}
@Override
public Karte play(SpielController spiel, KartenListe tischKarten) {
public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) {
return schafkopf.wartetAufKarte();
}
}

View File

@@ -4,9 +4,8 @@ import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.spielcontroller.SpielController;
/**
* Class that represents one Player of the game.
*/
/** Class that represents one Player of the game. */
public abstract class Player {
public abstract Karte play(SpielController spiel, KartenListe tischKarten);
public abstract Karte play(
SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten);
}

View File

@@ -1,13 +1,12 @@
package org.schafkopf.spielcontroller;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenSymbol;
import org.schafkopf.karte.KartenUtil;
/**
* SpielController that implements Logic of a Farb Geier.
*/
/** SpielController that implements Logic of a Farb Geier. */
public class FarbGeierController extends SoloController {
/**
* Create instance of SpielController.
@@ -27,9 +26,11 @@ public class FarbGeierController extends SoloController {
this.farbKarten = new KartenListe(kartenList);
}
public int welcheKarteSpielIch(int meinePosition,
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
return 0;
public Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten) {
return null;
}
}

View File

@@ -6,9 +6,7 @@ import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenSymbol;
import org.schafkopf.karte.KartenUtil;
/**
* SpielController that implements Logic of a Farb Solo.
*/
/** SpielController that implements Logic of a Farb Solo. */
public class FarbSoloController extends SoloController {
/**
* Create instance of SpielController.
@@ -32,8 +30,11 @@ public class FarbSoloController extends SoloController {
this.farbKarten = new KartenListe(kartenList);
}
public int welcheKarteSpielIch(int meinePosition,
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
return 0;
public Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten) {
return null;
}
}

View File

@@ -6,9 +6,7 @@ import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenSymbol;
import org.schafkopf.karte.KartenUtil;
/**
* SpielController that implements Logic of a Farb Wenz.
*/
/** SpielController that implements Logic of a Farb Wenz. */
public class FarbWenzController extends SoloController {
/**
* Create instance of SpielController.
@@ -28,8 +26,11 @@ public class FarbWenzController extends SoloController {
this.farbKarten = new KartenListe(kartenList);
}
public int welcheKarteSpielIch(int meinePosition,
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
return 0;
public Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten) {
return null;
}
}

View File

@@ -1,6 +1,5 @@
package org.schafkopf.spielcontroller;
import java.util.List;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
@@ -14,8 +13,8 @@ public class GeierWenzController extends SoloController {
}
@Override
public int welcheKarteSpielIch(int meinePosition, KartenListe gespielteKarten,
public Karte welcheKarteSpielIch(boolean istSpieler, KartenListe gespielteKarten,
KartenListe meineHand, KartenListe tischKarten) {
return 0;
return null;
}
}

View File

@@ -1,66 +1,58 @@
package org.schafkopf.spielcontroller;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
/**
* SpielController that implements Logic of a Sau Spiel Game.
*/
/** SpielController that implements Logic of a Sau Spiel Game. */
public class SauSpielController extends StandardController {
KartenFarbe suchFarbe;
boolean istSpieler;
/**
* Class that represents one Card of the game.
*/
/** Class that represents one Card of the game. */
public SauSpielController(int activePlayer, KartenFarbe farbe) {
super(activePlayer);
this.suchFarbe = suchFarbe;
this.istSpieler = istSpieler;
this.suchFarbe = farbe;
}
/**
* choose witch Card should be played with the right Game logic.
*/
public int welcheKarteSpielIch(int meinePosition,
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
/** choose witch Card should be played with the right Game logic. */
public Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten) {
System.out.println("Ich spiele eine Karte Sauspiel");
int spielerNummer = tischKarten.size();
if (istSpieler && tischKarten.getLast().getFarbe().equals(suchFarbe)) {
return farbeZugeben(meineHand, suchFarbe, 2);
}
switch (spielerNummer) {
case 0:
if (istSpieler) {
return meineHand.size() - 1;
return meineHand.getLast();
} else {
return 0;
return meineHand.getByIndex(0);
}
case 1:
if (istSpieler) {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
} else {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
}
case 2:
if (istSpieler) {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
} else {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
}
case 3:
if (istSpieler) {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 2);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
} else {
return farbeZugeben(meineHand, tischKarten.getLast().getFarbe(), 0);
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
}
default:
System.out.println("Ungültige SpielerNummer");
}
return 0;
return null;
}
}

View File

@@ -1,5 +1,6 @@
package org.schafkopf.spielcontroller;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenListe;
/**
@@ -11,8 +12,8 @@ public abstract class SoloController extends SpielController {
super(activePlayer);
}
public int welcheKarteSpielIch(
public Karte welcheKarteSpielIch(
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
return 0;
return null;
}
}

View File

@@ -1,5 +1,6 @@
package org.schafkopf.spielcontroller;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenUtil;
@@ -19,40 +20,52 @@ public abstract class SpielController {
* Create instance of SpielController.
*
* @param meineHand Cards one Player holds.
* @param farbe color the Player has to play.
* @param ersteKarte color the Player has to play.
* @param mode Mode the player chooses a Card if multiple are available.
*/
public static int farbeZugeben(KartenListe meineHand, KartenFarbe farbe, int mode) {
KartenListe farbKarten = meineHand.getKarten(farbe);
farbKarten.removeKarten(trumpfKarten);
if (farbKarten.size() == 1) {
return meineHand.indexOf(farbKarten.getByIndex(0));
public static Karte farbeZugeben(KartenListe meineHand, Karte ersteKarte, int mode) {
KartenListe hand = new KartenListe(meineHand);
sortiereKarten(hand);
boolean trumpfGespielt = trumpfKarten.containsKarte(ersteKarte);
KartenListe handTrumpfKarten = hand.removeKarten(trumpfKarten);
KartenListe handfarbKarten;
if (trumpfGespielt) {
handfarbKarten = handTrumpfKarten;
} else {
handfarbKarten = hand.getKarten(ersteKarte.getFarbe());
}
if (farbKarten.size() > 1) {
if (handfarbKarten.size() == 1) {
return handfarbKarten.getByIndex(0);
} else if (handfarbKarten.size() > 1) {
return switch (mode) {
case 0 -> // Abspatzen
handfarbKarten.getByIndex(0);
case 1, 2 -> // Stechen // Schmieren
handfarbKarten.getLast();
default -> null;
};
}
if (handfarbKarten.isEmpty()) {
switch (mode) {
case 0:
return 0;
case 1:
return meineHand.indexOf(farbKarten.getLast());
case 2:
return meineHand.indexOf(farbKarten.getLast());
case 0: // Abspatzen
return hand.getByIndex(0);
case 1: // Schmieren
return hand.getLast();
case 2: // Stechen
if (!handTrumpfKarten.isEmpty()) {
return handTrumpfKarten.getLast(); // trumpf reinspielen
} else {
return hand.getByIndex(0); // wenn kein Trumpf und farblos, abschpatzen
}
default:
return 0;
return null;
}
}
if (farbKarten.isEmpty()) {
switch (mode) {
case 0:
return 0;
case 1:
return 0;
case 2:
return meineHand.size() - 1;
default:
return 0;
}
}
return 0;
return null;
}
/**
@@ -100,8 +113,8 @@ public abstract class SpielController {
}
}
public abstract int welcheKarteSpielIch(
int meinePosition,
public abstract Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten);
@@ -110,6 +123,10 @@ public abstract class SpielController {
return trumpfKarten;
}
public boolean isTrumpf(Karte card) {
return trumpfKarten.containsKarte(card);
}
public KartenListe getFarbKarten() {
return farbKarten;
}

View File

@@ -1,13 +1,12 @@
package org.schafkopf.spielcontroller;
import org.schafkopf.karte.Karte;
import org.schafkopf.karte.KartenFarbe;
import org.schafkopf.karte.KartenListe;
import org.schafkopf.karte.KartenSymbol;
import org.schafkopf.karte.KartenUtil;
/**
* SpielController that has the standard Card Deck for Sauspiel, Bettel und Co.
*/
/** SpielController that has the standard Card Deck for Sauspiel, Bettel und Co. */
public abstract class StandardController extends SpielController {
StandardController(int activePlayer) {
@@ -26,6 +25,9 @@ public abstract class StandardController extends SpielController {
this.farbKarten = new KartenListe(kartenList);
}
public abstract int welcheKarteSpielIch(int meinePosition,
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten);
public abstract Karte welcheKarteSpielIch(
boolean istSpieler,
KartenListe gespielteKarten,
KartenListe meineHand,
KartenListe tischKarten);
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 815 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 859 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 971 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 954 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 797 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 603 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 646 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 730 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 768 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1008 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 870 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 412 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 470 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 498 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 626 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 957 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1010 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 959 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 686 KiB

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 704 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 741 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 881 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1009 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1015 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 958 KiB

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" class="iconify iconify--logos" width="37.07" height="36" preserveAspectRatio="xMidYMid meet" viewBox="0 0 256 198"><path fill="#41B883" d="M204.8 0H256L128 220.8L0 0h97.92L128 51.2L157.44 0h47.36Z"></path><path fill="#41B883" d="m0 0l128 220.8L256 0h-51.2L128 132.48L50.56 0H0Z"></path><path fill="#35495E" d="M50.56 0L128 133.12L204.8 0h-47.36L128 51.2L97.92 0H50.56Z"></path></svg>

After

Width:  |  Height:  |  Size: 496 B

View File

@@ -0,0 +1,15 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + Vue</title>
<script type="module" crossorigin src="/assets/index-6278b98f.js"></script>
<link rel="stylesheet" href="/assets/index-08f560d4.css">
</head>
<body class="bg-gray-800">
<div id="app"></div>
</body>
</html>