package org.teachingextensions.logo.utils.PuzzleUtils; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.Point; import java.util.ArrayDeque; import java.util.Arrays; import java.util.Queue; import javax.swing.JPanel; import org.teachingextensions.approvals.lite.util.StringUtils; import org.teachingextensions.logo.utils.ColorUtils.PenColors; import org.teachingextensions.logo.utils.InterfaceUtils.TkpPanel; /** * Draws and animates a 9-puzzle */ public class PuzzleBoard extends JPanel { private static final long serialVersionUID = -2008156268412728375L; private final static int blank = 8; private final Tile[] tiles; private final Queue<TileMove> solution; public PuzzleBoard(Puzzle puzzle, PuzzleState solution) { super(); this.solution = createSolution(solution, puzzle); this.tiles = createTiles(puzzle.getCells()); } public static Queue<TileMove> createSolution(PuzzleState solution, Puzzle puzzle) { if (solution == null) { return new ArrayDeque<>(); } int i = puzzle.getBlankIndex(); Queue<TileMove> moves = new ArrayDeque<>(); for (PuzzleState.Direction d : solution.getHistory()) { int m = d.getValue(); TileMove move = new TileMove(i + m, i); moves.add(move); i = move.getStart(); } return moves; } private static Tile[] createTiles(int[] cells) { Tile[] t = new Tile[9]; for (int i = 0; i < 9; i++) { if (cells[i] == blank) { continue; } t[i] = new Tile(i, cells[i]); } return t; } private static void drawBorder(Graphics2D g) { g.setColor(PenColors.Blues.DarkBlue); g.fillRect(20, 20, 410, 410); } private static void drawField(Graphics2D g) { g.setColor(PenColors.Blues.SkyBlue); g.fillRect(30, 30, 386, 386); } private static void drawTiles(Graphics2D g, Tile[] tiles) { for (Tile tile : tiles) { if (tile == null) { continue; } tile.paint(g); } } @Override protected void paintComponent(Graphics g) { super.paintComponent(g); Graphics2D g2d = TkpPanel.configureGraphics2D(g); drawBorder(g2d); drawField(g2d); drawTiles(g2d, tiles); g2d.dispose(); } public Tile[] getTiles() { return Arrays.copyOf(tiles, tiles.length); } public boolean hasMoves() { return !solution.isEmpty(); } public TileMove getNextMove() { return solution.isEmpty() ? null : solution.remove(); } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("PuzzleBoard" + StringUtils.NEW_LINE); for (int i = 0; i < tiles.length; i += 3) { sb.append(tiles[i] + ", " + tiles[i + 1] + ", " + tiles[i + 2] + StringUtils.NEW_LINE); } return sb.toString(); } public void swap(int start, int end) { Point p = Tile.getPosition(end); Tile tile = tiles[start]; tile.moveTo(p); tiles[start] = null; tiles[end] = tile; } }