diff --git a/dicegame/.gitattributes b/dicegame/.gitattributes new file mode 100644 index 00000000..f91f6460 --- /dev/null +++ b/dicegame/.gitattributes @@ -0,0 +1,12 @@ +# +# https://help.github.com/articles/dealing-with-line-endings/ +# +# Linux start script should use lf +/gradlew text eol=lf + +# These are Windows script files and should use crlf +*.bat text eol=crlf + +# Binary files should be left untouched +*.jar binary + diff --git a/dicegame/.gitignore b/dicegame/.gitignore new file mode 100644 index 00000000..eadf4f47 --- /dev/null +++ b/dicegame/.gitignore @@ -0,0 +1,8 @@ +/.idea/ +/target/ + +# Ignore Gradle project-specific cache directory +.gradle + +# Ignore Gradle build output directory +build diff --git a/dicegame/META-INF/MANIFEST.MF b/dicegame/META-INF/MANIFEST.MF index f961c940..4c4d1386 100644 --- a/dicegame/META-INF/MANIFEST.MF +++ b/dicegame/META-INF/MANIFEST.MF @@ -1,4 +1,4 @@ -Manifest-Version: 1.0 -Class-Path: . -Main-Class: WuerfelspielGUI - +Manifest-Version: 1.0 +Class-Path: . +Main-Class: WuerfelspielGUI + diff --git a/dicegame/gradle/libs.versions.toml b/dicegame/gradle/libs.versions.toml new file mode 100644 index 00000000..36adaf95 --- /dev/null +++ b/dicegame/gradle/libs.versions.toml @@ -0,0 +1,12 @@ +# This file was generated by the Gradle 'init' task. +# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format + +[versions] +guava = "33.2.1-jre" +junit-jupiter = "5.10.3" +mockito = "5.14.0" + +[libraries] +guava = { module = "com.google.guava:guava", version.ref = "guava" } +junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" } +mockito = { module = "org.mockito:mockito-core", version.ref = "mockito" } diff --git a/dicegame/gradle/wrapper/gradle-wrapper.jar b/dicegame/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 00000000..a4b76b95 Binary files /dev/null and b/dicegame/gradle/wrapper/gradle-wrapper.jar differ diff --git a/dicegame/gradle/wrapper/gradle-wrapper.properties b/dicegame/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000..df97d72b --- /dev/null +++ b/dicegame/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,7 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-bin.zip +networkTimeout=10000 +validateDistributionUrl=true +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/dicegame/gradlew b/dicegame/gradlew new file mode 100755 index 00000000..f5feea6d --- /dev/null +++ b/dicegame/gradlew @@ -0,0 +1,252 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s +' "$PWD" ) || exit + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/dicegame/gradlew.bat b/dicegame/gradlew.bat new file mode 100644 index 00000000..9d21a218 --- /dev/null +++ b/dicegame/gradlew.bat @@ -0,0 +1,94 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem +@rem SPDX-License-Identifier: Apache-2.0 +@rem + +@if "%DEBUG%"=="" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if %ERRORLEVEL% equ 0 goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. 1>&2 +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 +echo. 1>&2 +echo Please set the JAVA_HOME variable in your environment to match the 1>&2 +echo location of your Java installation. 1>&2 + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if %ERRORLEVEL% equ 0 goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/dicegame/pom.xml b/dicegame/pom.xml new file mode 100644 index 00000000..80ada6db --- /dev/null +++ b/dicegame/pom.xml @@ -0,0 +1,37 @@ + + + 4.0.0 + + de.uni-marburg.software-quality + dicegame + 1.0-SNAPSHOT + + + 21 + 21 + UTF-8 + + + + org.junit.jupiter + junit-jupiter + 5.11.3 + test + + + org.mockito + mockito-core + 5.11.0 + test + + + + + + + + + + diff --git a/dicegame/settings.gradle.kts b/dicegame/settings.gradle.kts new file mode 100644 index 00000000..71c4965b --- /dev/null +++ b/dicegame/settings.gradle.kts @@ -0,0 +1,14 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * The settings file is used to specify which projects to include in your build. + * For more detailed information on multi-project builds, please refer to https://docs.gradle.org/8.10.2/userguide/multi_project_builds.html in the Gradle documentation. + */ + +plugins { + // Apply the foojay-resolver plugin to allow automatic download of JDKs + id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" +} + +rootProject.name = "dicegame" +include("src") diff --git a/dicegame/src/build.gradle.kts b/dicegame/src/build.gradle.kts new file mode 100644 index 00000000..555b46fb --- /dev/null +++ b/dicegame/src/build.gradle.kts @@ -0,0 +1,73 @@ +/* + * This file was generated by the Gradle 'init' task. + * + * This generated file contains a sample Java application project to get you started. + * For more details on building Java & JVM projects, please refer to https://docs.gradle.org/8.10.2/userguide/building_java_projects.html in the Gradle documentation. + */ + +// As this is primarily a Maven project, our Java source files are not located inside the `/app/...` folder, +// thus we reconfigure their location here. +sourceSets { + main { + java { + srcDirs("main/java") + } + resources { + srcDirs("main/java") + } + } + test { + java { + srcDirs("test/java") + } + } +} + +plugins { + // Apply the application plugin to add support for building a CLI application in Java. + application +} + +repositories { + // Use Maven Central for resolving dependencies. + mavenCentral() +} + +val mockitoAgent = configurations.create("mockitoAgent") + +dependencies { + // Use JUnit Jupiter for testing. + testImplementation(libs.junit.jupiter) + // Use Mockito for mocking. + // https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mockito-instrumentation + testImplementation(libs.mockito) + mockitoAgent(libs.mockito) { isTransitive = false } + + + testRuntimeOnly("org.junit.platform:junit-platform-launcher") + + // This dependency is used by the application. + implementation(libs.guava) +} + +// Apply a specific Java toolchain to ease working on different environments. +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +application { + // Define the main class for the application. + mainClass = "dicegame.view.GUI" +} + +tasks { + test { + // Use JUnit Platform for unit tests. + useJUnitPlatform() + // Mockito JDK21+ config + // https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#mockito-instrumentation + jvmArgs("-javaagent:${mockitoAgent.asPath}") + } +} diff --git a/dicegame/src/dicegame/logic/DiceInteraction.java b/dicegame/src/main/java/dicegame/logic/DiceInteraction.java similarity index 96% rename from dicegame/src/dicegame/logic/DiceInteraction.java rename to dicegame/src/main/java/dicegame/logic/DiceInteraction.java index 0f57d7a4..c53c561c 100644 --- a/dicegame/src/dicegame/logic/DiceInteraction.java +++ b/dicegame/src/main/java/dicegame/logic/DiceInteraction.java @@ -1,5 +1,5 @@ -package dicegame.logic; - -public interface DiceInteraction { - public int changeDiceState(int diceIndex) throws SelectionException; -} +package dicegame.logic; + +public interface DiceInteraction { + public int changeDiceState(int diceIndex) throws SelectionException; +} diff --git a/dicegame/src/dicegame/logic/Logic.java b/dicegame/src/main/java/dicegame/logic/Logic.java similarity index 96% rename from dicegame/src/dicegame/logic/Logic.java rename to dicegame/src/main/java/dicegame/logic/Logic.java index cbd41089..50c98bf2 100644 --- a/dicegame/src/dicegame/logic/Logic.java +++ b/dicegame/src/main/java/dicegame/logic/Logic.java @@ -1,276 +1,276 @@ -package dicegame.logic; - -import java.util.Random; - -public class Logic implements DiceInteraction { - public static final int DICE_NUMBER = 6; - public static final int DEFAULT_PLAYER_NUMBER = 2; - public static final int DEFAULT_ROUNDS = 10; - private static final int DIE_UNFIXED = 0; - private static final int DIE_TEMP_FIXED = 1; - private static final int DIE_FIXED = 2; - private boolean gameIsRunning; - private boolean playerCanThrowDice; - private int currentPlayer; - private int roundNumber; - private int roundPoints; - private int maxRounds = DEFAULT_ROUNDS; - private int[] points = new int[2]; - private String[] names = new String[2]; - private int[] dicePips = new int[6]; - private int[] diceFixed = new int[6]; - private Random random; - - public Logic(Random random) { - this.random = random; - } - - public void startGame() { - this.resetGame(); - this.gameIsRunning = true; - this.playerCanThrowDice = true; - this.roundNumber = 1; - this.currentPlayer = 0; - } - - public String rollDice() { - if (!this.gameIsRunning) { - return "Das Spiel läuft aktuell nicht!"; - } else { - if (this.isAllDiceFixed()) { - this.resetDice(); - } - - for(int i = 0; i < DICE_NUMBER; ++i) { - if (this.diceFixed[i] == DIE_TEMP_FIXED) { - this.diceFixed[i] = DIE_FIXED; - } else if (this.diceFixed[i] == DIE_UNFIXED) { - this.dicePips[i] = this.random.nextInt(6) + 1; - } - } - - if (this.isScoringPipsAvailable()) { - this.playerCanThrowDice = true; - } else { - this.playerCanThrowDice = false; - this.roundPoints = 0; - } - - return null; - } - } - - public boolean isScoringPipsAvailable() { - for(int i = 0; i < DICE_NUMBER; ++i) { - if (this.diceFixed[i] != DIE_FIXED && (this.dicePips[i] == 5 || this.dicePips[i] == 1)) { - return true; - } - } - - return false; - } - - private boolean isAllDiceFixed() { - for(int i = 0; i < DICE_NUMBER; ++i) { - if (this.diceFixed[i] == DIE_UNFIXED) { - return false; - } - } - - return true; - } - - public String checkIfGameCanStart() { - if (this.gameIsRunning) { - return "Das Spiel läuft bereits!"; - } else { - for(int i = 0; i < DEFAULT_PLAYER_NUMBER; ++i) { - if (this.names[i] == null || this.names[i].trim().length() < 2) { - return "Spieler " + (i + 1) + " hat noch keinen Namen!"; - } - } - - return null; - } - } - - public void resetGame() { - this.roundNumber = 0; - this.roundPoints = 0; - this.resetDice(); - this.resetPoints(); - } - - public void finishRound() { - this.resetDice(); - int[] var10000 = this.points; - int var10001 = this.currentPlayer; - var10000[var10001] += this.roundPoints; - this.roundPoints = 0; - this.currentPlayer = ++this.currentPlayer % DEFAULT_PLAYER_NUMBER; - if (this.currentPlayer == 0) { - if (this.roundNumber == this.maxRounds) { - this.gameIsRunning = false; - } else { - ++this.roundNumber; - } - } - - } - - private void resetDice() { - for(int i = 0; i < DICE_NUMBER; ++i) { - this.diceFixed[i] = DIE_UNFIXED; - } - - } - - private void resetPoints() { - for(int i = 0; i < DEFAULT_PLAYER_NUMBER; ++i) { - this.points[i] = 0; - } - - } - - public int getRoundNumber() { - return this.roundNumber; - } - - public int getRoundPoints() { - return this.roundPoints; - } - - public boolean isDieFixed(int dieIndex) { - return this.diceFixed[dieIndex] != DIE_UNFIXED; - } - - public boolean isAtLeastOneDieFixedInCurrentThrow() { - for(int i = 0; i < DICE_NUMBER; ++i) { - if (this.diceFixed[i] == DIE_TEMP_FIXED) { - return true; - } - } - - return false; - } - - private int countTempFixedByPips(int pips) { - int count = 0; - - for(int i = 0; i < DICE_NUMBER; ++i) { - if (this.diceFixed[i] == DIE_TEMP_FIXED && this.dicePips[i] == pips) { - ++count; - } - } - - return count; - } - - public int getDiePips(int dieIndex) { - return this.dicePips[dieIndex]; - } - - public int getMaxRounds() { - return this.maxRounds; - } - - public String setMaxRounds(int maxRounds) { - if (this.gameIsRunning) { - return "Rundenzahl kann nicht während eines Spiels verändert werden!"; - } else { - this.maxRounds = maxRounds; - return null; - } - } - - public int getPoints(int playerIndex) { - return this.points[playerIndex]; - } - - public String getName(int playerIndex) { - return this.names[playerIndex]; - } - - public String setName(int playerIndex, String name) { - if (this.gameIsRunning) { - return "Ein Spielername kann nicht während eines Spiels verändert werden!"; - } else { - this.names[playerIndex] = name; - return null; - } - } - - public boolean isPlayerCanThrowDice() { - return this.playerCanThrowDice; - } - - public boolean isGameIsRunning() { - return this.gameIsRunning; - } - - public int getCurrentPlayer() { - return this.currentPlayer; - } - - @Override - public int changeDiceState(int diceIndex) throws SelectionException { - if (this.diceFixed[diceIndex] == DIE_UNFIXED) { - setDieFixed(diceIndex); - } else { - setDieUnfixed(diceIndex); - } - return roundPoints; - } - - private void setDieFixed(int dieIndex) throws SelectionException { - int c; - if (this.dicePips[dieIndex] == 1) { - c = this.countTempFixedByPips(1); - if (c != 2 && c != 5) { - this.roundPoints += 100; - } else { - this.roundPoints -= 200; - this.roundPoints += 1000; - } - - this.diceFixed[dieIndex] = DIE_TEMP_FIXED; - } else if (this.dicePips[dieIndex] == 5) { - c = this.countTempFixedByPips(5); - if (c != 2 && c != 5) { - this.roundPoints += 50; - } else { - this.roundPoints -= 100; - this.roundPoints += 500; - } - - this.diceFixed[dieIndex] = DIE_TEMP_FIXED; - } else { - throw new SelectionException("Es können nur 1'en und 5'en fixiert werden!"); - } - } - - private void setDieUnfixed(int dieIndex) throws SelectionException { - int c; - if (this.dicePips[dieIndex] == 1) { - c = this.countTempFixedByPips(1); - if (c != 3 && c != 6) { - this.roundPoints -= 100; - } else { - this.roundPoints -= 1000; - this.roundPoints += 200; - } - - this.diceFixed[dieIndex] = DIE_UNFIXED; - } else if (this.dicePips[dieIndex] == 5) { - c = this.countTempFixedByPips(5); - if (c != 3 && c != 6) { - this.roundPoints -= 50; - } else { - this.roundPoints -= 500; - this.roundPoints += 100; - } - - this.diceFixed[dieIndex] = DIE_UNFIXED; - } - } -} +package dicegame.logic; + +import java.util.Random; + +public class Logic implements DiceInteraction { + public static final int DICE_NUMBER = 6; + public static final int DEFAULT_PLAYER_NUMBER = 2; + public static final int DEFAULT_ROUNDS = 10; + private static final int DIE_UNFIXED = 0; + private static final int DIE_TEMP_FIXED = 1; + private static final int DIE_FIXED = 2; + private boolean gameIsRunning; + private boolean playerCanThrowDice; + private int currentPlayer; + private int roundNumber; + private int roundPoints; + private int maxRounds = DEFAULT_ROUNDS; + private int[] points = new int[2]; + private String[] names = new String[2]; + private int[] dicePips = new int[6]; + private int[] diceFixed = new int[6]; + private Random random; + + public Logic(Random random) { + this.random = random; + } + + public void startGame() { + this.resetGame(); + this.gameIsRunning = true; + this.playerCanThrowDice = true; + this.roundNumber = 1; + this.currentPlayer = 0; + } + + public String rollDice() { + if (!this.gameIsRunning) { + return "Das Spiel läuft aktuell nicht!"; + } else { + if (this.isAllDiceFixed()) { + this.resetDice(); + } + + for(int i = 0; i < DICE_NUMBER; ++i) { + if (this.diceFixed[i] == DIE_TEMP_FIXED) { + this.diceFixed[i] = DIE_FIXED; + } else if (this.diceFixed[i] == DIE_UNFIXED) { + this.dicePips[i] = this.random.nextInt(6) + 1; + } + } + + if (this.isScoringPipsAvailable()) { + this.playerCanThrowDice = true; + } else { + this.playerCanThrowDice = false; + this.roundPoints = 0; + } + + return null; + } + } + + public boolean isScoringPipsAvailable() { + for(int i = 0; i < DICE_NUMBER; ++i) { + if (this.diceFixed[i] != DIE_FIXED && (this.dicePips[i] == 5 || this.dicePips[i] == 1)) { + return true; + } + } + + return false; + } + + private boolean isAllDiceFixed() { + for(int i = 0; i < DICE_NUMBER; ++i) { + if (this.diceFixed[i] == DIE_UNFIXED) { + return false; + } + } + + return true; + } + + public String checkIfGameCanStart() { + if (this.gameIsRunning) { + return "Das Spiel läuft bereits!"; + } else { + for(int i = 0; i < DEFAULT_PLAYER_NUMBER; ++i) { + if (this.names[i] == null || this.names[i].trim().length() < 2) { + return "Spieler " + (i + 1) + " hat noch keinen Namen!"; + } + } + + return null; + } + } + + public void resetGame() { + this.roundNumber = 0; + this.roundPoints = 0; + this.resetDice(); + this.resetPoints(); + } + + public void finishRound() { + this.resetDice(); + int[] var10000 = this.points; + int var10001 = this.currentPlayer; + var10000[var10001] += this.roundPoints; + this.roundPoints = 0; + this.currentPlayer = ++this.currentPlayer % DEFAULT_PLAYER_NUMBER; + if (this.currentPlayer == 0) { + if (this.roundNumber == this.maxRounds) { + this.gameIsRunning = false; + } else { + ++this.roundNumber; + } + } + + } + + private void resetDice() { + for(int i = 0; i < DICE_NUMBER; ++i) { + this.diceFixed[i] = DIE_UNFIXED; + } + + } + + private void resetPoints() { + for(int i = 0; i < DEFAULT_PLAYER_NUMBER; ++i) { + this.points[i] = 0; + } + + } + + public int getRoundNumber() { + return this.roundNumber; + } + + public int getRoundPoints() { + return this.roundPoints; + } + + public boolean isDieFixed(int dieIndex) { + return this.diceFixed[dieIndex] != DIE_UNFIXED; + } + + public boolean isAtLeastOneDieFixedInCurrentThrow() { + for(int i = 0; i < DICE_NUMBER; ++i) { + if (this.diceFixed[i] == DIE_TEMP_FIXED) { + return true; + } + } + + return false; + } + + private int countTempFixedByPips(int pips) { + int count = 0; + + for(int i = 0; i < DICE_NUMBER; ++i) { + if (this.diceFixed[i] == DIE_TEMP_FIXED && this.dicePips[i] == pips) { + ++count; + } + } + + return count; + } + + public int getDiePips(int dieIndex) { + return this.dicePips[dieIndex]; + } + + public int getMaxRounds() { + return this.maxRounds; + } + + public String setMaxRounds(int maxRounds) { + if (this.gameIsRunning) { + return "Rundenzahl kann nicht während eines Spiels verändert werden!"; + } else { + this.maxRounds = maxRounds; + return null; + } + } + + public int getPoints(int playerIndex) { + return this.points[playerIndex]; + } + + public String getName(int playerIndex) { + return this.names[playerIndex]; + } + + public String setName(int playerIndex, String name) { + if (this.gameIsRunning) { + return "Ein Spielername kann nicht während eines Spiels verändert werden!"; + } else { + this.names[playerIndex] = name; + return null; + } + } + + public boolean isPlayerCanThrowDice() { + return this.playerCanThrowDice; + } + + public boolean isGameIsRunning() { + return this.gameIsRunning; + } + + public int getCurrentPlayer() { + return this.currentPlayer; + } + + @Override + public int changeDiceState(int diceIndex) throws SelectionException { + if (this.diceFixed[diceIndex] == DIE_UNFIXED) { + setDieFixed(diceIndex); + } else { + setDieUnfixed(diceIndex); + } + return roundPoints; + } + + private void setDieFixed(int dieIndex) throws SelectionException { + int c; + if (this.dicePips[dieIndex] == 1) { + c = this.countTempFixedByPips(1); + if (c != 2 && c != 5) { + this.roundPoints += 100; + } else { + this.roundPoints -= 200; + this.roundPoints += 1000; + } + + this.diceFixed[dieIndex] = DIE_TEMP_FIXED; + } else if (this.dicePips[dieIndex] == 5) { + c = this.countTempFixedByPips(5); + if (c != 2 && c != 5) { + this.roundPoints += 50; + } else { + this.roundPoints -= 100; + this.roundPoints += 500; + } + + this.diceFixed[dieIndex] = DIE_TEMP_FIXED; + } else { + throw new SelectionException("Es können nur 1'en und 5'en fixiert werden!"); + } + } + + private void setDieUnfixed(int dieIndex) throws SelectionException { + int c; + if (this.dicePips[dieIndex] == 1) { + c = this.countTempFixedByPips(1); + if (c != 3 && c != 6) { + this.roundPoints -= 100; + } else { + this.roundPoints -= 1000; + this.roundPoints += 200; + } + + this.diceFixed[dieIndex] = DIE_UNFIXED; + } else if (this.dicePips[dieIndex] == 5) { + c = this.countTempFixedByPips(5); + if (c != 3 && c != 6) { + this.roundPoints -= 50; + } else { + this.roundPoints -= 500; + this.roundPoints += 100; + } + + this.diceFixed[dieIndex] = DIE_UNFIXED; + } + } +} diff --git a/dicegame/src/dicegame/logic/SelectionException.java b/dicegame/src/main/java/dicegame/logic/SelectionException.java similarity index 95% rename from dicegame/src/dicegame/logic/SelectionException.java rename to dicegame/src/main/java/dicegame/logic/SelectionException.java index 3497b259..8c6439f0 100644 --- a/dicegame/src/dicegame/logic/SelectionException.java +++ b/dicegame/src/main/java/dicegame/logic/SelectionException.java @@ -1,7 +1,7 @@ -package dicegame.logic; - -public class SelectionException extends Exception { - SelectionException(String msg) { - super(msg); - } -} +package dicegame.logic; + +public class SelectionException extends Exception { + SelectionException(String msg) { + super(msg); + } +} diff --git a/dicegame/src/dicegame/view/GUI.java b/dicegame/src/main/java/dicegame/view/GUI.java similarity index 97% rename from dicegame/src/dicegame/view/GUI.java rename to dicegame/src/main/java/dicegame/view/GUI.java index ec7aeb9b..210cab6e 100644 --- a/dicegame/src/dicegame/view/GUI.java +++ b/dicegame/src/main/java/dicegame/view/GUI.java @@ -1,608 +1,608 @@ -package dicegame.view; - -import dicegame.logic.SelectionException; -import dicegame.logic.Logic; - -import java.awt.BorderLayout; -import java.awt.Color; -import java.awt.Dimension; -import java.awt.FlowLayout; -import java.awt.Font; -import java.awt.GridBagConstraints; -import java.awt.GridBagLayout; -import java.awt.GridLayout; -import java.awt.event.ActionEvent; -import java.awt.event.ActionListener; -import java.awt.event.KeyAdapter; -import java.awt.event.KeyEvent; -import java.util.Random; -import javax.swing.BorderFactory; -import javax.swing.JButton; -import javax.swing.JFrame; -import javax.swing.JLabel; -import javax.swing.JPanel; -import javax.swing.JTextField; -import javax.swing.JToggleButton; -import javax.swing.SwingUtilities; - -public final class GUI extends JFrame implements ActionListener { - private final Logic logic; - private static final long serialVersionUID = 1L; - private JPanel jContentPane = null; - private JPanel panelHead = null; - private JPanel panelMain = null; - private JTextField textfieldS1Name = null; - private JLabel labelS1Name = null; - private JLabel labelS2Name = null; - private JTextField textfieldS2Name = null; - private JPanel panelSpieler1 = null; - private JPanel panelSpieler2 = null; - private JLabel labelS1Points = null; - private JLabel labelS1PointsValue = null; - private JLabel labelS2Points = null; - private JLabel labelS2PointsValue = null; - private JPanel panelGoButton = null; - private JButton buttonGo = null; - private JPanel panelRound = null; - private JLabel labelRound = null; - private JLabel labelRoundValue = null; - private JPanel panelDice = null; - private JToggleButton toggleDie1 = null; - private JToggleButton toggleDie2 = null; - private JToggleButton toggleDie3 = null; - private JToggleButton toggleDie4 = null; - private JToggleButton toggleDie5 = null; - private JToggleButton toggleDie6 = null; - private JPanel panelActions = null; - private JPanel panelRoundPoints = null; - private JLabel labelRoundPoints = null; - private JLabel labelRoundPointsValue = null; - private JPanel panelActionsButtons = null; - private JButton buttonRoll = null; - private JButton buttonReady = null; - private JPanel panelDiceActions = null; - private JPanel panelStatus = null; - private JLabel labelStatus = null; - - private JPanel getPanelHead() { - if (this.panelHead == null) { - BorderLayout borderLayout3 = new BorderLayout(); - borderLayout3.setHgap(3); - borderLayout3.setVgap(3); - this.labelS2Name = new JLabel(); - this.labelS2Name.setText("Spieler 2 :"); - this.labelS2Name.setFont(new Font("Dialog", 0, 12)); - this.labelS2Name.setToolTipText(""); - this.labelS1Name = new JLabel(); - this.labelS1Name.setText("Spieler 1 :"); - this.labelS1Name.setFont(new Font("Dialog", 0, 12)); - this.panelHead = new JPanel(); - this.panelHead.setLayout(borderLayout3); - this.panelHead.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); - this.panelHead.add(this.getPanelSpieler1(), "West"); - this.panelHead.add(this.getPanelSpieler2(), "East"); - this.panelHead.add(this.getPanelGoButton(), "South"); - } - - return this.panelHead; - } - - private JPanel getPanelMain() { - if (this.panelMain == null) { - BorderLayout borderLayout1 = new BorderLayout(); - borderLayout1.setVgap(5); - GridLayout gridLayout3 = new GridLayout(); - gridLayout3.setRows(3); - gridLayout3.setColumns(1); - this.panelMain = new JPanel(); - this.panelMain.setEnabled(true); - this.panelMain.setBorder(BorderFactory.createEtchedBorder(0)); - this.panelMain.setLayout(borderLayout1); - this.panelMain.add(this.getPanelRound(), "North"); - this.panelMain.add(this.getPanelDiceActions(), "Center"); - } - - return this.panelMain; - } - - private JTextField getTextfieldS1Name() { - if (this.textfieldS1Name == null) { - this.textfieldS1Name = new JTextField(); - this.textfieldS1Name.setColumns(10); - this.textfieldS1Name.setName(""); - this.textfieldS1Name.setToolTipText("Name des ersten Spielers, bestehend aus mindestens 2 Zeichen"); - this.textfieldS1Name.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - GUI.this.textfieldS2Name.grabFocus(); - } - }); - this.textfieldS1Name.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { - GUI.this.logic.setName(0, GUI.this.textfieldS1Name.getText()); - String s = GUI.this.logic.checkIfGameCanStart(); - if (s != null) { - GUI.this.labelStatus.setText(s); - GUI.this.buttonGo.setEnabled(false); - } else { - GUI.this.buttonGo.setEnabled(true); - GUI.this.labelStatus.setText(" "); - } - - } - }); - } - - return this.textfieldS1Name; - } - - private JTextField getTextfieldS2Name() { - if (this.textfieldS2Name == null) { - this.textfieldS2Name = new JTextField(); - this.textfieldS2Name.setColumns(10); - this.textfieldS2Name.setName(""); - this.textfieldS2Name.setToolTipText("Name des zweiten Spielers, bestehend aus mindestens 2 Zeichen"); - this.textfieldS2Name.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - GUI.this.buttonGo.grabFocus(); - } - }); - this.textfieldS2Name.addKeyListener(new KeyAdapter() { - public void keyReleased(KeyEvent e) { - GUI.this.logic.setName(1, GUI.this.textfieldS2Name.getText()); - String s = GUI.this.logic.checkIfGameCanStart(); - if (s != null) { - GUI.this.labelStatus.setText(s); - GUI.this.buttonGo.setEnabled(false); - } else { - GUI.this.buttonGo.setEnabled(true); - GUI.this.labelStatus.setText(" "); - } - - } - }); - } - - return this.textfieldS2Name; - } - - private JPanel getPanelSpieler1() { - if (this.panelSpieler1 == null) { - GridLayout gridLayout21 = new GridLayout(); - gridLayout21.setRows(2); - this.labelS1PointsValue = new JLabel(); - this.labelS1PointsValue.setText("0"); - this.labelS1PointsValue.setFont(new Font("Dialog", 1, 14)); - GridLayout gridLayout1 = new GridLayout(); - gridLayout1.setRows(2); - gridLayout1.setColumns(2); - this.labelS1Points = new JLabel(); - this.labelS1Points.setText("Punkte :"); - this.labelS1Points.setFont(new Font("Dialog", 0, 12)); - GridLayout gridLayout = new GridLayout(); - gridLayout.setRows(2); - gridLayout.setColumns(2); - this.panelSpieler1 = new JPanel(); - this.panelSpieler1.setLayout(gridLayout21); - this.panelSpieler1.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - this.panelSpieler1.add(this.labelS1Name, (Object)null); - this.panelSpieler1.add(this.getTextfieldS1Name(), (Object)null); - this.panelSpieler1.add(this.labelS1Points, (Object)null); - this.panelSpieler1.add(this.labelS1PointsValue, (Object)null); - } - - return this.panelSpieler1; - } - - private JPanel getPanelSpieler2() { - if (this.panelSpieler2 == null) { - this.labelS2PointsValue = new JLabel(); - this.labelS2PointsValue.setText("0"); - this.labelS2PointsValue.setFont(new Font("Dialog", 1, 14)); - this.labelS2Points = new JLabel(); - this.labelS2Points.setText("Punkte :"); - this.labelS2Points.setFont(new Font("Dialog", 0, 12)); - GridLayout gridLayout2 = new GridLayout(); - gridLayout2.setRows(2); - gridLayout2.setColumns(2); - this.panelSpieler2 = new JPanel(); - this.panelSpieler2.setLayout(gridLayout2); - this.panelSpieler2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); - this.panelSpieler2.add(this.labelS2Name, (Object)null); - this.panelSpieler2.add(this.getTextfieldS2Name(), (Object)null); - this.panelSpieler2.add(this.labelS2Points, (Object)null); - this.panelSpieler2.add(this.labelS2PointsValue, (Object)null); - } - - return this.panelSpieler2; - } - - private JPanel getPanelGoButton() { - if (this.panelGoButton == null) { - this.panelGoButton = new JPanel(); - this.panelGoButton.setLayout(new GridBagLayout()); - this.panelGoButton.setEnabled(true); - this.panelGoButton.add(this.getButtonGo(), new GridBagConstraints()); - } - - return this.panelGoButton; - } - - private JButton getButtonGo() { - if (this.buttonGo == null) { - this.buttonGo = new JButton(); - this.buttonGo.setName(""); - this.buttonGo.setEnabled(false); - this.buttonGo.setText(" Spiel starten "); - this.buttonGo.addActionListener(this); - } - - return this.buttonGo; - } - - private JPanel getPanelRound() { - if (this.panelRound == null) { - this.labelRoundValue = new JLabel(); - this.labelRoundValue.setText("0"); - this.labelRoundValue.setFont(new Font("Dialog", 0, 12)); - this.labelRound = new JLabel(); - this.labelRound.setText("Runde "); - this.labelRound.setFont(new Font("Dialog", 0, 12)); - this.panelRound = new JPanel(); - this.panelRound.setLayout(new FlowLayout()); - this.panelRound.add(this.labelRound, (Object)null); - this.panelRound.add(this.labelRoundValue, (Object)null); - } - - return this.panelRound; - } - - private JPanel getPanelDice() { - if (this.panelDice == null) { - GridLayout gridLayout5 = new GridLayout(); - gridLayout5.setRows(1); - gridLayout5.setHgap(20); - gridLayout5.setVgap(1); - gridLayout5.setColumns(6); - this.panelDice = new JPanel(); - this.panelDice.setPreferredSize(new Dimension(346, 26)); - this.panelDice.setBorder(BorderFactory.createEmptyBorder(5, 3, 5, 0)); - this.panelDice.setLayout(gridLayout5); - this.panelDice.add(this.getToggleDie1(), (Object)null); - this.panelDice.add(this.getToggleDie2(), (Object)null); - this.panelDice.add(this.getToggleDie3(), (Object)null); - this.panelDice.add(this.getToggleDie4(), (Object)null); - this.panelDice.add(this.getToggleDie5(), (Object)null); - this.panelDice.add(this.getToggleDie6(), (Object)null); - } - - return this.panelDice; - } - - private JToggleButton getToggleDie1() { - if (this.toggleDie1 == null) { - this.toggleDie1 = new JToggleButton(); - this.toggleDie1.setText("1"); - this.toggleDie1.setEnabled(false); - this.toggleDie1.addActionListener(this); - } - - return this.toggleDie1; - } - - private JToggleButton getToggleDie2() { - if (this.toggleDie2 == null) { - this.toggleDie2 = new JToggleButton(); - this.toggleDie2.setText("2"); - this.toggleDie2.setEnabled(false); - this.toggleDie2.addActionListener(this); - } - - return this.toggleDie2; - } - - private JToggleButton getToggleDie3() { - if (this.toggleDie3 == null) { - this.toggleDie3 = new JToggleButton(); - this.toggleDie3.setText("3"); - this.toggleDie3.setEnabled(false); - this.toggleDie3.addActionListener(this); - } - - return this.toggleDie3; - } - - private JToggleButton getToggleDie4() { - if (this.toggleDie4 == null) { - this.toggleDie4 = new JToggleButton(); - this.toggleDie4.setText("4"); - this.toggleDie4.setEnabled(false); - this.toggleDie4.addActionListener(this); - } - - return this.toggleDie4; - } - - private JToggleButton getToggleDie5() { - if (this.toggleDie5 == null) { - this.toggleDie5 = new JToggleButton(); - this.toggleDie5.setText("5"); - this.toggleDie5.setEnabled(false); - this.toggleDie5.addActionListener(this); - } - - return this.toggleDie5; - } - - private JToggleButton getToggleDie6() { - if (this.toggleDie6 == null) { - this.toggleDie6 = new JToggleButton(); - this.toggleDie6.setText("6"); - this.toggleDie6.setEnabled(false); - this.toggleDie6.addActionListener(this); - } - - return this.toggleDie6; - } - - private JPanel getPanelActions() { - if (this.panelActions == null) { - BorderLayout borderLayout2 = new BorderLayout(); - borderLayout2.setVgap(0); - borderLayout2.setHgap(0); - this.panelActions = new JPanel(); - this.panelActions.setLayout(borderLayout2); - this.panelActions.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); - this.panelActions.add(this.getPanelRoundPoints(), "West"); - this.panelActions.add(this.getPanelActionsButtons(), "East"); - } - - return this.panelActions; - } - - private JPanel getPanelRoundPoints() { - if (this.panelRoundPoints == null) { - this.labelRoundPointsValue = new JLabel(); - this.labelRoundPointsValue.setText("0"); - this.labelRoundPoints = new JLabel(); - this.labelRoundPoints.setText("Punkte des aktuellen Zuges : "); - this.labelRoundPoints.setFont(new Font("Dialog", 0, 12)); - this.panelRoundPoints = new JPanel(); - this.panelRoundPoints.setLayout(new GridBagLayout()); - this.panelRoundPoints.add(this.labelRoundPoints, new GridBagConstraints()); - this.panelRoundPoints.add(this.labelRoundPointsValue, new GridBagConstraints()); - } - - return this.panelRoundPoints; - } - - private JPanel getPanelActionsButtons() { - if (this.panelActionsButtons == null) { - GridLayout gridLayout6 = new GridLayout(); - gridLayout6.setRows(2); - gridLayout6.setHgap(0); - gridLayout6.setVgap(6); - gridLayout6.setColumns(1); - this.panelActionsButtons = new JPanel(); - this.panelActionsButtons.setLayout(gridLayout6); - this.panelActionsButtons.add(this.getButtonRoll(), (Object)null); - this.panelActionsButtons.add(this.getButtonReady(), (Object)null); - } - - return this.panelActionsButtons; - } - - private JButton getButtonRoll() { - if (this.buttonRoll == null) { - this.buttonRoll = new JButton(); - this.buttonRoll.setText("Würfeln"); - this.buttonRoll.setEnabled(false); - this.buttonRoll.addActionListener(this); - } - - return this.buttonRoll; - } - - private JButton getButtonReady() { - if (this.buttonReady == null) { - this.buttonReady = new JButton(); - this.buttonReady.setText("Zug beenden"); - this.buttonReady.setEnabled(false); - this.buttonReady.addActionListener(this); - } - - return this.buttonReady; - } - - private JPanel getPanelDiceActions() { - if (this.panelDiceActions == null) { - BorderLayout borderLayout = new BorderLayout(); - borderLayout.setHgap(5); - borderLayout.setVgap(5); - this.panelDiceActions = new JPanel(); - this.panelDiceActions.setLayout(borderLayout); - this.panelDiceActions.add(this.getPanelDice(), "Center"); - this.panelDiceActions.add(this.getPanelActions(), "South"); - } - - return this.panelDiceActions; - } - - private JPanel getPanelStatus() { - if (this.panelStatus == null) { - this.labelStatus = new JLabel(); - this.labelStatus.setText(" "); - this.labelStatus.setToolTipText(""); - this.labelStatus.setFont(new Font("Arial", 0, 12)); - this.panelStatus = new JPanel(); - this.panelStatus.setLayout(new BorderLayout()); - this.panelStatus.setBorder(BorderFactory.createBevelBorder(1)); - this.panelStatus.add(this.labelStatus, "North"); - } - - return this.panelStatus; - } - - public GUI() { - this.initialize(); - this.logic = new Logic(new Random()); - this.logic.resetGame(); - } - - private void initialize() { - this.setSize(478, 311); - this.setResizable(false); - this.setDefaultCloseOperation(3); - this.setName("mainFrame"); - this.setContentPane(this.getJContentPane()); - this.setTitle("Dings"); - } - - private JPanel getJContentPane() { - if (this.jContentPane == null) { - BorderLayout borderLayout4 = new BorderLayout(); - borderLayout4.setHgap(3); - borderLayout4.setVgap(2); - this.jContentPane = new JPanel(); - this.jContentPane.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2)); - this.jContentPane.setLayout(borderLayout4); - this.jContentPane.add(this.getPanelHead(), "North"); - this.jContentPane.add(this.getPanelMain(), "Center"); - this.jContentPane.add(this.getPanelStatus(), "South"); - } - - return this.jContentPane; - } - - public void actionPerformed(ActionEvent e) { - Object source = e.getSource(); - if (source != this.textfieldS1Name && source != this.textfieldS2Name) { - if (source == this.buttonGo) { - this.logic.startGame(); - this.labelStatus.setText(" "); - this.buttonGo.setEnabled(false); - this.textfieldS1Name.setEditable(false); - this.textfieldS2Name.setEditable(false); - this.buttonReady.setEnabled(true); - this.labelS2PointsValue.setText(String.valueOf(this.logic.getPoints(1))); - this.labelS1PointsValue.setText(String.valueOf(this.logic.getPoints(0))); - this.syncRoundInfoToGui(); - this.logic.rollDice(); - this.syncLogicDiceToGui(); - this.toggleDie1.setEnabled(true); - this.toggleDie2.setEnabled(true); - this.toggleDie3.setEnabled(true); - this.toggleDie4.setEnabled(true); - this.toggleDie5.setEnabled(true); - this.toggleDie6.setEnabled(true); - } else if (source == this.buttonReady) { - this.logic.finishRound(); - this.syncRoundInfoToGui(); - if (this.logic.isGameIsRunning()) { - this.logic.rollDice(); - this.syncLogicDiceToGui(); - } - } else if (source == this.buttonRoll) { - if (!this.logic.isAtLeastOneDieFixedInCurrentThrow()) { - this.labelStatus.setText("Wenigstens ein Würfel muss fixiert sein."); - } else { - String s = this.logic.rollDice(); - if (s != null) { - this.labelStatus.setText(s); - } else { - this.syncLogicDiceToGui(); - } - } - } else if (source == this.toggleDie1) { - this.toggleDie(this.toggleDie1, 0); - } else if (source == this.toggleDie2) { - this.toggleDie(this.toggleDie2, 1); - } else if (source == this.toggleDie3) { - this.toggleDie(this.toggleDie3, 2); - } else if (source == this.toggleDie4) { - this.toggleDie(this.toggleDie4, 3); - } else if (source == this.toggleDie5) { - this.toggleDie(this.toggleDie5, 4); - } else if (source == this.toggleDie6) { - this.toggleDie(this.toggleDie6, 5); - } - } - - } - - private void toggleDie(JToggleButton die, int dieIndex) { - String result = null; - this.labelStatus.setText(" "); - try { - int resultingPoints = this.logic.changeDiceState(dieIndex); - this.labelRoundPointsValue.setText(String.valueOf(resultingPoints)); - } catch (SelectionException e) { - die.setSelected(!die.isSelected()); - this.labelStatus.setText(e.getMessage()); - } - } - - private void syncRoundInfoToGui() { - if (this.logic.isGameIsRunning()) { - this.labelRoundValue.setText(String.valueOf(this.logic.getRoundNumber())); - this.labelRoundPointsValue.setText(String.valueOf(this.logic.getRoundPoints())); - if (this.logic.getCurrentPlayer() == 0) { - this.labelS1Name.setForeground(Color.GREEN); - this.labelS2Name.setForeground(Color.BLACK); - this.labelS2PointsValue.setText(String.valueOf(this.logic.getPoints(1))); - } else { - this.labelS2Name.setForeground(Color.GREEN); - this.labelS1Name.setForeground(Color.BLACK); - this.labelS1PointsValue.setText(String.valueOf(this.logic.getPoints(0))); - } - } else { - this.labelS2Name.setForeground(Color.BLACK); - this.labelS1Name.setForeground(Color.BLACK); - this.textfieldS1Name.setEditable(true); - this.textfieldS2Name.setEditable(true); - this.labelStatus.setText("Das Spiel ist beendet!"); - this.buttonReady.setEnabled(false); - this.buttonRoll.setEnabled(false); - this.buttonGo.setEnabled(true); - this.toggleDie1.setEnabled(false); - this.toggleDie2.setEnabled(false); - this.toggleDie3.setEnabled(false); - this.toggleDie4.setEnabled(false); - this.toggleDie5.setEnabled(false); - this.toggleDie6.setEnabled(false); - } - - } - - private void syncLogicDiceToGui() { - this.syncLogicDieToGui(this.toggleDie1, 0); - this.syncLogicDieToGui(this.toggleDie2, 1); - this.syncLogicDieToGui(this.toggleDie3, 2); - this.syncLogicDieToGui(this.toggleDie4, 3); - this.syncLogicDieToGui(this.toggleDie5, 4); - this.syncLogicDieToGui(this.toggleDie6, 5); - this.buttonRoll.setEnabled(this.logic.isPlayerCanThrowDice()); - this.labelRoundPointsValue.setText(String.valueOf(this.logic.getRoundPoints())); - } - - private void syncLogicDieToGui(JToggleButton die, int dieIndex) { - die.setText(String.valueOf(this.logic.getDiePips(dieIndex))); - if (this.logic.isDieFixed(dieIndex)) { - die.setForeground(Color.BLUE); - die.setSelected(true); - } else { - die.setForeground(Color.BLACK); - die.setSelected(false); - } - - } - - public static void main(String[] args) { - SwingUtilities.invokeLater(new Runnable() { - public void run() { - GUI thisClass = new GUI(); - thisClass.setDefaultCloseOperation(3); - thisClass.setVisible(true); - } - }); - } -} +package dicegame.view; + +import dicegame.logic.SelectionException; +import dicegame.logic.Logic; + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Font; +import java.awt.GridBagConstraints; +import java.awt.GridBagLayout; +import java.awt.GridLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyAdapter; +import java.awt.event.KeyEvent; +import java.util.Random; +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.JToggleButton; +import javax.swing.SwingUtilities; + +public final class GUI extends JFrame implements ActionListener { + private final Logic logic; + private static final long serialVersionUID = 1L; + private JPanel jContentPane = null; + private JPanel panelHead = null; + private JPanel panelMain = null; + private JTextField textfieldS1Name = null; + private JLabel labelS1Name = null; + private JLabel labelS2Name = null; + private JTextField textfieldS2Name = null; + private JPanel panelSpieler1 = null; + private JPanel panelSpieler2 = null; + private JLabel labelS1Points = null; + private JLabel labelS1PointsValue = null; + private JLabel labelS2Points = null; + private JLabel labelS2PointsValue = null; + private JPanel panelGoButton = null; + private JButton buttonGo = null; + private JPanel panelRound = null; + private JLabel labelRound = null; + private JLabel labelRoundValue = null; + private JPanel panelDice = null; + private JToggleButton toggleDie1 = null; + private JToggleButton toggleDie2 = null; + private JToggleButton toggleDie3 = null; + private JToggleButton toggleDie4 = null; + private JToggleButton toggleDie5 = null; + private JToggleButton toggleDie6 = null; + private JPanel panelActions = null; + private JPanel panelRoundPoints = null; + private JLabel labelRoundPoints = null; + private JLabel labelRoundPointsValue = null; + private JPanel panelActionsButtons = null; + private JButton buttonRoll = null; + private JButton buttonReady = null; + private JPanel panelDiceActions = null; + private JPanel panelStatus = null; + private JLabel labelStatus = null; + + private JPanel getPanelHead() { + if (this.panelHead == null) { + BorderLayout borderLayout3 = new BorderLayout(); + borderLayout3.setHgap(3); + borderLayout3.setVgap(3); + this.labelS2Name = new JLabel(); + this.labelS2Name.setText("Spieler 2 :"); + this.labelS2Name.setFont(new Font("Dialog", 0, 12)); + this.labelS2Name.setToolTipText(""); + this.labelS1Name = new JLabel(); + this.labelS1Name.setText("Spieler 1 :"); + this.labelS1Name.setFont(new Font("Dialog", 0, 12)); + this.panelHead = new JPanel(); + this.panelHead.setLayout(borderLayout3); + this.panelHead.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0)); + this.panelHead.add(this.getPanelSpieler1(), "West"); + this.panelHead.add(this.getPanelSpieler2(), "East"); + this.panelHead.add(this.getPanelGoButton(), "South"); + } + + return this.panelHead; + } + + private JPanel getPanelMain() { + if (this.panelMain == null) { + BorderLayout borderLayout1 = new BorderLayout(); + borderLayout1.setVgap(5); + GridLayout gridLayout3 = new GridLayout(); + gridLayout3.setRows(3); + gridLayout3.setColumns(1); + this.panelMain = new JPanel(); + this.panelMain.setEnabled(true); + this.panelMain.setBorder(BorderFactory.createEtchedBorder(0)); + this.panelMain.setLayout(borderLayout1); + this.panelMain.add(this.getPanelRound(), "North"); + this.panelMain.add(this.getPanelDiceActions(), "Center"); + } + + return this.panelMain; + } + + private JTextField getTextfieldS1Name() { + if (this.textfieldS1Name == null) { + this.textfieldS1Name = new JTextField(); + this.textfieldS1Name.setColumns(10); + this.textfieldS1Name.setName(""); + this.textfieldS1Name.setToolTipText("Name des ersten Spielers, bestehend aus mindestens 2 Zeichen"); + this.textfieldS1Name.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + GUI.this.textfieldS2Name.grabFocus(); + } + }); + this.textfieldS1Name.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + GUI.this.logic.setName(0, GUI.this.textfieldS1Name.getText()); + String s = GUI.this.logic.checkIfGameCanStart(); + if (s != null) { + GUI.this.labelStatus.setText(s); + GUI.this.buttonGo.setEnabled(false); + } else { + GUI.this.buttonGo.setEnabled(true); + GUI.this.labelStatus.setText(" "); + } + + } + }); + } + + return this.textfieldS1Name; + } + + private JTextField getTextfieldS2Name() { + if (this.textfieldS2Name == null) { + this.textfieldS2Name = new JTextField(); + this.textfieldS2Name.setColumns(10); + this.textfieldS2Name.setName(""); + this.textfieldS2Name.setToolTipText("Name des zweiten Spielers, bestehend aus mindestens 2 Zeichen"); + this.textfieldS2Name.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + GUI.this.buttonGo.grabFocus(); + } + }); + this.textfieldS2Name.addKeyListener(new KeyAdapter() { + public void keyReleased(KeyEvent e) { + GUI.this.logic.setName(1, GUI.this.textfieldS2Name.getText()); + String s = GUI.this.logic.checkIfGameCanStart(); + if (s != null) { + GUI.this.labelStatus.setText(s); + GUI.this.buttonGo.setEnabled(false); + } else { + GUI.this.buttonGo.setEnabled(true); + GUI.this.labelStatus.setText(" "); + } + + } + }); + } + + return this.textfieldS2Name; + } + + private JPanel getPanelSpieler1() { + if (this.panelSpieler1 == null) { + GridLayout gridLayout21 = new GridLayout(); + gridLayout21.setRows(2); + this.labelS1PointsValue = new JLabel(); + this.labelS1PointsValue.setText("0"); + this.labelS1PointsValue.setFont(new Font("Dialog", 1, 14)); + GridLayout gridLayout1 = new GridLayout(); + gridLayout1.setRows(2); + gridLayout1.setColumns(2); + this.labelS1Points = new JLabel(); + this.labelS1Points.setText("Punkte :"); + this.labelS1Points.setFont(new Font("Dialog", 0, 12)); + GridLayout gridLayout = new GridLayout(); + gridLayout.setRows(2); + gridLayout.setColumns(2); + this.panelSpieler1 = new JPanel(); + this.panelSpieler1.setLayout(gridLayout21); + this.panelSpieler1.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + this.panelSpieler1.add(this.labelS1Name, (Object)null); + this.panelSpieler1.add(this.getTextfieldS1Name(), (Object)null); + this.panelSpieler1.add(this.labelS1Points, (Object)null); + this.panelSpieler1.add(this.labelS1PointsValue, (Object)null); + } + + return this.panelSpieler1; + } + + private JPanel getPanelSpieler2() { + if (this.panelSpieler2 == null) { + this.labelS2PointsValue = new JLabel(); + this.labelS2PointsValue.setText("0"); + this.labelS2PointsValue.setFont(new Font("Dialog", 1, 14)); + this.labelS2Points = new JLabel(); + this.labelS2Points.setText("Punkte :"); + this.labelS2Points.setFont(new Font("Dialog", 0, 12)); + GridLayout gridLayout2 = new GridLayout(); + gridLayout2.setRows(2); + gridLayout2.setColumns(2); + this.panelSpieler2 = new JPanel(); + this.panelSpieler2.setLayout(gridLayout2); + this.panelSpieler2.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0)); + this.panelSpieler2.add(this.labelS2Name, (Object)null); + this.panelSpieler2.add(this.getTextfieldS2Name(), (Object)null); + this.panelSpieler2.add(this.labelS2Points, (Object)null); + this.panelSpieler2.add(this.labelS2PointsValue, (Object)null); + } + + return this.panelSpieler2; + } + + private JPanel getPanelGoButton() { + if (this.panelGoButton == null) { + this.panelGoButton = new JPanel(); + this.panelGoButton.setLayout(new GridBagLayout()); + this.panelGoButton.setEnabled(true); + this.panelGoButton.add(this.getButtonGo(), new GridBagConstraints()); + } + + return this.panelGoButton; + } + + private JButton getButtonGo() { + if (this.buttonGo == null) { + this.buttonGo = new JButton(); + this.buttonGo.setName(""); + this.buttonGo.setEnabled(false); + this.buttonGo.setText(" Spiel starten "); + this.buttonGo.addActionListener(this); + } + + return this.buttonGo; + } + + private JPanel getPanelRound() { + if (this.panelRound == null) { + this.labelRoundValue = new JLabel(); + this.labelRoundValue.setText("0"); + this.labelRoundValue.setFont(new Font("Dialog", 0, 12)); + this.labelRound = new JLabel(); + this.labelRound.setText("Runde "); + this.labelRound.setFont(new Font("Dialog", 0, 12)); + this.panelRound = new JPanel(); + this.panelRound.setLayout(new FlowLayout()); + this.panelRound.add(this.labelRound, (Object)null); + this.panelRound.add(this.labelRoundValue, (Object)null); + } + + return this.panelRound; + } + + private JPanel getPanelDice() { + if (this.panelDice == null) { + GridLayout gridLayout5 = new GridLayout(); + gridLayout5.setRows(1); + gridLayout5.setHgap(20); + gridLayout5.setVgap(1); + gridLayout5.setColumns(6); + this.panelDice = new JPanel(); + this.panelDice.setPreferredSize(new Dimension(346, 26)); + this.panelDice.setBorder(BorderFactory.createEmptyBorder(5, 3, 5, 0)); + this.panelDice.setLayout(gridLayout5); + this.panelDice.add(this.getToggleDie1(), (Object)null); + this.panelDice.add(this.getToggleDie2(), (Object)null); + this.panelDice.add(this.getToggleDie3(), (Object)null); + this.panelDice.add(this.getToggleDie4(), (Object)null); + this.panelDice.add(this.getToggleDie5(), (Object)null); + this.panelDice.add(this.getToggleDie6(), (Object)null); + } + + return this.panelDice; + } + + private JToggleButton getToggleDie1() { + if (this.toggleDie1 == null) { + this.toggleDie1 = new JToggleButton(); + this.toggleDie1.setText("1"); + this.toggleDie1.setEnabled(false); + this.toggleDie1.addActionListener(this); + } + + return this.toggleDie1; + } + + private JToggleButton getToggleDie2() { + if (this.toggleDie2 == null) { + this.toggleDie2 = new JToggleButton(); + this.toggleDie2.setText("2"); + this.toggleDie2.setEnabled(false); + this.toggleDie2.addActionListener(this); + } + + return this.toggleDie2; + } + + private JToggleButton getToggleDie3() { + if (this.toggleDie3 == null) { + this.toggleDie3 = new JToggleButton(); + this.toggleDie3.setText("3"); + this.toggleDie3.setEnabled(false); + this.toggleDie3.addActionListener(this); + } + + return this.toggleDie3; + } + + private JToggleButton getToggleDie4() { + if (this.toggleDie4 == null) { + this.toggleDie4 = new JToggleButton(); + this.toggleDie4.setText("4"); + this.toggleDie4.setEnabled(false); + this.toggleDie4.addActionListener(this); + } + + return this.toggleDie4; + } + + private JToggleButton getToggleDie5() { + if (this.toggleDie5 == null) { + this.toggleDie5 = new JToggleButton(); + this.toggleDie5.setText("5"); + this.toggleDie5.setEnabled(false); + this.toggleDie5.addActionListener(this); + } + + return this.toggleDie5; + } + + private JToggleButton getToggleDie6() { + if (this.toggleDie6 == null) { + this.toggleDie6 = new JToggleButton(); + this.toggleDie6.setText("6"); + this.toggleDie6.setEnabled(false); + this.toggleDie6.addActionListener(this); + } + + return this.toggleDie6; + } + + private JPanel getPanelActions() { + if (this.panelActions == null) { + BorderLayout borderLayout2 = new BorderLayout(); + borderLayout2.setVgap(0); + borderLayout2.setHgap(0); + this.panelActions = new JPanel(); + this.panelActions.setLayout(borderLayout2); + this.panelActions.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5)); + this.panelActions.add(this.getPanelRoundPoints(), "West"); + this.panelActions.add(this.getPanelActionsButtons(), "East"); + } + + return this.panelActions; + } + + private JPanel getPanelRoundPoints() { + if (this.panelRoundPoints == null) { + this.labelRoundPointsValue = new JLabel(); + this.labelRoundPointsValue.setText("0"); + this.labelRoundPoints = new JLabel(); + this.labelRoundPoints.setText("Punkte des aktuellen Zuges : "); + this.labelRoundPoints.setFont(new Font("Dialog", 0, 12)); + this.panelRoundPoints = new JPanel(); + this.panelRoundPoints.setLayout(new GridBagLayout()); + this.panelRoundPoints.add(this.labelRoundPoints, new GridBagConstraints()); + this.panelRoundPoints.add(this.labelRoundPointsValue, new GridBagConstraints()); + } + + return this.panelRoundPoints; + } + + private JPanel getPanelActionsButtons() { + if (this.panelActionsButtons == null) { + GridLayout gridLayout6 = new GridLayout(); + gridLayout6.setRows(2); + gridLayout6.setHgap(0); + gridLayout6.setVgap(6); + gridLayout6.setColumns(1); + this.panelActionsButtons = new JPanel(); + this.panelActionsButtons.setLayout(gridLayout6); + this.panelActionsButtons.add(this.getButtonRoll(), (Object)null); + this.panelActionsButtons.add(this.getButtonReady(), (Object)null); + } + + return this.panelActionsButtons; + } + + private JButton getButtonRoll() { + if (this.buttonRoll == null) { + this.buttonRoll = new JButton(); + this.buttonRoll.setText("Würfeln"); + this.buttonRoll.setEnabled(false); + this.buttonRoll.addActionListener(this); + } + + return this.buttonRoll; + } + + private JButton getButtonReady() { + if (this.buttonReady == null) { + this.buttonReady = new JButton(); + this.buttonReady.setText("Zug beenden"); + this.buttonReady.setEnabled(false); + this.buttonReady.addActionListener(this); + } + + return this.buttonReady; + } + + private JPanel getPanelDiceActions() { + if (this.panelDiceActions == null) { + BorderLayout borderLayout = new BorderLayout(); + borderLayout.setHgap(5); + borderLayout.setVgap(5); + this.panelDiceActions = new JPanel(); + this.panelDiceActions.setLayout(borderLayout); + this.panelDiceActions.add(this.getPanelDice(), "Center"); + this.panelDiceActions.add(this.getPanelActions(), "South"); + } + + return this.panelDiceActions; + } + + private JPanel getPanelStatus() { + if (this.panelStatus == null) { + this.labelStatus = new JLabel(); + this.labelStatus.setText(" "); + this.labelStatus.setToolTipText(""); + this.labelStatus.setFont(new Font("Arial", 0, 12)); + this.panelStatus = new JPanel(); + this.panelStatus.setLayout(new BorderLayout()); + this.panelStatus.setBorder(BorderFactory.createBevelBorder(1)); + this.panelStatus.add(this.labelStatus, "North"); + } + + return this.panelStatus; + } + + public GUI() { + this.initialize(); + this.logic = new Logic(new Random()); + this.logic.resetGame(); + } + + private void initialize() { + this.setSize(478, 311); + this.setResizable(false); + this.setDefaultCloseOperation(3); + this.setName("mainFrame"); + this.setContentPane(this.getJContentPane()); + this.setTitle("Dings"); + } + + private JPanel getJContentPane() { + if (this.jContentPane == null) { + BorderLayout borderLayout4 = new BorderLayout(); + borderLayout4.setHgap(3); + borderLayout4.setVgap(2); + this.jContentPane = new JPanel(); + this.jContentPane.setBorder(BorderFactory.createEmptyBorder(0, 2, 0, 2)); + this.jContentPane.setLayout(borderLayout4); + this.jContentPane.add(this.getPanelHead(), "North"); + this.jContentPane.add(this.getPanelMain(), "Center"); + this.jContentPane.add(this.getPanelStatus(), "South"); + } + + return this.jContentPane; + } + + public void actionPerformed(ActionEvent e) { + Object source = e.getSource(); + if (source != this.textfieldS1Name && source != this.textfieldS2Name) { + if (source == this.buttonGo) { + this.logic.startGame(); + this.labelStatus.setText(" "); + this.buttonGo.setEnabled(false); + this.textfieldS1Name.setEditable(false); + this.textfieldS2Name.setEditable(false); + this.buttonReady.setEnabled(true); + this.labelS2PointsValue.setText(String.valueOf(this.logic.getPoints(1))); + this.labelS1PointsValue.setText(String.valueOf(this.logic.getPoints(0))); + this.syncRoundInfoToGui(); + this.logic.rollDice(); + this.syncLogicDiceToGui(); + this.toggleDie1.setEnabled(true); + this.toggleDie2.setEnabled(true); + this.toggleDie3.setEnabled(true); + this.toggleDie4.setEnabled(true); + this.toggleDie5.setEnabled(true); + this.toggleDie6.setEnabled(true); + } else if (source == this.buttonReady) { + this.logic.finishRound(); + this.syncRoundInfoToGui(); + if (this.logic.isGameIsRunning()) { + this.logic.rollDice(); + this.syncLogicDiceToGui(); + } + } else if (source == this.buttonRoll) { + if (!this.logic.isAtLeastOneDieFixedInCurrentThrow()) { + this.labelStatus.setText("Wenigstens ein Würfel muss fixiert sein."); + } else { + String s = this.logic.rollDice(); + if (s != null) { + this.labelStatus.setText(s); + } else { + this.syncLogicDiceToGui(); + } + } + } else if (source == this.toggleDie1) { + this.toggleDie(this.toggleDie1, 0); + } else if (source == this.toggleDie2) { + this.toggleDie(this.toggleDie2, 1); + } else if (source == this.toggleDie3) { + this.toggleDie(this.toggleDie3, 2); + } else if (source == this.toggleDie4) { + this.toggleDie(this.toggleDie4, 3); + } else if (source == this.toggleDie5) { + this.toggleDie(this.toggleDie5, 4); + } else if (source == this.toggleDie6) { + this.toggleDie(this.toggleDie6, 5); + } + } + + } + + private void toggleDie(JToggleButton die, int dieIndex) { + String result = null; + this.labelStatus.setText(" "); + try { + int resultingPoints = this.logic.changeDiceState(dieIndex); + this.labelRoundPointsValue.setText(String.valueOf(resultingPoints)); + } catch (SelectionException e) { + die.setSelected(!die.isSelected()); + this.labelStatus.setText(e.getMessage()); + } + } + + private void syncRoundInfoToGui() { + if (this.logic.isGameIsRunning()) { + this.labelRoundValue.setText(String.valueOf(this.logic.getRoundNumber())); + this.labelRoundPointsValue.setText(String.valueOf(this.logic.getRoundPoints())); + if (this.logic.getCurrentPlayer() == 0) { + this.labelS1Name.setForeground(Color.GREEN); + this.labelS2Name.setForeground(Color.BLACK); + this.labelS2PointsValue.setText(String.valueOf(this.logic.getPoints(1))); + } else { + this.labelS2Name.setForeground(Color.GREEN); + this.labelS1Name.setForeground(Color.BLACK); + this.labelS1PointsValue.setText(String.valueOf(this.logic.getPoints(0))); + } + } else { + this.labelS2Name.setForeground(Color.BLACK); + this.labelS1Name.setForeground(Color.BLACK); + this.textfieldS1Name.setEditable(true); + this.textfieldS2Name.setEditable(true); + this.labelStatus.setText("Das Spiel ist beendet!"); + this.buttonReady.setEnabled(false); + this.buttonRoll.setEnabled(false); + this.buttonGo.setEnabled(true); + this.toggleDie1.setEnabled(false); + this.toggleDie2.setEnabled(false); + this.toggleDie3.setEnabled(false); + this.toggleDie4.setEnabled(false); + this.toggleDie5.setEnabled(false); + this.toggleDie6.setEnabled(false); + } + + } + + private void syncLogicDiceToGui() { + this.syncLogicDieToGui(this.toggleDie1, 0); + this.syncLogicDieToGui(this.toggleDie2, 1); + this.syncLogicDieToGui(this.toggleDie3, 2); + this.syncLogicDieToGui(this.toggleDie4, 3); + this.syncLogicDieToGui(this.toggleDie5, 4); + this.syncLogicDieToGui(this.toggleDie6, 5); + this.buttonRoll.setEnabled(this.logic.isPlayerCanThrowDice()); + this.labelRoundPointsValue.setText(String.valueOf(this.logic.getRoundPoints())); + } + + private void syncLogicDieToGui(JToggleButton die, int dieIndex) { + die.setText(String.valueOf(this.logic.getDiePips(dieIndex))); + if (this.logic.isDieFixed(dieIndex)) { + die.setForeground(Color.BLUE); + die.setSelected(true); + } else { + die.setForeground(Color.BLACK); + die.setSelected(false); + } + + } + + public static void main(String[] args) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + GUI thisClass = new GUI(); + thisClass.setDefaultCloseOperation(3); + thisClass.setVisible(true); + } + }); + } +} diff --git a/dicegame/src/test/java/dicegame/logic/ChangeDiceStateTest.java b/dicegame/src/test/java/dicegame/logic/ChangeDiceStateTest.java new file mode 100644 index 00000000..31a9df66 --- /dev/null +++ b/dicegame/src/test/java/dicegame/logic/ChangeDiceStateTest.java @@ -0,0 +1,142 @@ +package dicegame.logic; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +import java.util.Random; + +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ChangeDiceStateTest { + /** + * All dices are set to the given value. + */ + Logic getLogicWithAllDiceAt(int value) { + // https://javadoc.io/doc/org.mockito/mockito-core/latest/org/mockito/Mockito.html#verification + Random r = mock(Random.class); + // Logic will add 1 to this value, thus we subtract 1. + when(r.nextInt(6)).thenReturn(value - 1); + + Logic l = new Logic(r); + l.startGame(); + assertNull(l.rollDice()); + return l; + } + + // K1 a + @ParameterizedTest + @CsvSource({ + "-1", + "-2" + }) + void negativeIndex(int index) { + Logic logic = getLogicWithAllDiceAt(3); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> logic.changeDiceState(index)); + } + + // K1 b + @ParameterizedTest + @CsvSource({ + "0", + "1", + "2", + "3", + "4", + "5" + }) + void validIndex(int index) throws SelectionException { + Logic logic = getLogicWithAllDiceAt(1); + logic.changeDiceState(index); + } + + // K1 c + @ParameterizedTest + @CsvSource({ + "6", + "7" + }) + void indexGreaterThan5(int index) { + Logic logic = getLogicWithAllDiceAt(3); + assertThrows(ArrayIndexOutOfBoundsException.class, () -> logic.changeDiceState(index)); + } + + + // K2 a+b + @ParameterizedTest + @CsvSource({ + "1", + "5" + }) + void canFix(int value) throws SelectionException { + Logic logic = getLogicWithAllDiceAt(value); + logic.changeDiceState(0); + } + // K2 c + @ParameterizedTest + @CsvSource({ + "0,2", + "1,2", + "2,2", + "3,3", + "4,3", + "5,3", + "0,4", + "1,4", + "2,4", + "3,6", + "4,6", + "5,6", + }) + void cantFix(int index, int value) { + Logic logic = getLogicWithAllDiceAt(value); + assertThrows(SelectionException.class, () -> logic.changeDiceState(index)); + } + + // K3 a + @ParameterizedTest + @CsvSource({ + "1", + "5" + }) + void cantFixAgainAfterRoll(int value) throws SelectionException { + Logic logic = getLogicWithAllDiceAt(value); + logic.changeDiceState(0); + + assertTrue(logic.isDieFixed(0)); + logic.rollDice(); + // This assertion fails due to the implementation not fulfilling the specification. + // If the client fixes a dice and then rolls the dice again, an exception should be thrown if they try to unfix the dice afterward. + assertThrows(SelectionException.class, () -> logic.changeDiceState(0)); + } + + // K3 b + @ParameterizedTest + @CsvSource({ + "1", + "5" + }) + void unfix(int value) throws SelectionException { + Logic logic = getLogicWithAllDiceAt(value); + logic.changeDiceState(0); + + assertTrue(logic.isDieFixed(0)); + logic.changeDiceState(0); + assertFalse(logic.isDieFixed(0)); + } + + // K3 c + @ParameterizedTest + @CsvSource({ + "1", + "5" + }) + void fix(int value) throws SelectionException { + Logic logic = getLogicWithAllDiceAt(value); + + assertFalse(logic.isDieFixed(0)); + logic.changeDiceState(0); + assertTrue(logic.isDieFixed(0)); + } +} diff --git a/dicegame/src/test/java/dicegame/logic/LogicTest.java b/dicegame/src/test/java/dicegame/logic/LogicTest.java new file mode 100644 index 00000000..6f463884 --- /dev/null +++ b/dicegame/src/test/java/dicegame/logic/LogicTest.java @@ -0,0 +1,115 @@ +//package dicegame.logic; +// +//import org.junit.jupiter.api.AfterEach; +//import org.junit.jupiter.api.Test; +//import org.mockito.Mockito; +//import org.mockito.stubbing.Answer; +// +//import java.util.Random; +//import java.util.function.Predicate; +// +//import static org.junit.jupiter.api.Assertions.*; +// +//class LogicTest { +// Logic logic; +// Random random = new Random(1234L); +// +// /** +// * K1 Passed index: +// * - index: 0-5 +// * - error: out of bounds +// * +// * K2 The number of the dice passed: +// * - value: 1 | 5 +// * - error: !(1 | 5) +// * +// * K3 Existing fixation of the passed dice: +// * - fixable: true | false +// * - error: dice was fixed previously +// * +// * K4 Number of other dice of the same number fixed in the current roll: +// * - bonus triggered: (2 | 5) of the same number fixed +// * - no bonus triggered: (1 | 3 | 4) of the same number fixed +// * - first fix of the game: 0 of the same number fixed +// * +// * K5 Number of fixed dice of the same number in previous rolls: +// * - bonus triggered: (2 | 5) of the same number fixed +// * - no bonus triggered: (1 | 3 | 4) of the same number fixed +// * - first fix of the game: 0 of the same number fixed +// */ +// +// @AfterEach +// void tearDown() { +// logic = null; +// } +// +// // K2 (c) +// // Valid index: 0-5 +// // The value for this index is not 1 or 5 +// @Test +// void changeDiceStateWithValidDiceNot1Or5() { +// startGameAndRollDice(invocation -> randomNumberNot0or4()); +// +// Exception e = assertThrows(SelectionException.class, () -> logic.changeDiceState(0)); +// String expectedMessage = "Es können nur 1'en und 5'en fixiert werden!"; +// String actualMessage = e.getMessage(); +// assertEquals(expectedMessage, actualMessage); +// } +// +// // K3 (a) +// // Valid index: 0-5 +// // Value: 0 | 5 +// // Index refers to dice which has been fixed in previous round +// @Test +// void changeDiceStateWhenFixedInPrevRoll() { +// startGameAndRollDice(invocation -> randomNumber0or4()); +// assertDoesNotThrow(() -> logic.changeDiceState(0)); +// logic.rollDice(); +// assertThrows(Exception.class, () -> logic.changeDiceState(0)); +// } +// +// // K3 (b) +// // Valid index: 0-5 +// // Value: 0 | 5 +// // Index refers to dice which has been fixed in current round +// @Test +// void changeDiceStateWhenFixedInThisRoll() { +// startGameAndRollDice(invocation -> randomNumber0or4()); +// assertDoesNotThrow(() -> logic.changeDiceState(0)); +// assertDoesNotThrow(() -> logic.changeDiceState(0)); +// } +// +// // K3 (c) +// // Valid index: 0-5 +// // Value: 0 | 5 +// // Index refers to dice which is not fixed +// @Test +// void changeDiceStateWhenNotFixed() { +// startGameAndRollDice(invocation -> randomNumber0or4()); +// assertDoesNotThrow(() -> logic.changeDiceState(0)); +// } +// +// private void startGameAndRollDice(Answer answer) { +// Random mockedRandom = Mockito.mock(Random.class); +// Mockito.when(mockedRandom.nextInt(6)).thenAnswer(answer); +// logic = new Logic(mockedRandom); +// logic.startGame(); +// logic.rollDice(); +// } +// +// private int randomNumber0or4() { +// return randomNumberExcept(n -> n != 0 && n != 4); +// } +// +// private int randomNumberNot0or4() { +// return randomNumberExcept(n -> n == 0 || n == 4); +// } +// +// private int randomNumberExcept(Predicate condition) { +// int randomNumber; +// do { +// randomNumber = random.nextInt(6); // 0 to 5 +// } while (condition.test(randomNumber)); // Repeat until condition is satisfied +// return randomNumber; +// } +//} \ No newline at end of file