[QUIZ#9] zeja (Java)

zeja

Erfahrenes Mitglied
Unterstützt werden alle Eingabeformate. Diese werden an ihrere Endung erkannt.

Java:
package de.tutorials.quiz9;

import java.awt.Color;
import java.awt.Desktop;
import java.awt.Graphics2D;
import java.awt.geom.Point2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Stack;

import javax.imageio.ImageIO;

import de.tutorials.quiz9.TurtleFile.Type;

public class PaintingTurtle {

	private static class RecoverPoint {

		private int anglePosition;
		private Point2D.Double point;

		public RecoverPoint(Point2D.Double point, int anglePosition) {
			this.point = (Point2D.Double) point.clone( );
			this.anglePosition = anglePosition;
		}

	}

	public static BufferedImage createImage(final TurtleFile turtleFile)
			throws IOException {
		// Iteration über die Aktionen durchführen
		final List<TurtleAction> actions = expandActions(turtleFile);

		final BufferedImage image = new BufferedImage(turtleFile.getWidth( ),
				turtleFile.getHeight( ), BufferedImage.TYPE_INT_BGR);

		final Graphics2D graphics = image.createGraphics( );

		// Bild Hintergrund weiß und Vordergrund schwarz
		graphics.setBackground(Color.WHITE);
		graphics
				.clearRect(0, 0, turtleFile.getWidth( ), turtleFile.getHeight( ));
		graphics.setColor(Color.BLACK);

		// Wieviele unterschiedliche Winkel können vorkommen?
		final int count = (int) Math.round(360.0 / turtleFile.getAngle( ));

		// Alle benötigten Vektoren vorberechnen
		final Point2D.Double[] vectors = new Point2D.Double[count];

		for (int i = 0; i < count; i++) {
			double angle = i * turtleFile.getAngle( );

			double rad = Math.toRadians(angle);
			double cos = Math.cos(rad);
			double sin = Math.sin(rad);

			double newX = turtleFile.getStep( ) * cos; // + 0 * -sin
			double newY = turtleFile.getStep( ) * sin; // + 0 * cos

			vectors[i] = new Point2D.Double(newX, newY);
		}

		// Blickrichtung
		int angleCount = 0;

		// Ausgangspunkt
		final Point2D.Double point = new Point2D.Double(turtleFile.getxPos( ),
				turtleFile.getHeight( ) - turtleFile.getyPos( ));

		// STACK für Markierungen
		final Stack<RecoverPoint> stack = new Stack<RecoverPoint>( );

		// Aktionen ausführen
		for (TurtleAction action : actions) {
			// Vorwärts
			if (action == TurtleAction.FORWARD) {
				final Point2D.Double vector = vectors[angleCount];
				graphics.drawLine(rint(point.x), rint(point.y), rint(point.x
						+ vector.x), rint(point.y + vector.y));
				point.setLocation(point.x + vector.x, point.y + vector.y);
			}
			// Linksdrehung
			else if (action == TurtleAction.TURN_LEFT) {
				if (angleCount == 0) {
					angleCount = count - 1;
				}
				else {
					angleCount--;
				}
			}
			// Rechtsdrehung
			else if (action == TurtleAction.TURN_RIGHT) {
				if (angleCount == count - 1) {
					angleCount = 0;
				}
				else {
					angleCount++;
				}
			}
			// Markierung setzen
			else if (action == TurtleAction.MARK) {
				stack.push(new RecoverPoint(point, angleCount));
			}
			// zu letzter Markierung zurückspringen
			else if (action == TurtleAction.REWIND) {
				final RecoverPoint recover = stack.pop( );
				point.setLocation(recover.point.x, recover.point.y);
				angleCount = recover.anglePosition;
			}

		}

		return image;
	}

	private static int rint(double d) {
		return (int) Math.round(d);
	}

	private static List<TurtleAction> expandActions(final TurtleFile turtleFile) {
		List<TurtleAction> actions = new ArrayList<TurtleAction>(turtleFile
				.getStartList( ));

		// Iterationen durchführen
		for (int i = 0; i < turtleFile.getIterations( ); i++) {

			// Neue Aktionsliste
			final List<TurtleAction> newActions = new ArrayList<TurtleAction>( );

			for (TurtleAction action : actions) {
				final RouletteList rouletteList = turtleFile
						.getReplaceList(action);

				if (rouletteList != null) {
					newActions.addAll(rouletteList.get( ));
				}
				else {
					newActions.add(action);
				}
			}

			actions = newActions;
		}
		return actions;
	}

	public static void create(File in, boolean show) throws IOException {
		final String name = in.getName( );
		final String suffix = name.substring(name.lastIndexOf(".") + 1);
		final Type type = Type.valueOf(suffix.toUpperCase( ));

		final TurtleFile turtleFile = TurtleFile.read(in, type);

		final BufferedImage image = createImage(turtleFile);

		final File imageFile = new File(name + ".png");
		ImageIO.write(image, "png", imageFile);
		if (show) {
			Desktop.getDesktop( ).open(imageFile);
		}
	}

	public static void main(String[] args) throws IOException {
		final File in = new File(".");

		for (File f : in.listFiles( )) {
			if (f.getName( ).contains("turtle") && !f.getName( ).endsWith("png")) {
				create(f, false);
			}
		}

	}

}

Java:
package de.tutorials.quiz9;

public class TurtleAction {

	public static final TurtleAction TURN_LEFT = new TurtleAction("+");
	public static final TurtleAction TURN_RIGHT = new TurtleAction("-");
	public static final TurtleAction FORWARD = new TurtleAction("F");
	public static final TurtleAction MARK = new TurtleAction("[");
	public static final TurtleAction REWIND = new TurtleAction("]");

	private String id;

	public TurtleAction(String id) {
		this.id = id;
	}

	@Override
	public String toString() {
		return id;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((id == null) ? 0 : id.hashCode( ));
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (obj == null) {
			return false;
		}
		if (!(obj instanceof TurtleAction)) {
			return false;
		}
		TurtleAction other = (TurtleAction) obj;
		if (id == null) {
			if (other.id != null) {
				return false;
			}
		}
		else if (!id.equals(other.id)) {
			return false;
		}
		return true;
	}

}

Java:
package de.tutorials.quiz9;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class TurtleFile {

	private int width;
	private int height;
	private int xPos;
	private int yPos;
	private int step;
	private double angle;
	private List<TurtleAction> startList = new ArrayList<TurtleAction>( );
	private int iterations;
	private Map<TurtleAction, RouletteList> replaceMap = new HashMap<TurtleAction, RouletteList>( );

	public enum Type {
		A, B, B1, B2
	}

	// Breite Höhe
	// x-Position y-Position
	// Schrittweite
	// Drehwinkel
	// Liste der Aktionen
	// * +: Linksdrehung (gegen den Uhrzeigersinn)
	// * -: Rechtsdrehung (im Uhrzeigersinn)
	// * F: Vorwärtsbewegung in Blickrichtung (Forward)

	public static TurtleFile read(File file, Type type) throws IOException {
		final BufferedReader reader = new BufferedReader(new FileReader(file));
		String[] split = reader.readLine( ).split(" ");

		final TurtleFile turtleFile = new TurtleFile( );
		turtleFile.width = Integer.parseInt(split[0]);
		turtleFile.height = Integer.parseInt(split[1]);

		split = reader.readLine( ).split(" ");
		turtleFile.xPos = Integer.parseInt(split[0]);
		turtleFile.yPos = Integer.parseInt(split[1]);

		turtleFile.step = Integer.parseInt(reader.readLine( ));
		turtleFile.angle = Double.parseDouble(reader.readLine( ));

		if (type == Type.A) {
			readA(reader, turtleFile);
		}
		else if (type == Type.B) {
			readB(reader, turtleFile);
		}
		else if (type == Type.B1) {
			readB1(reader, turtleFile);
		}
		else if (type == Type.B2) {
			readB2(reader, turtleFile);
		}

		reader.close( );

		return turtleFile;
	}

	private static void readA(BufferedReader reader, TurtleFile turtleFile)
			throws IOException {
		String[] split = reader.readLine( ).split("");
		List<TurtleAction> actionList = new ArrayList<TurtleAction>( );
		addToList(split, actionList);

		turtleFile.startList = actionList;
		turtleFile.iterations = 0;
	}

	private static void readCommonB(BufferedReader reader, TurtleFile turtleFile)
			throws IOException {
		String[] split = reader.readLine( ).split("");
		addToList(split, turtleFile.startList);

		turtleFile.iterations = Integer.parseInt(reader.readLine( ));
	}

	private static void readB(BufferedReader reader, TurtleFile turtleFile)
			throws IOException {
		readCommonB(reader, turtleFile);

		String[] split = reader.readLine( ).split("");
		List<TurtleAction> replaceList = new ArrayList<TurtleAction>( );
		addToList(split, replaceList);
		turtleFile.replaceMap.put(TurtleAction.FORWARD, RouletteList
				.createSingleton(replaceList));
	}

	private static void readB1(final BufferedReader reader,
			final TurtleFile turtleFile) throws IOException {
		readCommonB(reader, turtleFile);

		String line;
		while ((line = reader.readLine( )) != null) {
			String[] split = line.split(" ");
			final TurtleAction action = toAction(split[0]);
			List<TurtleAction> replaceList = new ArrayList<TurtleAction>( );
			addToList(split[1].split(""), replaceList);
			turtleFile.replaceMap.put(action, RouletteList
					.createSingleton(replaceList));
		}
	}

	private static void readB2(BufferedReader reader, TurtleFile turtleFile)
			throws IOException {
		readCommonB(reader, turtleFile);

		Map<TurtleAction, List<FactorList>> map = new HashMap<TurtleAction, List<FactorList>>( );

		String line;
		while ((line = reader.readLine( )) != null) {
			final String[] split = reader.readLine( ).split(" ");
			final TurtleAction action = toAction(split[0]);
			int prop = Integer.parseInt(split[1]);
			List<TurtleAction> replaceList = new ArrayList<TurtleAction>( );
			addToList(split[2].split(""), replaceList);

			List<FactorList> list = map.get(action);
			if (list == null) {
				list = new ArrayList<FactorList>( );
				map.put(action, list);
			}
			list.add(new FactorList(prop, replaceList));
		}

		for (Map.Entry<TurtleAction, List<FactorList>> entry : map.entrySet( )) {
			turtleFile.replaceMap.put(entry.getKey( ), RouletteList
					.createForFactorList(entry.getValue( )));
		}
	}

	private static void addToList(String[] split,
			final List<TurtleAction> actionList) {
		for (String s : split) {
			if (s.length( ) > 0) {
				actionList.add(toAction(s));
			}
		}
	}

	private static TurtleAction toAction(String s) {
		if ("+".equals(s)) {
			return TurtleAction.TURN_LEFT;
		}
		else if ("-".equals(s)) {
			return TurtleAction.TURN_RIGHT;
		}
		else if ("F".equals(s)) {
			return TurtleAction.FORWARD;
		}
		else if ("[".equals(s)) {
			return TurtleAction.MARK;
		}
		else if ("]".equals(s)) {
			return TurtleAction.REWIND;
		}
		return new TurtleAction(s);
	}

	/**
	 * @return the width
	 */
	public int getWidth() {
		return width;
	}

	/**
	 * @return the height
	 */
	public int getHeight() {
		return height;
	}

	/**
	 * @return the xPos
	 */
	public int getxPos() {
		return xPos;
	}

	/**
	 * @return the yPos
	 */
	public int getyPos() {
		return yPos;
	}

	/**
	 * @return the step
	 */
	public int getStep() {
		return step;
	}

	/**
	 * @return the angle
	 */
	public double getAngle() {
		return angle;
	}

	public List<TurtleAction> getStartList() {
		return startList;
	}

	public int getIterations() {
		return iterations;
	}

	public RouletteList getReplaceList(TurtleAction action) {
		return replaceMap.get(action);
	}

}

Java:
package de.tutorials.quiz9;

import java.util.List;

class FactorList {

	int probability;
	List<TurtleAction> replaceList;

	public FactorList(int probability, List<TurtleAction> replaceList) {
		this.probability = probability;
		this.replaceList = replaceList;
	}

}

Java:
package de.tutorials.quiz9;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;

public class RouletteList {

	private final List<List<TurtleAction>> replaceLists = new ArrayList<List<TurtleAction>>( );

	private final Random random = new Random( );

	private RouletteList() {
	}

	public static RouletteList createSingleton(List<TurtleAction> replaceList) {
		RouletteList list = new RouletteList( );
		list.replaceLists.add(replaceList);

		return list;
	}

	public static RouletteList createForFactorList(List<FactorList> factorLists) {
		RouletteList list = new RouletteList( );

		// Ersetzungslisten entsprechend ihrer Anzahl in die Liste
		// hinzufügen
		for (FactorList factorList : factorLists) {
			for (int i = 0; i < factorList.probability; i++) {
				list.replaceLists.add(new ArrayList<TurtleAction>(
						factorList.replaceList));
			}
		}

		// Einmal durchmischen
		Collections.shuffle(list.replaceLists);

		return list;
	}

	public List<TurtleAction> get() {
		// Ziehen aus der Liste in der die Ersetzungen entsprechend
		// der Wahrscheinlichkeiten vorhanden sind.
		// Jeder Ersetzung kommt durch das zufällige ziehen
		// entsprechend ihrer Wahrscheinlichkeit dran.
		return replaceLists.get(random.nextInt(replaceLists.size( )));
	}

}
 
Alternative Methode ohne selber zu rechnen mit der Nutzung von AffineTransform des Graphics2D.

Java:
private static class RecoverPoint {

	private AffineTransform transform;
	private Point point;

	public RecoverPoint(Point point, AffineTransform transform) {
		this.point = (Point) point.clone( );
		this.transform = (AffineTransform) transform.clone( );
	}

}

public static BufferedImage createImage(final TurtleFile turtleFile)
		throws IOException {
	// Iteration über die Aktionen durchführen
	final List<TurtleAction> actions = expandActions(turtleFile);

	final BufferedImage image = new BufferedImage(turtleFile.getWidth( ),
			turtleFile.getHeight( ), BufferedImage.TYPE_INT_BGR);

	final Graphics2D graphics = image.createGraphics( );

	// Bild Hintergrund weiß und Vordergrund schwarz
	graphics.setBackground(Color.WHITE);
	graphics
			.clearRect(0, 0, turtleFile.getWidth( ), turtleFile.getHeight( ));
	graphics.setColor(Color.BLACK);
	
	// Ausgangspunkt
	final Point point = new Point(turtleFile.getxPos( ),
			turtleFile.getHeight( ) - turtleFile.getyPos( ));

	// STACK für Markierungen
	final Stack<RecoverPoint> stack = new Stack<RecoverPoint>( );
	
	final double theta = Math.toRadians(turtleFile.getAngle( ));

	// Aktionen ausführen
	for (TurtleAction action : actions) {
		// Vorwärts
		if (action == TurtleAction.FORWARD) {
			graphics.drawLine(point.x, point.y, point.x+turtleFile.getStep( ),point.y);
			point.setLocation(point.x+turtleFile.getStep( ),point.y);
		}
		// Linksdrehung
		else if (action == TurtleAction.TURN_LEFT) {
			graphics.rotate(-theta, point.x, point.y);
		}
		// Rechtsdrehung
		else if (action == TurtleAction.TURN_RIGHT) {
			graphics.rotate(theta, point.x, point.y);
		}
		// Markierung setzen
		else if (action == TurtleAction.MARK) {
			stack.push(new RecoverPoint(point, graphics.getTransform( )));
		}
		// zu letzter Markierung zurückspringen
		else if (action == TurtleAction.REWIND) {
			final RecoverPoint recover = stack.pop( );
			point.setLocation(recover.point.x, recover.point.y);
			graphics.setTransform(recover.transform);
		}

	}

	return image;
}
 
Zurück