mirror of
https://github.com/Vale54321/schafkopf-bot.git
synced 2025-12-16 11:49:33 +01:00
init kotlin backend
This commit is contained in:
@@ -1,20 +1,89 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.schafkopf</groupId>
|
||||
<artifactId>schafkopf-backend-java</artifactId>
|
||||
<version>1.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>de.heiserer</groupId>
|
||||
<artifactId>schafkopf-2</artifactId>
|
||||
<version>0.0.1</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>schafkopf-shared</artifactId>
|
||||
<artifactId>schafkopf-shared</artifactId>
|
||||
|
||||
<properties>
|
||||
<maven.compiler.source>21</maven.compiler.source>
|
||||
<maven.compiler.target>21</maven.compiler.target>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<kotlin.code.style>official</kotlin.code.style>
|
||||
<kotlin.compiler.jvmTarget>1.8</kotlin.compiler.jvmTarget>
|
||||
</properties>
|
||||
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>mavenCentral</id>
|
||||
<url>https://repo1.maven.org/maven2/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
|
||||
<build>
|
||||
<sourceDirectory>src/main/kotlin</sourceDirectory>
|
||||
<testSourceDirectory>src/test/kotlin</testSourceDirectory>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compile</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>test-compile</id>
|
||||
<phase>test-compile</phase>
|
||||
<goals>
|
||||
<goal>test-compile</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>2.22.2</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<mainClass>MainKt</mainClass>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-test-junit5</artifactId>
|
||||
<version>2.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.junit.jupiter</groupId>
|
||||
<artifactId>junit-jupiter</artifactId>
|
||||
<version>5.10.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.jetbrains.kotlin</groupId>
|
||||
<artifactId>kotlin-stdlib</artifactId>
|
||||
<version>2.0.0</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
@@ -1,51 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import java.util.List;
|
||||
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
|
||||
import org.schafkopf.player.BotPlayer;
|
||||
import org.schafkopf.player.Player;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public abstract class BaseGameSession implements MessageSender {
|
||||
|
||||
protected static final Logger logger = LoggerFactory.getLogger(BaseGameSession.class);
|
||||
protected Thread spielThread;
|
||||
protected Schafkopf schafkopf;
|
||||
protected List<Player> players;
|
||||
|
||||
void startGame(List<Player> players) {
|
||||
logger.info("Starting game");
|
||||
for (int i = players.size(); i < 4; i++) {
|
||||
players.add(new BotPlayer("Bot " + i));
|
||||
}
|
||||
|
||||
sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.GAME_START_READY));
|
||||
|
||||
//wait for 5 seconds
|
||||
try {
|
||||
Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
spielThread = new Thread(() -> {
|
||||
try {
|
||||
schafkopf = new Schafkopf(players.toArray(Player[]::new), this);
|
||||
schafkopf.startGame();
|
||||
} catch (NotEnoughPlayersException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
});
|
||||
|
||||
spielThread.start();
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
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 String 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, String player) {
|
||||
this.gamePhase = phase;
|
||||
this.currentPlayer = player;
|
||||
}
|
||||
|
||||
/**
|
||||
* GameState.
|
||||
*/
|
||||
public GameState(GamePhase phase, String 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, String player, Karte card) {
|
||||
this.gamePhase = phase;
|
||||
this.currentPlayer = player;
|
||||
this.card = card;
|
||||
}
|
||||
|
||||
/**
|
||||
* GameState.
|
||||
*/
|
||||
public JsonObject getJson() {
|
||||
Gson gson = new Gson();
|
||||
JsonObject gameStateObject = new JsonObject();
|
||||
|
||||
if (this.currentPlayer != null) {
|
||||
gameStateObject.addProperty("currentPlayer", this.currentPlayer);
|
||||
}
|
||||
if (this.card != null) {
|
||||
gameStateObject.add("card", gson.toJsonTree(this.card));
|
||||
}
|
||||
gameStateObject.addProperty("gamePhase", this.gamePhase.name());
|
||||
gameStateObject.addProperty("trumpf", this.trumpf);
|
||||
if (this.color != null) {
|
||||
gameStateObject.addProperty("color", this.color.name());
|
||||
}
|
||||
|
||||
return gameStateObject;
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public interface MessageListener {
|
||||
|
||||
void receiveMessage(String message);
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public interface MessageSender {
|
||||
|
||||
void sendMessage(SchafkopfBaseMessage message);
|
||||
}
|
||||
@@ -1,116 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import org.schafkopf.GameState.GamePhase;
|
||||
import org.schafkopf.SchafkopfException.NotEnoughPlayersException;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
|
||||
import org.schafkopf.karte.KartenFarbe;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
import org.schafkopf.player.BotPlayer;
|
||||
import org.schafkopf.player.OnlinePlayer;
|
||||
import org.schafkopf.player.Player;
|
||||
import org.schafkopf.spielcontroller.SauSpielController;
|
||||
import org.schafkopf.spielcontroller.SpielController;
|
||||
|
||||
/**
|
||||
* The main class representing the Schafkopf game.
|
||||
*/
|
||||
public class Schafkopf {
|
||||
|
||||
private final MessageSender messageSender;
|
||||
|
||||
/**
|
||||
* The game controller. This is the class that implements the game logic.
|
||||
*/
|
||||
private SpielController spiel = new SauSpielController(0, KartenFarbe.EICHEL);
|
||||
|
||||
private final Player[] player;
|
||||
|
||||
private GameState gameState = new GameState(GamePhase.GAME_STOP);
|
||||
|
||||
/**
|
||||
* Constructor for the Schafkopf class.
|
||||
*
|
||||
* @param messageSender MessageSender
|
||||
*/
|
||||
public Schafkopf(Player[] player, MessageSender messageSender) throws NotEnoughPlayersException {
|
||||
this.player = player;
|
||||
|
||||
if (player.length < 4) {
|
||||
throw new NotEnoughPlayersException();
|
||||
}
|
||||
|
||||
this.messageSender = messageSender;
|
||||
System.out.println("SchaffKopfGame erstellt");
|
||||
}
|
||||
|
||||
public Player[] getPlayer() {
|
||||
return player;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set GameState to "started" and start Game Thread.
|
||||
*/
|
||||
public void startGame() throws InterruptedException {
|
||||
if (gameState.getGamePhase() != GamePhase.GAME_STOP) {
|
||||
System.out.println("Game already started!");
|
||||
messageSender.sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR));
|
||||
} else {
|
||||
gameState = new GameState(GamePhase.GAME_START);
|
||||
setAndSendGameState(gameState);
|
||||
System.out.println("Start Game");
|
||||
|
||||
KartenListe austeilen = KartenUtil.initializeSchafKopfCardDeck();
|
||||
austeilen.shuffle();
|
||||
for (Player currentPlayer : player) {
|
||||
if (currentPlayer instanceof BotPlayer botPlayer) {
|
||||
KartenListe botHand = new KartenListe();
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
botHand.addKarten(austeilen.removeKarten(austeilen.getByIndex(i)));
|
||||
}
|
||||
System.out.println("Bot Hand: " + botHand.getJson().toString());
|
||||
botPlayer.setCards(botHand); // Replace with the actual method you want to call
|
||||
}
|
||||
}
|
||||
|
||||
for (Player currentPlayer : player) {
|
||||
if (currentPlayer instanceof OnlinePlayer onlinePlayer) {
|
||||
KartenListe karten = new KartenListe();
|
||||
for (int i = 7; i >= 0; i--) {
|
||||
karten.addKarten(austeilen.removeKarten(austeilen.getByIndex(i)));
|
||||
}
|
||||
onlinePlayer.setAndSendPlayerCards(karten);
|
||||
}
|
||||
}
|
||||
|
||||
new Spielablauf(this, spiel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set GameState to "stopped" and interrupt Game Thread.
|
||||
*/
|
||||
public void stopGame() {
|
||||
if (gameState.getGamePhase() == GamePhase.GAME_STOP) {
|
||||
System.out.println("no active Game!");
|
||||
messageSender.sendMessage(new SchafkopfBaseMessage(SchafkopfMessageType.UNKNOWN_ERROR));
|
||||
} else {
|
||||
gameState = new GameState(GamePhase.GAME_STOP);
|
||||
setAndSendGameState(gameState);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public void setAndSendGameState(GameState gameState) {
|
||||
this.gameState = gameState;
|
||||
this.messageSender.sendMessage(
|
||||
new SchafkopfBaseMessage(SchafkopfMessageType.GAME_STATE, gameState.getJson()));
|
||||
}
|
||||
|
||||
public GameState getGameState() {
|
||||
return this.gameState;
|
||||
}
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public class SchafkopfException extends Exception {
|
||||
|
||||
private SchafkopfException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public static class NotEnoughPlayersException extends SchafkopfException {
|
||||
|
||||
public NotEnoughPlayersException() {
|
||||
super("Not enough players to start the game");
|
||||
}
|
||||
|
||||
// You can also include additional constructors or methods if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public static class NoGameSessionException extends SchafkopfException {
|
||||
|
||||
public NoGameSessionException() {
|
||||
super("No game session available");
|
||||
}
|
||||
|
||||
// You can also include additional constructors or methods if needed
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The main entrypoint of the Application.
|
||||
*/
|
||||
public static class PlayerNotReadyException extends SchafkopfException {
|
||||
|
||||
public PlayerNotReadyException() {
|
||||
super("Not all Players are in Ready State");
|
||||
}
|
||||
|
||||
// You can also include additional constructors or methods if needed
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public class InvalidMoveException extends SchafkopfException {
|
||||
|
||||
// Constructor with a message
|
||||
public InvalidMoveException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
// You can also include additional constructors or methods if needed
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,156 +0,0 @@
|
||||
package org.schafkopf;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public class SchafkopfMessage {
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public static class SchafkopfBaseMessage {
|
||||
|
||||
private JsonObject message;
|
||||
private SchafkopfMessageType messageType;
|
||||
|
||||
public SchafkopfBaseMessage(SchafkopfMessageType messageType, String content) {
|
||||
this.messageType = messageType;
|
||||
this.message = buildBaseMessage(messageType, content);
|
||||
}
|
||||
|
||||
public SchafkopfBaseMessage(SchafkopfMessageType messageType, JsonObject content) {
|
||||
this.messageType = messageType;
|
||||
this.message = buildBaseMessage(messageType, content);
|
||||
}
|
||||
|
||||
public SchafkopfBaseMessage(SchafkopfMessageType messageType) {
|
||||
this.messageType = messageType;
|
||||
this.message = buildBaseMessage(messageType);
|
||||
}
|
||||
|
||||
public JsonObject getBaseMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
JsonObject message;
|
||||
|
||||
public SchafkopfMessage(SchafkopfMessageOrigin origin, SchafkopfBaseMessage baseMessage) {
|
||||
this.message = buildWrapperMessage(origin, baseMessage.getBaseMessage());
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public SchafkopfMessage(SchafkopfMessageOrigin origin, SchafkopfMessageType messageType) {
|
||||
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.add("content", buildBaseMessage(messageType));
|
||||
|
||||
this.message = buildWrapperMessage(origin, messageContentObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
private SchafkopfMessage(SchafkopfMessageOrigin origin, SchafkopfMessageType messageType,
|
||||
JsonObject messageContent) {
|
||||
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.add("content", buildBaseMessage(messageType, messageContent));
|
||||
|
||||
this.message = buildWrapperMessage(origin, messageContentObject);
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public SchafkopfMessage(SchafkopfMessageOrigin origin, SchafkopfMessageType messageType,
|
||||
String messageContent) {
|
||||
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.add("content", buildBaseMessage(messageType, messageContent));
|
||||
|
||||
this.message = buildWrapperMessage(origin, messageContentObject);
|
||||
}
|
||||
|
||||
private static JsonObject buildWrapperMessage(SchafkopfMessageOrigin origin, JsonObject message) {
|
||||
JsonObject messageObject = new JsonObject();
|
||||
messageObject.addProperty("origin", origin.toString());
|
||||
messageObject.add("message", message);
|
||||
|
||||
return messageObject;
|
||||
}
|
||||
|
||||
private static JsonObject buildBaseMessage(SchafkopfMessageType messageType,
|
||||
String messageContent) {
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.addProperty("message_type", messageType.toString());
|
||||
messageContentObject.addProperty("content", messageContent);
|
||||
|
||||
return messageContentObject;
|
||||
}
|
||||
|
||||
private static JsonObject buildBaseMessage(SchafkopfMessageType messageType,
|
||||
JsonObject messageContent) {
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.addProperty("message_type", messageType.toString());
|
||||
messageContentObject.add("content", messageContent);
|
||||
|
||||
return messageContentObject;
|
||||
}
|
||||
|
||||
private static JsonObject buildBaseMessage(SchafkopfMessageType messageType) {
|
||||
JsonObject messageContentObject = new JsonObject();
|
||||
messageContentObject.addProperty("message_type", messageType.toString());
|
||||
|
||||
return messageContentObject;
|
||||
}
|
||||
|
||||
public JsonObject getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public String getMessageAsString() {
|
||||
return message.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public enum SchafkopfMessageType {
|
||||
UNKNOWN_ERROR,
|
||||
|
||||
INFO_MESSAGE,
|
||||
HEARTBEAT_SYN,
|
||||
HEARTBEAT_ACK,
|
||||
GET_CARD_ONLINE_PLAYER,
|
||||
ONLINE_PLAYER_HAND,
|
||||
GAME_STATE,
|
||||
SERVER_CONNECTION_SUCCESSFUL,
|
||||
REQUEST_SERVER_CONNECTION,
|
||||
JOIN_ONLINE_GAME,
|
||||
START_DEDICATED_GAME,
|
||||
PLAYER_CARD,
|
||||
LIST_ONLINE_GAMES,
|
||||
|
||||
GET_ONLINE_GAME,
|
||||
CREATE_ONLINE_GAME,
|
||||
SET_STATUS_READY,
|
||||
SET_PLAYER_NAME,
|
||||
GAME_START_READY,
|
||||
LEAVE_ONLINE_GAME
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public enum SchafkopfMessageOrigin {
|
||||
FRONTEND,
|
||||
BACKEND,
|
||||
DEDICATED_SERVER
|
||||
}
|
||||
}
|
||||
@@ -1,90 +0,0 @@
|
||||
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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* The main class that controlls the game flow.
|
||||
*/
|
||||
public class Spielablauf {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(Spielablauf.class);
|
||||
private final KartenListe gespielteKarten = new KartenListe();
|
||||
|
||||
private final KartenListe tischKarten = new KartenListe();
|
||||
|
||||
private final SpielController spiel;
|
||||
|
||||
private final Player[] players;
|
||||
|
||||
private final Schafkopf schafkopf;
|
||||
|
||||
Spielablauf(Schafkopf schafkopf, SpielController spiel) throws InterruptedException {
|
||||
this.schafkopf = schafkopf;
|
||||
this.spiel = spiel;
|
||||
this.players = schafkopf.getPlayer();
|
||||
|
||||
playRound();
|
||||
}
|
||||
|
||||
private void playRound() throws InterruptedException {
|
||||
int startingPlayer = 0;
|
||||
|
||||
logger.info("Starte Stiche");
|
||||
for (int i = 0; i < 8; i++) {
|
||||
logger.info("Stich: {}", i);
|
||||
startingPlayer = playTrick(startingPlayer);
|
||||
}
|
||||
schafkopf.stopGame();
|
||||
}
|
||||
|
||||
private int playTrick(int startingPlayer) throws InterruptedException {
|
||||
schafkopf.setAndSendGameState(new GameState(GamePhase.TRICK_START));
|
||||
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int currentPlayer = (i + startingPlayer) % 4;
|
||||
|
||||
logger.info("Spieler ist dran: {}", players[currentPlayer].getName());
|
||||
schafkopf.setAndSendGameState(
|
||||
new GameState(GamePhase.WAIT_FOR_CARD, players[currentPlayer].getName()));
|
||||
|
||||
Karte playedCard = players[currentPlayer].play(spiel, tischKarten, gespielteKarten);
|
||||
tischKarten.addKarten(playedCard);
|
||||
|
||||
schafkopf.setAndSendGameState(
|
||||
new GameState(
|
||||
GamePhase.PLAYER_CARD,
|
||||
players[currentPlayer].getName(),
|
||||
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, players[winningPlayerIndex].getName(),
|
||||
tischKarten.getByIndex(stichSpieler)));
|
||||
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
logger.error("error sleep");
|
||||
}
|
||||
|
||||
gespielteKarten.addKarten(tischKarten);
|
||||
tischKarten.clear();
|
||||
|
||||
return winningPlayerIndex;
|
||||
}
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
package org.schafkopf.karte;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonObject;
|
||||
|
||||
/** enum to represent all cards in the game. */
|
||||
public enum Karte {
|
||||
SCHELL_7(KartenFarbe.SCHELL, KartenSymbol.SEVEN),
|
||||
SCHELL_8(KartenFarbe.SCHELL, KartenSymbol.EIGHT),
|
||||
SCHELL_9(KartenFarbe.SCHELL, KartenSymbol.NINE),
|
||||
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_U(KartenFarbe.HERZ, KartenSymbol.UNTER),
|
||||
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;
|
||||
private final KartenSymbol symbol;
|
||||
|
||||
private final String displayName;
|
||||
|
||||
private final int punkte;
|
||||
|
||||
Karte(KartenFarbe farbe, KartenSymbol symbol) {
|
||||
this.farbe = farbe;
|
||||
this.symbol = symbol;
|
||||
this.id = this.name().toLowerCase();
|
||||
this.displayName = farbe.getDisplayName() + " " + symbol.getDisplayName();
|
||||
this.punkte = symbol.getValue();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return this.id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return this.displayName;
|
||||
}
|
||||
|
||||
public KartenFarbe getFarbe() {
|
||||
return this.farbe;
|
||||
}
|
||||
|
||||
public KartenSymbol getSymbol() {
|
||||
return this.symbol;
|
||||
}
|
||||
|
||||
public int getPunkte() {
|
||||
return this.punkte;
|
||||
}
|
||||
|
||||
/** get the Card as a Json Object. */
|
||||
public JsonObject getJson() {
|
||||
Gson gson = new Gson();
|
||||
JsonObject jsonObject = new JsonObject();
|
||||
jsonObject.add("card", gson.toJsonTree(this));
|
||||
|
||||
return jsonObject;
|
||||
}
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
package org.schafkopf.karte;
|
||||
|
||||
/**
|
||||
* Enum for all possible Card Colors.
|
||||
*/
|
||||
public enum KartenFarbe {
|
||||
EICHEL("Eichel"),
|
||||
BLATT("Blatt"),
|
||||
HERZ("Herz"),
|
||||
SCHELL("Schell");
|
||||
|
||||
private final String displayName;
|
||||
|
||||
KartenFarbe(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
}
|
||||
@@ -1,238 +0,0 @@
|
||||
package org.schafkopf.karte;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonElement;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public class KartenListe {
|
||||
|
||||
private List<Karte> kartenListe;
|
||||
|
||||
public KartenListe() {
|
||||
this.kartenListe = new ArrayList<>();
|
||||
}
|
||||
|
||||
public KartenListe(KartenListe liste) {
|
||||
this.kartenListe = new ArrayList<>(liste.getKartenListe());
|
||||
}
|
||||
|
||||
public List<Karte> getKartenListe() {
|
||||
return this.kartenListe;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public void sort() {
|
||||
KartenListe completeDeck = KartenUtil.initializeSchafKopfCardDeck();
|
||||
completeDeck.removeKarten(this);
|
||||
|
||||
KartenListe completeDeck2 = KartenUtil.initializeSchafKopfCardDeck();
|
||||
completeDeck2.removeKarten(completeDeck);
|
||||
|
||||
this.kartenListe = completeDeck2.getKartenListe();
|
||||
}
|
||||
|
||||
public void shuffle() {
|
||||
Collections.shuffle(this.kartenListe);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public void addKarten(Karte karte) {
|
||||
if (!this.containsKarte(karte)) {
|
||||
this.kartenListe.add(karte);
|
||||
return;
|
||||
}
|
||||
throw new RuntimeException("Karte bereits vorhanden: " + karte.getName());
|
||||
}
|
||||
|
||||
// methoden zum hinzufügen von karten
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public void addKarten(KartenListe karten) {
|
||||
for (Karte karte : karten.getKartenListe()) {
|
||||
this.addKarten(karte);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public KartenListe removeKarten(KartenListe karten) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karteWeg : karten.getKartenListe()) {
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getId().equals(karteWeg.getId())) {
|
||||
result.addKarten(karte);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.kartenListe.removeAll(result.getKartenListe());
|
||||
return result;
|
||||
}
|
||||
|
||||
// methoden zum entfernen von karten
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public KartenListe removeKarten(KartenFarbe farbe) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getFarbe().equals(farbe)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
this.kartenListe.removeAll(result.getKartenListe());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public KartenListe removeKarten(KartenSymbol symbol) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getSymbol().equals(symbol)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
this.kartenListe.removeAll(result.getKartenListe());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public Karte removeKarten(Karte karteToRemove) {
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getId().equals(karteToRemove.getId())) {
|
||||
this.kartenListe.remove(karte);
|
||||
return karte;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public Karte removeKarten(String idToRemove) {
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getId().equals(idToRemove)) {
|
||||
this.kartenListe.remove(karte);
|
||||
return karte;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public boolean containsKarte(Karte karte) {
|
||||
for (Karte karteInListe : this.kartenListe) {
|
||||
if (karteInListe.getId().equals(karte.getId())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// get Karten
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public KartenListe getKarten(KartenFarbe farbe) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getFarbe().equals(farbe)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public KartenListe getKarten(KartenSymbol symbol) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getSymbol().equals(symbol)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public Karte getKarten(KartenSymbol symbol, KartenFarbe farbe) {
|
||||
KartenListe result = new KartenListe();
|
||||
for (Karte karte : this.kartenListe) {
|
||||
if (karte.getSymbol().equals(symbol)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
for (Karte karte : result.kartenListe) {
|
||||
if (karte.getFarbe().equals(farbe)) {
|
||||
result.addKarten(karte);
|
||||
}
|
||||
}
|
||||
return result.getByIndex(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public JsonElement getJson() {
|
||||
Gson gson = new Gson();
|
||||
|
||||
return gson.toJsonTree(this.kartenListe);
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return this.kartenListe.isEmpty();
|
||||
}
|
||||
|
||||
public Karte getLast() {
|
||||
return this.kartenListe.getLast();
|
||||
}
|
||||
|
||||
public Karte getByIndex(int index) {
|
||||
return this.kartenListe.get(index);
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return this.kartenListe.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public int indexOf(Karte karte) {
|
||||
for (Karte karteInListe : this.kartenListe) {
|
||||
if (karteInListe.getId().equals(karte.getId())) {
|
||||
return this.kartenListe.indexOf(karteInListe);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
this.kartenListe.clear();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
package org.schafkopf.karte;
|
||||
|
||||
/**
|
||||
* Enum for all possible Card Symbols.
|
||||
*/
|
||||
public enum KartenSymbol {
|
||||
SIX("6", "6", 0),
|
||||
SEVEN("7", "7", 0),
|
||||
EIGHT("8", "8", 0),
|
||||
NINE("9", "9", 0),
|
||||
UNTER("u", "Unter", 2),
|
||||
OBER("o", "Ober", 3),
|
||||
KOENIG("k", "König", 4),
|
||||
TEN("x", "10", 10),
|
||||
ASS("a", "Ass", 11);
|
||||
|
||||
private final String displayName;
|
||||
private final String id;
|
||||
private final int value;
|
||||
|
||||
KartenSymbol(String id, String displayName, int value) {
|
||||
this.displayName = displayName;
|
||||
this.value = value;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public int getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
@@ -1,82 +0,0 @@
|
||||
package org.schafkopf.karte;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/** Class that brings usefully functions for Card/s. */
|
||||
public class KartenUtil {
|
||||
|
||||
/** initialize a normal Card Deck. It will be in the standard order. */
|
||||
public static KartenListe initializeSchafKopfCardDeck() {
|
||||
KartenListe deck = new KartenListe();
|
||||
|
||||
for (Karte karte : Karte.values()) {
|
||||
deck.addKarten(karte);
|
||||
}
|
||||
|
||||
deck.removeKarten(KartenSymbol.SIX);
|
||||
return deck;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a List of Random Cards.
|
||||
*
|
||||
* @param anzahl count of random cards.
|
||||
*/
|
||||
public static KartenListe zieheZufallsHand(int anzahl) {
|
||||
KartenListe karten = initializeSchafKopfCardDeck();
|
||||
KartenListe gezogeneKarten = new KartenListe();
|
||||
Random random = new Random();
|
||||
|
||||
// Ziehe zufällige Karten
|
||||
for (int i = 0; i < anzahl; i++) {
|
||||
int zufallsIndex = random.nextInt(karten.size());
|
||||
Karte gezogeneKarte = karten.getByIndex(zufallsIndex);
|
||||
gezogeneKarten.addKarten(gezogeneKarte);
|
||||
karten.removeKarten(gezogeneKarte);
|
||||
}
|
||||
return gezogeneKarten;
|
||||
}
|
||||
|
||||
/**
|
||||
* converts Uid from a NFC Card to a card ID.
|
||||
*
|
||||
* @param uid uId to get the Card ID from.
|
||||
*/
|
||||
public static Karte getIdOfUid(String uid) {
|
||||
return switch (uid) {
|
||||
case "04E7A9C2126F80" -> Karte.EICHEL_7;
|
||||
case "04A46BB4780000" -> Karte.EICHEL_8;
|
||||
case "04A26BB4780000" -> Karte.EICHEL_9;
|
||||
case "04A16BB4780000" -> Karte.EICHEL_X;
|
||||
case "049E6BB4780000" -> Karte.EICHEL_K;
|
||||
case "04A86BB4780000" -> Karte.EICHEL_A;
|
||||
case "04A06BB4780000" -> Karte.EICHEL_U;
|
||||
case "049F6BB4780000" -> Karte.EICHEL_O;
|
||||
case "04F26BB4780000" -> Karte.BLATT_7;
|
||||
case "04A76BB4780000" -> Karte.BLATT_8;
|
||||
case "049B6BB4780000" -> Karte.BLATT_9;
|
||||
case "04996BB4780000" -> Karte.BLATT_X;
|
||||
case "041CD2C2126F81" -> Karte.BLATT_K;
|
||||
case "04A96BB4780000" -> Karte.BLATT_A;
|
||||
case "049A6BB4780000" -> Karte.BLATT_U;
|
||||
case "049D6BB4780000" -> Karte.BLATT_O;
|
||||
case "04936BB4780000" -> Karte.SCHELL_7;
|
||||
case "04F697C2126F80" -> Karte.SCHELL_8;
|
||||
case "04946BB4780000" -> Karte.SCHELL_9;
|
||||
case "04956BB4780000" -> Karte.SCHELL_X;
|
||||
case "04986BB4780000" -> Karte.SCHELL_K;
|
||||
case "04AA6BB4780000" -> Karte.SCHELL_A;
|
||||
case "04966BB4780000" -> Karte.SCHELL_U;
|
||||
case "04976BB4780000" -> Karte.SCHELL_O;
|
||||
case "04F36BB4780000" -> Karte.HERZ_7;
|
||||
case "04B06BB4780000" -> Karte.HERZ_8;
|
||||
case "04AF6BB4780000" -> Karte.HERZ_9;
|
||||
case "04AE6BB4780000" -> Karte.HERZ_X;
|
||||
case "04AB6BB4780000" -> Karte.HERZ_K;
|
||||
case "049C6BB4780000" -> Karte.HERZ_A;
|
||||
case "04AD6BB4780000" -> Karte.HERZ_U;
|
||||
case "04AC6BB4780000" -> Karte.HERZ_O;
|
||||
default -> null;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
package org.schafkopf.player;
|
||||
|
||||
import org.schafkopf.MessageSender;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
import org.schafkopf.spielcontroller.SpielController;
|
||||
|
||||
/**
|
||||
* Player that represents the Bot.
|
||||
*/
|
||||
public class BotPlayer extends Player {
|
||||
|
||||
private KartenListe eigeneKarten;
|
||||
private KartenListe unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck();
|
||||
|
||||
/**
|
||||
* Constructor for the BotPlayer.
|
||||
*/
|
||||
public BotPlayer(String name) {
|
||||
super(name, new MessageSender() {
|
||||
@Override
|
||||
public void sendMessage(SchafkopfBaseMessage message) {
|
||||
System.out.println("BotPlayer: " + message);
|
||||
}
|
||||
});
|
||||
this.setReady(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten) {
|
||||
|
||||
try {
|
||||
Thread.sleep(1000);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Karte card = spiel.welcheKarteSpielIch(true, gespielteKarten, eigeneKarten, tischKarten);
|
||||
|
||||
eigeneKarten.removeKarten(card);
|
||||
|
||||
System.out.println("Eigene Karte legen");
|
||||
return card;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the Cards of the Player.
|
||||
*/
|
||||
public void setCards(KartenListe cards) {
|
||||
System.out.println("Eigene Karte setzen");
|
||||
cards.sort();
|
||||
this.eigeneKarten = cards;
|
||||
this.unbekannteKarten = KartenUtil.initializeSchafKopfCardDeck();
|
||||
this.unbekannteKarten.removeKarten(eigeneKarten);
|
||||
System.out.println("Eigene Karte fertig");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(SchafkopfBaseMessage message) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetReady() {
|
||||
// Not needed
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package org.schafkopf.player;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import org.schafkopf.MessageSender;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfBaseMessage;
|
||||
import org.schafkopf.SchafkopfMessage.SchafkopfMessageType;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.spielcontroller.SpielController;
|
||||
|
||||
/**
|
||||
* Player that plays in real life.
|
||||
*/
|
||||
public class OnlinePlayer extends Player {
|
||||
|
||||
private final BlockingQueue<Karte> receivedCardQueue = new LinkedBlockingQueue<>();
|
||||
|
||||
private KartenListe karten = new KartenListe();
|
||||
|
||||
public OnlinePlayer(MessageSender messageSender, String name) {
|
||||
super(name, messageSender);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Class that represents a list of Cards.
|
||||
*/
|
||||
public void setAndSendPlayerCards(KartenListe karten) {
|
||||
karten.sort();
|
||||
this.karten = karten;
|
||||
|
||||
sendPlayerCards();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Karte play(SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten)
|
||||
throws InterruptedException {
|
||||
sendPlayerCards();
|
||||
Karte spielKarte = null;
|
||||
|
||||
// Send the message to request the card from the frontend
|
||||
messageSender.sendMessage(
|
||||
new SchafkopfBaseMessage(SchafkopfMessageType.GET_CARD_ONLINE_PLAYER));
|
||||
|
||||
spielKarte = receivedCardQueue.take();
|
||||
|
||||
this.karten.removeKarten(spielKarte);
|
||||
sendPlayerCards();
|
||||
System.out.println("Karte gespielt: " + spielKarte);
|
||||
return spielKarte;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetReady() {
|
||||
this.setReady(false);
|
||||
}
|
||||
|
||||
private void sendPlayerCards() {
|
||||
JsonObject messageObject = new JsonObject();
|
||||
messageObject.add("cards", this.karten.getJson());
|
||||
|
||||
messageSender.sendMessage(
|
||||
new SchafkopfBaseMessage(SchafkopfMessageType.ONLINE_PLAYER_HAND, messageObject));
|
||||
}
|
||||
|
||||
/**
|
||||
* Class that represents one Frontend Connection.
|
||||
*/
|
||||
public void receiveCard(Karte receivedCard) {
|
||||
System.out.println("Received Card before Queue: " + receivedCard.getName());
|
||||
receivedCardQueue.add(receivedCard);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(SchafkopfBaseMessage message) {
|
||||
messageSender.sendMessage(message);
|
||||
}
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
package org.schafkopf.player;
|
||||
|
||||
import org.schafkopf.MessageSender;
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.spielcontroller.SpielController;
|
||||
|
||||
/**
|
||||
* Class that represents one Player of the game.
|
||||
*/
|
||||
public abstract class Player implements MessageSender {
|
||||
|
||||
protected MessageSender messageSender;
|
||||
private boolean ready = false;
|
||||
private String name;
|
||||
|
||||
protected Player(String name, MessageSender messageSender) {
|
||||
this.messageSender = messageSender;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public abstract Karte play(
|
||||
SpielController spiel, KartenListe tischKarten, KartenListe gespielteKarten)
|
||||
throws InterruptedException;
|
||||
|
||||
public abstract void resetReady();
|
||||
|
||||
public void setReady(boolean ready) {
|
||||
this.ready = ready;
|
||||
}
|
||||
|
||||
public boolean isReady() {
|
||||
return ready;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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. */
|
||||
public class FarbGeierController extends SoloController {
|
||||
/**
|
||||
* Create instance of SpielController.
|
||||
*
|
||||
* @param farbe Trumpffarbe of the Farb Geier.
|
||||
*/
|
||||
public FarbGeierController(int activePlayer, KartenFarbe farbe) {
|
||||
super(activePlayer);
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe oberKarten = kartenList.getKarten(KartenSymbol.OBER);
|
||||
KartenListe farbTrumpfKarten = kartenList.getKarten(farbe);
|
||||
farbTrumpfKarten.removeKarten(KartenSymbol.OBER);
|
||||
farbTrumpfKarten.addKarten(oberKarten);
|
||||
kartenList.removeKarten(farbTrumpfKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(farbTrumpfKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
|
||||
public Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
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 Solo. */
|
||||
public class FarbSoloController extends SoloController {
|
||||
/**
|
||||
* Create instance of SpielController.
|
||||
*
|
||||
* @param farbe Trumpffarbe of the Farb Solo.
|
||||
*/
|
||||
public FarbSoloController(int activePlayer, KartenFarbe farbe) {
|
||||
super(activePlayer);
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER);
|
||||
|
||||
KartenListe farbTrumpfKarten = kartenList.getKarten(farbe);
|
||||
farbTrumpfKarten.removeKarten(KartenSymbol.UNTER);
|
||||
farbTrumpfKarten.removeKarten(KartenSymbol.OBER);
|
||||
farbTrumpfKarten.addKarten(kartenList.getKarten(KartenSymbol.UNTER));
|
||||
farbTrumpfKarten.addKarten(kartenList.getKarten(KartenSymbol.OBER));
|
||||
|
||||
kartenList.removeKarten(farbTrumpfKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(farbTrumpfKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
|
||||
public Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,36 +0,0 @@
|
||||
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 Wenz. */
|
||||
public class FarbWenzController extends SoloController {
|
||||
/**
|
||||
* Create instance of SpielController.
|
||||
*
|
||||
* @param farbe Trumpffarbe of the Farb Wenz.
|
||||
*/
|
||||
public FarbWenzController(int activePlayer, KartenFarbe farbe) {
|
||||
super(activePlayer);
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER);
|
||||
KartenListe farbTrumpfKarten = kartenList.getKarten(farbe);
|
||||
farbTrumpfKarten.removeKarten(KartenSymbol.UNTER);
|
||||
farbTrumpfKarten.addKarten(unterKarten);
|
||||
kartenList.removeKarten(farbTrumpfKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(farbTrumpfKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
|
||||
public Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,24 +0,0 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenSymbol;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
|
||||
/**
|
||||
* SpielController that implements Logic of a Geier Game.
|
||||
*/
|
||||
public class GeierController extends GeierWenzController {
|
||||
/**
|
||||
* Create instance of Geier Game.
|
||||
*/
|
||||
public GeierController(int activePlayer) {
|
||||
super(activePlayer);
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe oberKarten = kartenList.getKarten(KartenSymbol.OBER);
|
||||
|
||||
kartenList.removeKarten(oberKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(oberKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
|
||||
/**
|
||||
* SpielController that implements Logic of a Geier/Wenz Game.
|
||||
*/
|
||||
public class GeierWenzController extends SoloController {
|
||||
|
||||
public GeierWenzController(int activePlayer) {
|
||||
super(activePlayer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Karte welcheKarteSpielIch(boolean istSpieler, KartenListe gespielteKarten,
|
||||
KartenListe meineHand, KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,58 +0,0 @@
|
||||
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. */
|
||||
public class SauSpielController extends StandardController {
|
||||
|
||||
KartenFarbe suchFarbe;
|
||||
|
||||
/** Class that represents one Card of the game. */
|
||||
public SauSpielController(int activePlayer, KartenFarbe farbe) {
|
||||
super(activePlayer);
|
||||
this.suchFarbe = farbe;
|
||||
}
|
||||
|
||||
/** 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();
|
||||
|
||||
switch (spielerNummer) {
|
||||
case 0:
|
||||
if (istSpieler) {
|
||||
return meineHand.getLast();
|
||||
} else {
|
||||
return meineHand.getByIndex(0);
|
||||
}
|
||||
case 1:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
case 2:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
case 3:
|
||||
if (istSpieler) {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 2);
|
||||
} else {
|
||||
return farbeZugeben(meineHand, tischKarten.getByIndex(0), 0);
|
||||
}
|
||||
default:
|
||||
System.out.println("Ungültige SpielerNummer");
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
|
||||
/**
|
||||
* abstract Class that represents Logic of a Solo like Game.
|
||||
*/
|
||||
public abstract class SoloController extends SpielController {
|
||||
|
||||
SoloController(int activePlayer) {
|
||||
super(activePlayer);
|
||||
}
|
||||
|
||||
public Karte welcheKarteSpielIch(
|
||||
KartenListe gespielteKarten, KartenListe meineHand, KartenListe tischKarten) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.Karte;
|
||||
import org.schafkopf.karte.KartenFarbe;
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
|
||||
/** Base Class of Game Controllers. */
|
||||
public abstract class SpielController {
|
||||
protected static KartenListe trumpfKarten;
|
||||
protected static KartenListe farbKarten;
|
||||
|
||||
protected static int activePlayer;
|
||||
|
||||
public SpielController(int activePlayer) {
|
||||
this.activePlayer = activePlayer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create instance of SpielController.
|
||||
*
|
||||
* @param meineHand Cards one Player holds.
|
||||
* @param ersteKarte color the Player has to play.
|
||||
* @param mode Mode the player chooses a Card if multiple are available.
|
||||
*/
|
||||
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 (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: // 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 null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* sorts Cards, so they are in the right order for the active game.
|
||||
*
|
||||
* @param karten Trumpffarbe of the Farb Geier.
|
||||
*/
|
||||
public static void sortiereKarten(KartenListe karten) {
|
||||
KartenListe kartenReihenfolge = new KartenListe(farbKarten);
|
||||
kartenReihenfolge.addKarten(trumpfKarten);
|
||||
|
||||
KartenListe kartenListe = KartenUtil.initializeSchafKopfCardDeck();
|
||||
|
||||
kartenListe.removeKarten(karten);
|
||||
kartenReihenfolge.removeKarten(kartenListe);
|
||||
|
||||
karten.clear();
|
||||
karten.addKarten(kartenReihenfolge);
|
||||
}
|
||||
|
||||
/**
|
||||
* checks, which card has the highest strength and will win one Stich.
|
||||
*
|
||||
* @param karten Cards to check.
|
||||
*/
|
||||
public static int welcheKarteSticht(KartenListe karten) {
|
||||
KartenListe kartenNew = new KartenListe(karten);
|
||||
sortiereKarten(kartenNew);
|
||||
KartenListe farbTischKarten = kartenNew.removeKarten(trumpfKarten);
|
||||
System.out.println("trumpfKarten:");
|
||||
System.out.println(trumpfKarten.getJson());
|
||||
|
||||
if (!farbTischKarten.isEmpty()) {
|
||||
System.out.println("trumpfkarten:");
|
||||
System.out.println(farbTischKarten.getJson());
|
||||
return karten.indexOf(farbTischKarten.getLast());
|
||||
} else {
|
||||
KartenFarbe firstColor = karten.getByIndex(0).getFarbe();
|
||||
KartenListe firstColorCards = kartenNew.removeKarten(firstColor);
|
||||
|
||||
System.out.println("firstcolor:");
|
||||
System.out.println(firstColorCards.getJson());
|
||||
|
||||
return karten.indexOf(firstColorCards.getLast());
|
||||
}
|
||||
}
|
||||
|
||||
public abstract Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten);
|
||||
|
||||
public KartenListe getTrumpfKarten() {
|
||||
return trumpfKarten;
|
||||
}
|
||||
|
||||
public boolean isTrumpf(Karte card) {
|
||||
return trumpfKarten.containsKarte(card);
|
||||
}
|
||||
|
||||
public KartenListe getFarbKarten() {
|
||||
return farbKarten;
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
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. */
|
||||
public abstract class StandardController extends SpielController {
|
||||
|
||||
StandardController(int activePlayer) {
|
||||
super(activePlayer);
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe herzKarten = kartenList.getKarten(KartenFarbe.HERZ);
|
||||
herzKarten.removeKarten(KartenSymbol.UNTER);
|
||||
herzKarten.removeKarten(KartenSymbol.OBER);
|
||||
|
||||
herzKarten.addKarten(kartenList.getKarten(KartenSymbol.UNTER));
|
||||
herzKarten.addKarten(kartenList.getKarten(KartenSymbol.OBER));
|
||||
|
||||
kartenList.removeKarten(herzKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(herzKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
|
||||
public abstract Karte welcheKarteSpielIch(
|
||||
boolean istSpieler,
|
||||
KartenListe gespielteKarten,
|
||||
KartenListe meineHand,
|
||||
KartenListe tischKarten);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
package org.schafkopf.spielcontroller;
|
||||
|
||||
import org.schafkopf.karte.KartenListe;
|
||||
import org.schafkopf.karte.KartenSymbol;
|
||||
import org.schafkopf.karte.KartenUtil;
|
||||
|
||||
/**
|
||||
* SpielController that implements Logic of a Wenz Game.
|
||||
*/
|
||||
public class WenzController extends GeierWenzController {
|
||||
/**
|
||||
* Create instance of Wenz Game.
|
||||
*/
|
||||
public WenzController(int activePlayer) {
|
||||
super(activePlayer);
|
||||
this.activePlayer = activePlayer;
|
||||
KartenListe kartenList = KartenUtil.initializeSchafKopfCardDeck();
|
||||
KartenListe unterKarten = kartenList.getKarten(KartenSymbol.UNTER);
|
||||
|
||||
kartenList.removeKarten(unterKarten);
|
||||
|
||||
this.trumpfKarten = new KartenListe(unterKarten);
|
||||
this.farbKarten = new KartenListe(kartenList);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,113 @@
|
||||
package de.heiserer
|
||||
|
||||
class SchafkopfGameController {
|
||||
private val players = listOf(NPCPlayer("NPC 1"), NPCPlayer("NPC 2"), NPCPlayer("NPC 3"), NPCPlayer("NPC 4"))
|
||||
|
||||
private lateinit var gameType: GameType
|
||||
private val playedCards: CardList = UnsortedCardList()
|
||||
|
||||
fun playRound(startingOffset: Int = 0){
|
||||
serveCards()
|
||||
|
||||
gameType = GameType.SAU_SPIEL
|
||||
players.forEach { it.sortCards(gameType) }
|
||||
|
||||
var startingPlayer: Player = players[startingOffset % 4]
|
||||
|
||||
for(i in 0 until 8){
|
||||
startingPlayer = playTrick(startingPlayer)
|
||||
}
|
||||
}
|
||||
|
||||
private fun playTrick(startingPlayer: Player): Player{
|
||||
val tableCards = UnsortedCardList()
|
||||
|
||||
for(i in 0 until 4){
|
||||
val currentPlayer = calculatePlayerOffset(startingPlayer, i)
|
||||
currentPlayer.printName()
|
||||
|
||||
val card = currentPlayer.playCard(tableCards, gameType)
|
||||
tableCards.add(card)
|
||||
}
|
||||
|
||||
tableCards.print()
|
||||
|
||||
return startingPlayer
|
||||
}
|
||||
|
||||
private fun calculatePlayerOffset(startingPlayer: Player, i: Int): Player = players[(players.indexOf(startingPlayer) + i) % 4]
|
||||
|
||||
private fun serveCards(){
|
||||
val deck = UnsortedCardList(true)
|
||||
deck.shuffle()
|
||||
|
||||
for(i in 0 until 4){
|
||||
val playerCards = UnsortedCardList()
|
||||
|
||||
for(j in 0 until 8){
|
||||
playerCards.add(deck.removeLast())
|
||||
}
|
||||
|
||||
players[i % 4].serveCards(playerCards)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class Player(private var name: String){
|
||||
protected var cards: SortedCardList = SortedCardList(GameType.SAU_SPIEL)
|
||||
|
||||
fun serveCards(cards: UnsortedCardList){
|
||||
this.cards = cards.asSortedCardList(GameType.SAU_SPIEL)
|
||||
}
|
||||
|
||||
fun sortCards(gameType: GameType){
|
||||
cards = cards.asSortedCardList(gameType)
|
||||
println("Spieler $name hat folgende Karten sortiert:")
|
||||
cards.print()
|
||||
println()
|
||||
println("Trumpf:")
|
||||
cards.getTrumpf().print()
|
||||
println()
|
||||
println("Farbe:")
|
||||
cards.getCardsWithoutTrumpf().print()
|
||||
println()
|
||||
}
|
||||
|
||||
abstract fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card
|
||||
|
||||
fun printName(){
|
||||
println(name)
|
||||
}
|
||||
}
|
||||
|
||||
class NPCPlayer(name: String) : Player(name){
|
||||
override fun playCard(tableCards: UnsortedCardList, gameType: GameType): Card {
|
||||
if(tableCards.size() == 0){
|
||||
println("Erster Spieler")
|
||||
val card = cards.removeLast()
|
||||
println("Spielt ${card.displayName}")
|
||||
println()
|
||||
return card
|
||||
}
|
||||
|
||||
val firstCard = tableCards.get(0)
|
||||
if(cards.farbFreiOrTrumpf(firstCard, gameType)){
|
||||
println("farbFrei Or Trumpf")
|
||||
return playTrumpf()
|
||||
}
|
||||
}
|
||||
|
||||
private fun playTrumpf(): Card {
|
||||
val trumpf = cards.getTrumpf()
|
||||
if (trumpf.size() > 0) {
|
||||
println("play Trumpf")
|
||||
val card = trumpf.removeLast()
|
||||
println("Spielt ${card.displayName}")
|
||||
println()
|
||||
return cards.remove(card)
|
||||
} else {
|
||||
println("abspatzen")
|
||||
return cards.removeFirst()
|
||||
}
|
||||
}
|
||||
}
|
||||
82
Backend/schafkopf-shared/src/main/kotlin/Schafkopfkarte.kt
Normal file
82
Backend/schafkopf-shared/src/main/kotlin/Schafkopfkarte.kt
Normal file
@@ -0,0 +1,82 @@
|
||||
package de.heiserer
|
||||
|
||||
enum class Card(val color: CardColor, val symbol: CardSymbol) {
|
||||
SCHELL_7(CardColor.SCHELL, CardSymbol.SIEBEN),
|
||||
SCHELL_8(CardColor.SCHELL, CardSymbol.ACHT),
|
||||
SCHELL_9(CardColor.SCHELL, CardSymbol.NINE),
|
||||
SCHELL_U(CardColor.SCHELL, CardSymbol.UNTER),
|
||||
SCHELL_O(CardColor.SCHELL, CardSymbol.OBER),
|
||||
SCHELL_K(CardColor.SCHELL, CardSymbol.KOENIG),
|
||||
SCHELL_X(CardColor.SCHELL, CardSymbol.ZEHN),
|
||||
SCHELL_A(CardColor.SCHELL, CardSymbol.ASS),
|
||||
HERZ_7(CardColor.HERZ, CardSymbol.SIEBEN),
|
||||
HERZ_8(CardColor.HERZ, CardSymbol.ACHT),
|
||||
HERZ_9(CardColor.HERZ, CardSymbol.NINE),
|
||||
HERZ_U(CardColor.HERZ, CardSymbol.UNTER),
|
||||
HERZ_O(CardColor.HERZ, CardSymbol.OBER),
|
||||
HERZ_K(CardColor.HERZ, CardSymbol.KOENIG),
|
||||
HERZ_X(CardColor.HERZ, CardSymbol.ZEHN),
|
||||
HERZ_A(CardColor.HERZ, CardSymbol.ASS),
|
||||
BLATT_7(CardColor.BLATT, CardSymbol.SIEBEN),
|
||||
BLATT_8(CardColor.BLATT, CardSymbol.ACHT),
|
||||
BLATT_9(CardColor.BLATT, CardSymbol.NINE),
|
||||
BLATT_U(CardColor.BLATT, CardSymbol.UNTER),
|
||||
BLATT_O(CardColor.BLATT, CardSymbol.OBER),
|
||||
BLATT_K(CardColor.BLATT, CardSymbol.KOENIG),
|
||||
BLATT_X(CardColor.BLATT, CardSymbol.ZEHN),
|
||||
BLATT_A(CardColor.BLATT, CardSymbol.ASS),
|
||||
EICHEL_7(CardColor.EICHEL, CardSymbol.SIEBEN),
|
||||
EICHEL_8(CardColor.EICHEL, CardSymbol.ACHT),
|
||||
EICHEL_9(CardColor.EICHEL, CardSymbol.NINE),
|
||||
EICHEL_U(CardColor.EICHEL, CardSymbol.UNTER),
|
||||
EICHEL_O(CardColor.EICHEL, CardSymbol.OBER),
|
||||
EICHEL_K(CardColor.EICHEL, CardSymbol.KOENIG),
|
||||
EICHEL_X(CardColor.EICHEL, CardSymbol.ZEHN),
|
||||
EICHEL_A(CardColor.EICHEL, CardSymbol.ASS);
|
||||
|
||||
val id = name.lowercase()
|
||||
val displayName = "${color.displayName} ${symbol.displayName}"
|
||||
val points = symbol.value
|
||||
}
|
||||
|
||||
enum class CardColor(val order: Int, val displayName: String) {
|
||||
SCHELL(0,"Schell"),
|
||||
HERZ(1,"Herz"),
|
||||
BLATT(2,"Blatt"),
|
||||
EICHEL(3,"Eichel")
|
||||
}
|
||||
|
||||
enum class CardSymbol(val order: Int, val displayName: String, val value: Int) {
|
||||
SIEBEN(0,"7", 0),
|
||||
ACHT(1,"8", 0),
|
||||
NINE(2,"9", 0),
|
||||
UNTER(3,"Unter", 2),
|
||||
OBER(4,"Ober", 3),
|
||||
KOENIG(5,"König", 4),
|
||||
ZEHN(6,"10", 10),
|
||||
ASS(7,"Ass", 11)
|
||||
}
|
||||
|
||||
enum class GameType(val color: CardColor?, val symbol: CardSymbol?){
|
||||
RAMSCH(CardColor.HERZ, null),
|
||||
SAU_SPIEL(CardColor.HERZ, null),
|
||||
BETTEL(CardColor.HERZ, null),
|
||||
|
||||
SCHELL_GEIER(CardColor.SCHELL, CardSymbol.OBER),
|
||||
HERZ_GEIER(CardColor.HERZ, CardSymbol.OBER),
|
||||
BLATT_GEIER(CardColor.BLATT, CardSymbol.OBER),
|
||||
EICHEL_GEIER(CardColor.EICHEL, CardSymbol.OBER),
|
||||
|
||||
SCHELL_WENZ(CardColor.SCHELL, CardSymbol.UNTER),
|
||||
HERZ_WENZ(CardColor.HERZ, CardSymbol.UNTER),
|
||||
BLATT_WENZ(CardColor.BLATT, CardSymbol.UNTER),
|
||||
EICHEL_WENZ(CardColor.EICHEL, CardSymbol.UNTER),
|
||||
|
||||
GEIER(null, CardSymbol.OBER),
|
||||
WENZ(null, CardSymbol.UNTER),
|
||||
|
||||
SCHELL_SOLO(CardColor.SCHELL, null),
|
||||
BLATT_SOLO(CardColor.BLATT, null),
|
||||
EICHEL_SOLO(CardColor.EICHEL, null),
|
||||
HERZ_SOLO(CardColor.HERZ, null),
|
||||
}
|
||||
180
Backend/schafkopf-shared/src/main/kotlin/UnsortedCardList.kt
Normal file
180
Backend/schafkopf-shared/src/main/kotlin/UnsortedCardList.kt
Normal file
@@ -0,0 +1,180 @@
|
||||
package de.heiserer
|
||||
|
||||
interface CardList {
|
||||
fun add(card: Card)
|
||||
fun add(cards: CardList)
|
||||
fun remove(card: Card): Card
|
||||
fun remove(cards: CardList)
|
||||
fun removeLast(): Card
|
||||
fun get(index: Int): Card
|
||||
fun getCopyOfCards(): List<Card>
|
||||
fun size(): Int
|
||||
fun print()
|
||||
fun asSortedCardList(type: GameType): SortedCardList
|
||||
fun removeFirst(): Card
|
||||
}
|
||||
|
||||
open class UnsortedCardList(withAllCards: Boolean = false): CardList {
|
||||
private val cards: MutableList<Card> = if(withAllCards){
|
||||
enumValues<Card>().toMutableList()
|
||||
} else {
|
||||
mutableListOf()
|
||||
}
|
||||
|
||||
override fun add(card: Card) {
|
||||
if (card !in cards) {
|
||||
cards.add(card)
|
||||
} else {
|
||||
throw CardAlreadyAddedException("Karte $card is already in the deck.", card)
|
||||
}
|
||||
}
|
||||
|
||||
override fun add(cards: CardList) {
|
||||
cards.getCopyOfCards().forEach { card -> add(card) }
|
||||
}
|
||||
|
||||
override fun remove(card: Card) : Card {
|
||||
if (card !in cards) {
|
||||
throw IllegalArgumentException("Karte $card is not in the deck.")
|
||||
} else {
|
||||
cards.remove(card)
|
||||
return card
|
||||
}
|
||||
}
|
||||
|
||||
override fun remove(cards: CardList) {
|
||||
cards.getCopyOfCards().forEach { card -> remove(card) }
|
||||
}
|
||||
|
||||
override fun removeFirst(): Card {
|
||||
if (cards.isEmpty()) {
|
||||
throw IllegalArgumentException("Deck is empty.")
|
||||
}
|
||||
return cards.removeFirst()
|
||||
}
|
||||
|
||||
override fun removeLast(): Card {
|
||||
if (cards.isEmpty()) {
|
||||
throw IllegalArgumentException("Deck is empty.")
|
||||
}
|
||||
return cards.removeLast()
|
||||
}
|
||||
|
||||
override fun get(index: Int): Card {
|
||||
if(index < 0 || index >= cards.size){
|
||||
throw IllegalArgumentException("Index $index is out of bounds.")
|
||||
}
|
||||
return cards[index]
|
||||
}
|
||||
|
||||
protected fun get(color: CardColor): CardList {
|
||||
val list = UnsortedCardList()
|
||||
cards.forEach { card ->
|
||||
if (card.color == color) {
|
||||
list.add(card)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
protected fun get(symbol: CardSymbol): CardList {
|
||||
val list = UnsortedCardList()
|
||||
cards.forEach { card ->
|
||||
if (card.symbol == symbol) {
|
||||
list.add(card)
|
||||
}
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
override fun getCopyOfCards(): List<Card> {
|
||||
return cards.toList()
|
||||
}
|
||||
|
||||
override fun size(): Int {
|
||||
return cards.size
|
||||
}
|
||||
|
||||
override fun print() {
|
||||
println("KartenDeck:")
|
||||
cards.forEach { karte ->
|
||||
println(karte.displayName)
|
||||
}
|
||||
println()
|
||||
}
|
||||
|
||||
fun shuffle() {
|
||||
cards.shuffle()
|
||||
}
|
||||
|
||||
override fun asSortedCardList(type: GameType): SortedCardList {
|
||||
val sortedList = SortedCardList(type)
|
||||
cards.forEach { card -> sortedList.add(card) }
|
||||
return sortedList
|
||||
}
|
||||
|
||||
protected fun sortInternal(symbol: CardSymbol? = null, color: CardColor? = null) {
|
||||
if (symbol != null && symbol != CardSymbol.OBER && symbol != CardSymbol.UNTER) {
|
||||
throw IllegalArgumentException("Symbol $symbol is not accepted. Only OBER and UNTER are allowed.")
|
||||
}
|
||||
|
||||
cards.sortWith(compareBy<Card> {
|
||||
when {
|
||||
symbol == null && it.symbol == CardSymbol.OBER -> 3
|
||||
symbol == null && it.symbol == CardSymbol.UNTER -> 2
|
||||
symbol != null && it.symbol == symbol -> 2
|
||||
color != null && it.color == color -> 1
|
||||
else -> 0
|
||||
}
|
||||
}.thenComparing(compareBy({ it.color.order }, { it.symbol.order })))
|
||||
}
|
||||
}
|
||||
|
||||
class SortedCardList(private val gameType: GameType, withAllCards: Boolean = false) : UnsortedCardList(withAllCards) {
|
||||
private fun sort() {
|
||||
super.sortInternal(gameType.symbol, gameType.color)
|
||||
}
|
||||
|
||||
fun getCardsWithoutTrumpf(color: CardColor? = null): SortedCardList {
|
||||
val cardsWithoutTrumpf = SortedCardList(gameType)
|
||||
|
||||
color?.let { cardsWithoutTrumpf.add(get(it)) }?: cardsWithoutTrumpf.add(this)
|
||||
try {
|
||||
cardsWithoutTrumpf.remove(getTrumpf())
|
||||
} catch (_: IllegalArgumentException) {
|
||||
}
|
||||
|
||||
return cardsWithoutTrumpf
|
||||
}
|
||||
|
||||
fun getTrumpf():SortedCardList {
|
||||
val trumpf = SortedCardList(gameType)
|
||||
|
||||
gameType.symbol?.let {
|
||||
trumpf.add(get(it))
|
||||
} ?: run {
|
||||
trumpf.add(get(CardSymbol.OBER))
|
||||
trumpf.add(get(CardSymbol.UNTER))
|
||||
}
|
||||
|
||||
gameType.color?.let { try{
|
||||
trumpf.add(get(it))
|
||||
} catch (_: CardAlreadyAddedException) {}
|
||||
}
|
||||
|
||||
return trumpf
|
||||
}
|
||||
|
||||
fun farbFreiOrTrumpf(firstCard: Card, gameType: GameType) =
|
||||
firstCard.color == gameType.color || getCardsWithoutTrumpf(gameType.color).size() == 0
|
||||
|
||||
override fun add(card: Card) {
|
||||
super.add(card)
|
||||
sort()
|
||||
}
|
||||
}
|
||||
|
||||
class CardAlreadyAddedException(message: String, val card: Card) : RuntimeException(message) {
|
||||
|
||||
// You can add additional constructors or methods if needed, but for now, this is sufficient to handle the scenario of adding a card that's already in the list.
|
||||
}
|
||||
476
Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt
Normal file
476
Backend/schafkopf-shared/src/test/kotlin/CardListTest.kt
Normal file
@@ -0,0 +1,476 @@
|
||||
import de.heiserer.*
|
||||
import org.junit.jupiter.api.Assertions.*
|
||||
import org.junit.jupiter.api.Test
|
||||
import org.junit.jupiter.params.ParameterizedTest
|
||||
import org.junit.jupiter.params.provider.MethodSource
|
||||
|
||||
class UnsortedListTest {
|
||||
@Test
|
||||
fun `init with all cards`() {
|
||||
assertEquals(32, UnsortedCardList(true).size())
|
||||
}
|
||||
}
|
||||
|
||||
class SortingCardsTest {
|
||||
private val defaultList = listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
fun gameTypeProvider() = GameType.values().asList()
|
||||
}
|
||||
|
||||
private fun testCardSorting(expectedCards: List<Card>, gameType: GameType) {
|
||||
// ARRANGE
|
||||
var cards = UnsortedCardList()
|
||||
defaultList.shuffled().forEach {
|
||||
cards.add(it)
|
||||
}
|
||||
|
||||
// ACT
|
||||
cards = cards.asSortedCardList(gameType)
|
||||
|
||||
// ASSERT
|
||||
assertEquals(expectedCards.size, cards.size())
|
||||
expectedCards.forEachIndexed { index, card ->
|
||||
assertEquals(card, cards.get(index))
|
||||
}
|
||||
}
|
||||
|
||||
private fun expectedCardsForGameType(gameType: GameType): List<Card> {
|
||||
return when(gameType) {
|
||||
GameType.RAMSCH -> defaultList
|
||||
GameType.SAU_SPIEL -> defaultList
|
||||
GameType.BETTEL -> defaultList
|
||||
|
||||
GameType.SCHELL_GEIER -> listOf(
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.HERZ_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_X,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.BLATT_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.EICHEL_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_O
|
||||
)
|
||||
|
||||
GameType.SCHELL_WENZ -> listOf(
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
GameType.HERZ_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U
|
||||
)
|
||||
GameType.BLATT_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_A,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
GameType.EICHEL_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.EICHEL_U
|
||||
)
|
||||
|
||||
GameType.GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
|
||||
GameType.SCHELL_SOLO -> listOf(
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.BLATT_SOLO -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_A,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.EICHEL_SOLO -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.HERZ_SOLO -> defaultList
|
||||
else -> throw IllegalArgumentException("No expected cards defined for gameType: $gameType")
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "test sorting for {0}") // This gives a clear name in the test output
|
||||
@MethodSource("gameTypeProvider")
|
||||
fun `test sorting for all game types`(gameType: GameType) {
|
||||
// ARRANGE
|
||||
val expectedCards = expectedCardsForGameType(gameType)
|
||||
|
||||
// ACT & ASSERT
|
||||
testCardSorting(expectedCards, gameType)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
private fun testGetTrumpfCard(expectedCards: List<Card>, gameType: GameType) {
|
||||
// ARRANGE
|
||||
var cards = UnsortedCardList()
|
||||
defaultList.shuffled().forEach {
|
||||
cards.add(it)
|
||||
}
|
||||
|
||||
// ACT
|
||||
cards = cards.asSortedCardList(gameType).getTrumpf()
|
||||
|
||||
// ASSERT
|
||||
expectedCards.forEachIndexed { index, card ->
|
||||
assertEquals(card, cards.get(index))
|
||||
}
|
||||
}
|
||||
|
||||
private fun expectedTrumpfCardsForGameType(gameType: GameType): List<Card> {
|
||||
val herzList = listOf(
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
return when(gameType) {
|
||||
GameType.RAMSCH -> herzList
|
||||
GameType.SAU_SPIEL -> herzList
|
||||
GameType.BETTEL -> herzList
|
||||
|
||||
GameType.SCHELL_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.HERZ_GEIER -> listOf(
|
||||
Card.HERZ_X,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.BLATT_GEIER -> listOf(
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.EICHEL_GEIER -> listOf(
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
Card.HERZ_O
|
||||
)
|
||||
|
||||
GameType.SCHELL_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
GameType.HERZ_WENZ -> listOf(
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U
|
||||
)
|
||||
GameType.BLATT_WENZ -> listOf(
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
GameType.EICHEL_WENZ -> listOf(
|
||||
Card.EICHEL_A,
|
||||
Card.EICHEL_U
|
||||
)
|
||||
|
||||
GameType.GEIER -> listOf(
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.WENZ -> listOf(
|
||||
Card.EICHEL_U,
|
||||
)
|
||||
|
||||
GameType.SCHELL_SOLO -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.BLATT_SOLO -> listOf(
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.EICHEL_SOLO -> listOf(
|
||||
Card.EICHEL_A,
|
||||
Card.EICHEL_U,
|
||||
Card.HERZ_O
|
||||
)
|
||||
GameType.HERZ_SOLO -> herzList
|
||||
else -> throw IllegalArgumentException("No expected cards defined for gameType: $gameType")
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "test get Trumpfcards for {0}") // This gives a clear name in the test output
|
||||
@MethodSource("gameTypeProvider")
|
||||
fun `test get Trumpfcards for all game types`(gameType: GameType) {
|
||||
// ARRANGE
|
||||
val expectedCards = expectedTrumpfCardsForGameType(gameType)
|
||||
|
||||
// ACT & ASSERT
|
||||
testGetTrumpfCard(expectedCards, gameType)
|
||||
}
|
||||
|
||||
|
||||
|
||||
private fun testCardsWithoutTrumpf(expectedCards: List<Card>, gameType: GameType) {
|
||||
// ARRANGE
|
||||
var cards = UnsortedCardList()
|
||||
defaultList.shuffled().forEach {
|
||||
cards.add(it)
|
||||
}
|
||||
|
||||
// ACT
|
||||
cards = cards.asSortedCardList(gameType).getCardsWithoutTrumpf()
|
||||
|
||||
// ASSERT
|
||||
expectedCards.forEachIndexed { index, card ->
|
||||
assertEquals(card, cards.get(index))
|
||||
}
|
||||
}
|
||||
|
||||
private fun expectedCardsWithoutTrumpfForGameType(gameType: GameType): List<Card> {
|
||||
val herzList = listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
return when(gameType) {
|
||||
GameType.RAMSCH -> herzList
|
||||
GameType.SAU_SPIEL -> herzList
|
||||
GameType.BETTEL -> herzList
|
||||
|
||||
GameType.SCHELL_GEIER -> listOf(
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.HERZ_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.BLATT_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.EICHEL_GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
)
|
||||
|
||||
GameType.SCHELL_WENZ -> listOf(
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.HERZ_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.BLATT_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.EICHEL_WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
)
|
||||
|
||||
GameType.GEIER -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_U,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.WENZ -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_O,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
|
||||
GameType.SCHELL_SOLO -> listOf(
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.BLATT_SOLO -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.EICHEL_A,
|
||||
)
|
||||
GameType.EICHEL_SOLO -> listOf(
|
||||
Card.SCHELL_7,
|
||||
Card.SCHELL_K,
|
||||
Card.HERZ_X,
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
)
|
||||
GameType.HERZ_SOLO -> herzList
|
||||
else -> throw IllegalArgumentException("No expected cards defined for gameType: $gameType")
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "test get Cards without Trumpf for {0}") // This gives a clear name in the test output
|
||||
@MethodSource("gameTypeProvider")
|
||||
fun `test get Cards without Trumpf for all game types`(gameType: GameType) {
|
||||
// ARRANGE
|
||||
val expectedCards = expectedCardsWithoutTrumpfForGameType(gameType)
|
||||
|
||||
// ACT & ASSERT
|
||||
testCardsWithoutTrumpf(expectedCards, gameType)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test get Cards without Trumpf with Color`() {
|
||||
// ARRANGE
|
||||
var cards = UnsortedCardList()
|
||||
defaultList.shuffled().forEach {
|
||||
cards.add(it)
|
||||
}
|
||||
|
||||
val expectedCards = listOf(
|
||||
Card.BLATT_8,
|
||||
Card.BLATT_9,
|
||||
)
|
||||
|
||||
// ACT
|
||||
cards = cards.asSortedCardList(GameType.SAU_SPIEL).getCardsWithoutTrumpf(CardColor.BLATT)
|
||||
|
||||
// ASSERT
|
||||
expectedCards.forEachIndexed { index, card ->
|
||||
assertEquals(card, cards.get(index))
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user