Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found
Select Git revision
  • main
  • master
2 results

Target

Select target project
  • b23003912/image-template-tp-4-baron-law-yoann
  • s21226517/image-template
  • c19028886/tp-3-rayane-chorfi
  • s23026062/image-sahin
  • t21233923/image-template
  • z23012739/image-template
  • a23026569/image-template-amroun-said
  • boukenze.b/image-template-tp-4
  • l3_s3_infoamu/s3/programmation-2/tp-4-manipulation-dimages
  • c22029830/image-template-rafi
  • m22023183/image-template
  • l3_s3_infoamu/s3/programmation-2/image-template
  • a19029459/image-template
  • a19021078/image-template
  • alaboure/image-template
  • saddem.r/image-template
  • b21229750/image-template-tp-4
17 results
Select Git revision
Loading items
Show changes
Commits on Source (9)
Showing
with 487 additions and 519 deletions
......@@ -51,6 +51,7 @@ cmake-build-*/
# IntelliJ
out/
.idea
# mpeltonen/sbt-idea plugin
.idea_modules/
......
image: gradle:jdk16
image: openjdk:17-alpine
variables:
GRADLE_OPTS: "-Dorg.gradle.daemon=false"
before_script:
- export GRADLE_USER_HOME=`pwd`/.gradle
......@@ -8,11 +11,30 @@ cache:
- .gradle/wrapper
- .gradle/caches
stages:
- build
- test
build:
stage: build
script: ./gradlew --build-cache assemble
cache:
key: "$CI_COMMIT_REF_NAME"
policy: push
paths:
- build
- .gradle
java:
stage: test
script:
- gradle test
script: ./gradlew test
artifacts:
when: always
reports:
junit: build/test-results/test/**/TEST-*.xml
cache:
key: "$CI_COMMIT_REF_NAME"
policy: pull
paths:
- build
- .gradle
\ No newline at end of file
......@@ -4,7 +4,6 @@
Ce projet est l'occasion de travailler sur la représentation et la manipulation d'images. Ces images seront constituées de pixels caractérisés par une couleur représentant un niveau de gris.
## Membres du projet
## Membre du projet
- NOM, prénom, numéro de groupe, du premier participant
- NOM, prénom, numéro de groupe, du deuxième participant
- NOM, prénom
plugins {
id 'java'
id 'application'
id "org.openjfx.javafxplugin" version "0.0.10"
id "org.openjfx.javafxplugin" version "0.0.14"
}
group 'M2_BIO_INFO'
version '1.0-SNAPSHOT'
javafx {
version = "17"
version = "20"
modules = [ 'javafx.controls', 'javafx.fxml' ]
}
......@@ -12,16 +16,21 @@ repositories {
mavenCentral()
}
dependencies {
testImplementation('org.junit.jupiter:junit-jupiter-api:5.7.2',
'org.hamcrest:hamcrest-library:2.2', 'net.obvj:junit-utils:1.3.1')
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}
test {
useJUnitPlatform()
}
dependencies {
testRuntimeOnly("org.junit.platform:junit-platform-launcher") {
because("Only needed to run tests in a version of IntelliJ IDEA that bundles older versions")
}
testRuntimeOnly("org.junit.jupiter:junit-jupiter-engine")
testImplementation("org.assertj:assertj-core:3.24.2")
testImplementation("org.junit.jupiter:junit-jupiter:5.10.0")
}
application {
mainClassName = "GameOfLifeApplication"
mainClass.set("Main")
}
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.1-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
#!/usr/bin/env sh
#!/bin/sh
#
# Copyright 2015 the original author or authors.
# 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.
......@@ -17,67 +17,101 @@
#
##############################################################################
##
## Gradle start up script for UN*X
##
#
# 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/subprojects/plugins/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
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
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
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# 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"'
DEFAULT_JVM_OPTS='-Dfile.encoding=UTF-8 "-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
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
;;
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
......@@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
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"
JAVACMD=$JAVA_HOME/jre/sh/java
else
JAVACMD="$JAVA_HOME/bin/java"
JAVACMD=$JAVA_HOME/bin/java
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
......@@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
JAVACMD=java
which java >/dev/null 2>&1 || 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
......@@ -106,80 +140,105 @@ location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
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=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=SC3045
ulimit -n "$MAX_FD" ||
warn "Could not set maximum file descriptor limit to $MAX_FD"
esac
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
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" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if "$cygwin" || "$msys" ; then
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
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
i=`expr $i + 1`
# 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
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command;
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
# shell script including quotes and variable substitutions, so put them in
# double quotes to make sure that they get re-expanded; and
# * put everything else in single quotes, so that it's not re-expanded.
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.
#
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
eval "set -- $(
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
xargs -n1 |
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
tr '\n' ' '
)" '"$@"'
exec "$JAVACMD" "$@"
rootProject.name = 'game-of-life'
rootProject.name = 'image'
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public class ByteGrayColor implements GrayColor {
private static final int MINIMUM_GRAY_LEVEL = 0;
private static final int MAXIMUM_GRAY_LEVEL = 255;
private static final int OPACITY = 1;
// TODO : add static ByteGrayColors WHITE and BLACK
private final int grayLevel;
public ByteGrayColor(){
this.grayLevel = MINIMUM_GRAY_LEVEL;
}
public ByteGrayColor(int grayLevel) {
// TODO : Corriger l'initialisation de la propriété grayLevel de l'instance.
this.grayLevel = 0;
}
public ByteGrayColor(double luminosity) {
// TODO : Corriger l'initialisation de la propriété grayLevel de l'instance.
this.grayLevel = 0;
}
@Override
public double getLuminosity() {
// TODO : Retourner la luminosité de la couleur (entre 0 noir et 1 blanc)
return 0;
}
@Override
public Color getColor(){
double component = getLuminosity();
return new Color(component, component, component, OPACITY);
}
@Override
public int compareTo(GrayColor o) {
// TODO : Retourner la différence de niveau de gris.
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (this.getClass() != o.getClass()) return false;
ByteGrayColor color = (ByteGrayColor) o;
return grayLevel == color.grayLevel;
}
}
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.canvas.Canvas;
import javafx.scene.canvas.GraphicsContext;
import javafx.scene.image.PixelWriter;
import java.net.URL;
import java.util.ResourceBundle;
/**
* Created by Arnaud Labourel on 04/10/2018.
*/
public class Display implements Initializable {
@FXML
private Canvas canvas;
MatrixGrayImage image;
@Override
public void initialize(URL location, ResourceBundle resources) {
this.image = MatrixGrayImage.createImageFromPGMFile("images/luminy.pgm");
// TODO : Ajouter les transformations d'image.
render();
}
public void render() {
int pixelWidth = image.getWidth();
int pixelHeight = image.getHeight();
canvas.setWidth(pixelWidth);
canvas.setHeight(pixelHeight);
GraphicsContext graphicsContext = canvas.getGraphicsContext2D();
PixelWriter pixelWriter = graphicsContext.getPixelWriter();
for (int i = 0; i < pixelWidth; i++) {
for (int j = 0; j < pixelHeight; j++) {
renderPixel(i,j, pixelWriter);
}
}
}
private void renderPixel(int x, int y, PixelWriter pixelWriter) {
pixelWriter.setColor(x, y, image.getPixelColor(x, y));
}
}
import controller.Controller;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import model.GameOfLife;
import model.Grid;
import java.io.IOException;
import java.net.URL;
import static java.util.Objects.requireNonNull;
/**
* Entry point for <i>The Game of Life</i> application.
*
*/
public class GameOfLifeApplication extends Application {
private static final int NUMBER_OF_ROWS = 40;
private static final int NUMBER_OF_COLUMNS = 70;
private static final String APP_NAME = "Game of Life";
private static final String VIEW_RESOURCE_PATH = "/view/view.fxml";
private final GameOfLife gameOfLife;
private Stage primaryStage;
private Parent view;
/**
* Creates a new {@code GameOfLifeApplication} instance.
*/
public GameOfLifeApplication() {
this(new GameOfLife(new Grid(NUMBER_OF_ROWS, NUMBER_OF_COLUMNS)));
}
/**
* Creates a new {@code GameOfLifeApplication} instance given a {@link GameOfLife} instance.
*
* @param gameOfLife the {@link GameOfLife} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
private GameOfLifeApplication(GameOfLife gameOfLife) {
this.gameOfLife = requireNonNull(gameOfLife, "game of life is null");
}
@Override
public void start(Stage primaryStage) throws IOException {
initializePrimaryStage(primaryStage);
initializeView();
showScene();
}
private void initializePrimaryStage(Stage primaryStage) {
this.primaryStage = primaryStage;
this.primaryStage.setTitle(APP_NAME);
this.primaryStage.setOnCloseRequest(event -> Platform.exit());
this.primaryStage.setResizable(false);
this.primaryStage.sizeToScene();
}
private void initializeView() throws IOException {
FXMLLoader loader = new FXMLLoader();
URL location = GameOfLifeApplication.class.getResource(VIEW_RESOURCE_PATH);
loader.setLocation(location);
view = loader.load();
Controller controller = loader.getController();
controller.setGameOfLife(gameOfLife);
}
private void showScene() {
Scene scene = new Scene(view);
primaryStage.setScene(scene);
primaryStage.show();
}
}
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 04/10/2018.
* Interface correspondant à une couleur de gris.
*/
public interface GrayColor extends Comparable<GrayColor> {
double getLuminosity();
Color getColor();
}
/**
* Created by Arnaud Labourel on 04/10/2018.
*/
public interface GrayImage extends Image {
void setPixel(GrayColor gray, int x, int y);
GrayColor getPixelGrayColor(int x, int y);
}
import javafx.scene.paint.Color;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public interface Image {
Color getPixelColor(int x, int y);
int getWidth();
int getHeight();
}
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Main extends Application
{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws IOException {
Parent root =FXMLLoader.load(getClass().getResource("fxml/Display.fxml"));
primaryStage.setTitle("Image display");
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
import javafx.scene.paint.Color;
import java.io.FileWriter;
import java.io.InputStream;
import java.io.PrintWriter;
import java.util.Scanner;
/**
* Created by Arnaud Labourel on 02/10/2018.
*/
public class MatrixGrayImage implements GrayImage {
private final GrayColor[][] pixels;
private final int width;
private final int height;
@Override
public void setPixel(GrayColor gray, int x, int y) {
// TODO : Compléter la méthode pour modifier le pixel.
}
@Override
public GrayColor getPixelGrayColor(int x, int y) {
// TODO : Changer les instructions pour retourner le bon pixel.
return new ByteGrayColor();
}
@Override
public Color getPixelColor(int x, int y) {
// TODO : Changer les instructions pour retourner la couleur du pixel.
return Color.WHITE;
}
@Override
public int getWidth() {
// TODO : Changer les instructions pour retourner la largeur de l'image.
return 600;
}
@Override
public int getHeight() {
// TODO : Changer les instructions pour retourner la hauteur de l'image.
return 400;
}
public MatrixGrayImage(int width, int height){
/* TODO : Modifier les instructions pour initialiser correctement
les propriétés de l'instance.
*/
this.width = 0;
this.height = 0;
this.pixels = null;
}
public static MatrixGrayImage createImageFromPGMFile(String fileName) {
// NE PAS MODIFIER !
InputStream file = ClassLoader.getSystemResourceAsStream(fileName);
Scanner scan = new Scanner(file);
scan.nextLine();
scan.nextLine();
int width = scan.nextInt();
int height = scan.nextInt();
MatrixGrayImage result = new MatrixGrayImage(width, height);
scan.nextInt();
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++) {
GrayColor color = new ByteGrayColor(scan.nextInt());
result.setPixel(color, x, y);
}
}
return result;
}
public void writeIntoPGMFormat(String fileName){
// NE PAS MODIFIER !
try {
FileWriter fileWriter = new FileWriter(fileName);
PrintWriter printWriter = new PrintWriter(fileWriter);
printWriter.println("P2");
printWriter.println("# CREATOR: TP3 Version 1.0");
printWriter.printf("%d %d\n",this.width, this.height);
printWriter.println(pgmCodeOfGrayColor(pixels[0][0]));
for(int y = 0; y < height; y++){
for(int x = 0; x < width; x++) {
printWriter.println(pgmCodeOfGrayColor(getPixelGrayColor(x,y)));
}
}
printWriter.close();
}
catch (Exception e){
e.printStackTrace();
}
}
private static final int PGM_MAXIMUM_CODE = 255;
private int pgmCodeOfGrayColor(GrayColor pixelGrayColor) {
return (int) (pixelGrayColor.getLuminosity() * (double) PGM_MAXIMUM_CODE);
}
}
package controller;
import javafx.fxml.FXML;
import javafx.scene.control.Label;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import model.GameOfLife;
import model.Grid;
import view.MatrixPane;
import static java.util.Objects.requireNonNull;
/**
* Controller for <i>The Game of Life</i> application.
*/
public class Controller {
@FXML
private ToggleButton playToggleButton;
@FXML
private ToggleButton pauseToggleButton;
@FXML
private Label generationNumberLabel;
@FXML
private MatrixPane matrixPane;
private GameOfLife gameOfLife;
@FXML
private void initialize() {
initializePlayAndPauseToggleButtons();
}
private void initializePlayAndPauseToggleButtons() {
ToggleGroup toggleGroup = new PersistentToggleGroup();
toggleGroup.getToggles().addAll(playToggleButton, pauseToggleButton);
pauseToggleButton.setSelected(true);
}
/**
* Sets {@link GameOfLife} instance.
*
* @param gameOfLife {@link GameOfLife} instance
* @throws NullPointerException if {@code gameOfLife} is {@code null}
*/
public void setGameOfLife(GameOfLife gameOfLife) {
this.gameOfLife = requireNonNull(gameOfLife, "game of life is null");
setGenerationNumberLabelTextProperty();
initializeMatrixPane();
}
private void setGenerationNumberLabelTextProperty() {
generationNumberLabel.textProperty().bind(gameOfLife.generationNumberProperty().asString());
}
private void initializeMatrixPane() {
Grid grid = gameOfLife.getGrid();
matrixPane.initialize(grid);
}
@FXML
private void playToggleButtonAction() {
gameOfLife.play();
}
@FXML
private void pauseToggleButtonAction() {
gameOfLife.pause();
}
@FXML
private void resetButtonAction() {
gameOfLife.reset();
pauseToggleButton.setSelected(true);
}
@FXML
private void clearButtonAction() {
gameOfLife.clear();
pauseToggleButton.setSelected(true);
}
}
package controller;
import javafx.collections.ListChangeListener.Change;
import javafx.scene.control.Toggle;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.input.MouseEvent;
/**
* An extension of {@link ToggleGroup} that ensures that a {@link Toggle} in a group must always be
* selected.
*
*/
class PersistentToggleGroup extends ToggleGroup {
/**
* Creates a new {@code PersistentToggleGroup}.
*/
PersistentToggleGroup() {
getToggles().addListener((Change<? extends Toggle> change) -> {
while (change.next()) {
for (Toggle toggle : change.getAddedSubList()) {
ToggleButton toggleButton = (ToggleButton) toggle;
toggleButton.addEventFilter(MouseEvent.MOUSE_RELEASED, mouseEvent -> {
if (toggleButton.equals(getSelectedToggle())) {
mouseEvent.consume();
}
});
}
}
});
}
}
package model;
import javafx.beans.property.Property;
import javafx.beans.property.SimpleObjectProperty;
/**
* {@link Cell} instances represent the cells of <i>The Game of Life</i>.
*/
public class Cell {
private final Property<CellState> stateProperty = new SimpleObjectProperty<>(CellState.DEAD);
/**
* Determines whether this {@link Cell} is alive or not.
*
* @return {@code true} if this {@link Cell} is alive and {@code false} otherwise
*/
public boolean isAlive() {
return getState().isAlive;
}
/**
* Sets the state of this {@link Cell}.
*
* @param cellState the new state of this {@link Cell}
*/
public void setState(CellState cellState) {
getStateProperty().setValue(cellState);
}
/**
* Returns the current state of this {@link Cell}.
*
* @return the current state of this {@link Cell}
*/
public CellState getState(){
return getStateProperty().getValue();
}
/**
* Change the state of this {@link Cell} from ALIVE to DEAD or from DEAD to ALIVE.
*/
public void toggleState() {
CellState[] possibleStates = CellState.values();
int stateOrdinal = getState().ordinal();
int numberOfPossibleStates = possibleStates.length;
setState(possibleStates[(stateOrdinal+1)%numberOfPossibleStates]);
}
/**
* Returns this {@link Cell}'s state property.
*
* @return this {@link Cell}'s state property.
*/
public Property<CellState> getStateProperty() {
return stateProperty;
}
}
package model;
import javafx.scene.paint.Color;
/**
* {@link CellState} instances represent the possible states of a {@link CellState}.
*/
public enum CellState {
ALIVE(true, Color.RED), DEAD(false, Color.WHITE);
public final boolean isAlive;
public final Color color;
CellState(boolean isAlive, Color color) {
this.isAlive = isAlive;
this.color = color;
}
}
package model;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.beans.property.ReadOnlyLongProperty;
import javafx.beans.property.ReadOnlyLongWrapper;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.util.Duration;
import java.util.Random;
import static java.util.Objects.requireNonNull;
/**
* {@link GameOfLife} instances run <i>The Game of Life</i>.
*/
public class GameOfLife {
private final Random random = new Random();
private static final int PERIOD_IN_MILLISECONDS = 100;
private final Grid grid;
private final ReadOnlyLongWrapper generationNumber = new ReadOnlyLongWrapper();
private Timeline timeline;
/**
* Creates a new {@code GameOfLife} instance given the underlying {@link Grid}.
*
* @param grid the underlying {@link Grid}
* @throws NullPointerException if {@code grid} is {@code null}
*/
public GameOfLife(Grid grid) {
this.grid = requireNonNull(grid, "grid is null");
updateTimeline();
grid.randomGeneration(random);
}
private void updateTimeline() {
Duration duration = new Duration(PERIOD_IN_MILLISECONDS);
EventHandler<ActionEvent> eventHandler = event -> next();
KeyFrame keyFrame = new KeyFrame(duration, eventHandler);
timeline = new Timeline(keyFrame);
timeline.setCycleCount(Animation.INDEFINITE);
}
/**
* Transitions into the next generationNumber.
*/
private void next() {
grid.updateToNextGeneration();
generationNumber.set(getGenerationNumber() + 1);
}
/**
* Returns the current generationNumber.
*
* @return the current generationNumber
*/
private long getGenerationNumber() {
return generationNumber.get();
}
/**
* Returns the generationNumber {@link ReadOnlyLongProperty}.
*
* @return the generationNumber {@link ReadOnlyLongProperty}
*/
public ReadOnlyLongProperty generationNumberProperty() {
return generationNumber.getReadOnlyProperty();
}
/**
* Returns the {@link Grid}.
*
* @return the {@link Grid}
*/
public Grid getGrid() {
return grid;
}
/**
* Plays the game.
*/
public void play() {
timeline.play();
}
/**
* Pauses the game.
*/
public void pause() {
timeline.pause();
}
/**
* Clears the current game.
*/
public void clear() {
pause();
grid.clear();
generationNumber.set(0);
}
/**
* Clears the current game and randomly generates a new one.
*/
public void reset() {
clear();
grid.randomGeneration(random);
}
}