/* * Note for teachers: * * Below is one possible way you could use this lab with students. Depending on how * much you do/don't want them to do on their own, you can add back in code from the * solution files or you can delete more code from this lab before you hand it out. * The philosophy taken here is to have them working mainly with the World, Grid, and * Location classes - therefore, the code that takes care of the structure of the game, * graphics, etc. has been left intact. * * Directions for students: * * If a method contains "*** complete this method ***" on the first line, complete * it where the comments direct you. Otherwise, the methods are already complete. */ /* * AP(r) Computer Science GridWorld Case Study: * Copyright(c) 2002-2006 College Entrance Examination Board * (http://www.collegeboard.com). * * This code is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation. * * This code is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ import info.gridworld.grid.Grid; import info.gridworld.grid.BoundedGrid; import info.gridworld.grid.Location; import info.gridworld.world.World; import java.util.ArrayList; import java.util.Collections; /** * The GameOfFifteen class is the main application. *
* This class is not tested on the AP CS A and AB exams. *

* copyright© 2007 Dave Wittry (http://apcomputerscience.com) * @author Dave Wittry */ public class GameOfFifteen extends World { private boolean winner; /** * Constructs a bounded 4-by-4 grid */ public GameOfFifteen() { setGrid( new BoundedGrid(4, 4) ); loadBoard(); winner = false; setMessage("Rearrange the tiles in alphabetical row-major order.\n" + "Type the letter you want to move."); } /** * Loads the board/grid with the first 15 letters of the alphabet scrambled */ private void loadBoard() { // *** complete this method first *** String[] letters = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N","O"}; List list = new ArrayList(); /* * Students, write a for-each loop here which traverses through the letters * array and places each one into the ArrayList list. */ /* * Students, write a loop which takes one letter at a time from list and * adds it to the World/Grid in row-major order. Do this with one for-each * loop that goes through the 'list' ArrayList. You should not need any other loops. */ /* For shuffling, we have to be careful. We can't just * scramble any way we wish because there is the "15-14" * problem - read a website for explanation. In short, not all * random chosen starting situations are solvable. So, my scramble * scrambles the way someone would scramble the board that * you would buy in a store - since the pieces can't be removed, * if we start with a solved puzzle and make a whole bunch of * random legal moves (don't remove pieces and snap them back in), * then we'll still have a solvable puzzle when we're done. */ for (int num=1; num<=200; num++) { makeALegalMove(getGrid()); } } /** * The method is called by loadBoard in order to help it scramble * the board. */ private void makeALegalMove(Grid gr) { Location locOfOpenCell = null; for (int row=0; row legalMoves = new ArrayList(); Location north = locOfOpenCell.getAdjacentLocation(Location.NORTH); Location south = locOfOpenCell.getAdjacentLocation(Location.SOUTH); Location east = locOfOpenCell.getAdjacentLocation(Location.EAST); Location west = locOfOpenCell.getAdjacentLocation(Location.WEST); if ( gr.isValid(north) ) legalMoves.add(north); if ( gr.isValid(south) ) legalMoves.add(south); if ( gr.isValid(east) ) legalMoves.add(east); if ( gr.isValid(west) ) legalMoves.add(west); int randomIndex = (int)(Math.random() * legalMoves.size()); gr.put(locOfOpenCell, gr.get(legalMoves.get(randomIndex))); gr.remove(legalMoves.get(randomIndex)); } /** * The method is called by the GUI when a keyboard event takes place * @param desc the String describing the key * @param loc the selected location in the grid at the time the key was pressed * @return true if the world consumes the key press, false * @see World class */ public boolean keyPressed(String desc, Location loc) { /* *** complete this method *** *** where you see the "..." and a comment afterward, complete the stmt. if ( winner ) return true; // game over; no more play if ( !("A".compareTo(desc)<=0 && "Z".compareTo(desc)>=0) ) // not a legal keyboard entry return true; Grid grid = getGrid(); ArrayList nbrs = ... get the occupied locations from the grid for (Location possLoc: nbrs) if ( grid.get(possLoc).getText().equals(desc) ) { ArrayList emptyCells = ... get the empty, adjacent locations from the grid if ( emptyCells.size() == 0 ) // no open spot next to that letter return true; // at this point, there is exactly one open spot int dirToward = ... get the direction from possLoc toward the open cell (use the Location class to help you) if ( dirToward % 90 != 0) return true; // can only move horizontally/vertically // we've found somewhere to move to ... from the Grid, remove the object from Location possLoc and place it at the open location winner = determineWinner(); if ( winner ) setMessage("You WIN"); else setMessage("You moved letter " + desc + " from position " + possLoc); return true; } return true; */ return true; // delete this line when completing this method } /** * The method determines if there is a winning situation * @return true if there is a winning situation, false otherwise */ private boolean determineWinner() { // *** complete this method *** /* * Students, one possible way to write this method would be to get all of the objects out of the Grid * in row-major order and place them into an ArrayList. Then, go through that ArrayList making sure * that adjacent elements are ordered based on getText() (or your teacher may want you to make the * ColorTextPiece class implement Comparable as a nice additional exercise). * Keep in mind that somewhere there will be a null location! You're hoping the null location ends up * as the 16th cell, with all other cells being ordered - then you have your winning situation! Try * this algorithm with a piece of graph paper and a friend - see if it makes sense to the both of you * before you start coding. Or, come up with your own algorithm. */ return true; // remove this stmt when completing this method } /** * The method is called by the GUI when a mouse event takes place. There are no mouse * events for this game - so this method immediately returns true; * @param loc the selected location in the grid at the time the mouse was pressed * @return true if the world consumes the key press, false * @see World class */ public boolean locationClicked(Location loc) { return true; // do nothing when mouse-clicked } public static void main(String[] args) { World mw = new GameOfFifteen(); System.setProperty("info.gridworld.gui.selection", "hide"); mw.show(); } }