소스 검색

Initial commit

Tom Flucke 11 년 전
커밋
393681d7f0
7개의 변경된 파일1059개의 추가작업 그리고 0개의 파일을 삭제
  1. 28 0
      src/ai/RandomAI.java
  2. 375 0
      src/game/GUIGrid.java
  3. 429 0
      src/game/Grid.java
  4. 8 0
      src/game/GridConstants.java
  5. 18 0
      src/game/GridEvent.java
  6. 8 0
      src/game/GridListener.java
  7. 193 0
      src/game/PlayerGrid.java

+ 28 - 0
src/ai/RandomAI.java

@@ -0,0 +1,28 @@
+package ai;
+
+import game.Grid;
+
+import java.awt.Point;
+
+public class RandomAI implements game.PlayerGrid.Player
+{
+	@Override
+    public Point[] placeMarker(Point[][] options)
+    {
+	    return options[(int) (Math.random()*options.length)];
+    }
+
+	@Override
+    public Point[] pickSector(Point[][] options)
+    {
+	    return options[(int) (Math.random()*options.length)];
+    }
+
+	@Override
+    public void setGrid(Grid g)
+    {}
+
+	@Override
+    public void markerPlaced(Point[] position, int player)
+    {}
+}

+ 375 - 0
src/game/GUIGrid.java

@@ -0,0 +1,375 @@
+package game;
+
+import game.Grid.GridObject;
+import game.PlayerGrid.Player;
+
+import java.awt.BasicStroke;
+import java.awt.Color;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.Graphics;
+import java.awt.Point;
+import java.awt.Stroke;
+import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
+import java.awt.Graphics2D;
+import java.util.ArrayList;
+
+import javax.swing.BorderFactory;
+import javax.swing.JFrame;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.WindowConstants;
+
+import ai.RandomAI;
+import arrays.ArrayMethods;
+import name.tomflucke.layouts.TableLayout;
+
+public class GUIGrid extends JPanel implements GridConstants
+{
+	private static final long serialVersionUID = -1636143083725158877L;
+
+	public static class GUIPlayer implements Player
+	{
+		private final Color playerColor;
+		private final Player play;
+
+		public GUIPlayer(Player play, Color color)
+		{
+			playerColor = color;
+			this.play = play;
+		}
+		
+		public Color getColor()
+		{
+			return playerColor;
+		}
+		
+		@Override
+        public Point[] placeMarker(Point[][] options)
+        {
+			return play.placeMarker(options);
+        }
+
+		@Override
+        public Point[] pickSector(Point[][] options)
+        {
+			return play.pickSector(options);
+        }
+
+		@Override
+        public void setGrid(Grid g)
+        {
+	        play.setGrid(g);
+        }
+
+		@Override
+        public void markerPlaced(Point[] position, int player)
+        {
+			play.markerPlaced(position, player);
+        }
+		
+	}
+	
+	public static class ClickPlayer implements Player
+	{
+		private static Placeholder clicked;
+		private static boolean hasClicked;
+		
+		public static void click(Placeholder ph)
+		{
+			hasClicked = true;
+			clicked = ph;
+		}
+		
+		private void waitForClick()
+		{
+			while (!hasClicked)
+			{
+				try
+                {
+	                Thread.sleep(100);
+                }
+                catch (InterruptedException ie)
+                {
+	                // TODO Auto-generated catch block
+	                ie.printStackTrace();
+                }
+			}
+			hasClicked = false;
+		}
+		
+		@Override
+        public Point[] placeMarker(Point[][] options)
+        {
+			waitForClick();
+	        return clicked.getGridLocation();
+        }
+
+		@Override
+        public Point[] pickSector(Point[][] options)
+        {
+			waitForClick();
+			Point[] result = clicked.getGridLocation();
+	        return ArrayMethods.subarray(result, 0, result.length -1);
+        }
+
+		@Override
+        public void setGrid(Grid g)
+        {}
+
+		@Override
+        public void markerPlaced(Point[] position, int player)
+        {}
+	}
+	
+	public static void main(String... strs)
+	{
+		int gridNum = 2;
+		boolean ai = true;
+		int i = 0;
+		while (i < strs.length)
+		{
+			switch (strs[i])
+			{
+				case "-h":
+				case "--help":
+					System.out.println("Welcome to X3T! (Extreme Tic-Tac-Toe!)");
+					System.out.println("This is only a basic demonstration of the core of the soon-to-be program.");
+					System.out.println("We currently accept the following arguements:");
+					System.out.println("-a --ai\t\t\tCauses player two to become an AI player");
+					System.out.println("\t\t\tCurrently, the only AI avaliable is the randomm AI.");
+					System.out.println("-m --human\t\tCauses player two to place moves based on user input. (Default)");
+					System.out.println("-g [n] --grid [n]\tSets the depth of recurssion. (Default n=2)");
+					return;
+				case "-a":
+				case "--ai":
+					ai = true;
+					System.out.println("Using Random Number AI for player two.");
+					break;
+				case "-m":
+				case "--human":
+					ai = false;
+					System.out.println("Using human input for player two.");
+					break;
+				case "-g":
+				case "--grid":
+					i++;
+					if (i+1 == strs.length || !strs[i+1].matches("\\d+"))
+					{
+						System.out.println("Invalid grid depth specified.  Defaulting to two.");
+					}
+					gridNum = Integer.valueOf(strs[i + 1]);
+					break;
+				default:
+					System.out.println("Invalid arguement: "+strs[i]);
+			}
+			i++;
+		}
+		JFrame window = new JFrame();
+		Player p = ai?new RandomAI():new ClickPlayer();
+		PlayerGrid g = new PlayerGrid(gridNum, new GUIPlayer(new RandomAI(), Color.RED), new GUIPlayer(p, Color.BLUE));
+		GUIGrid guig = new GUIGrid(g);
+		g.runGame();
+		window.add(guig);
+		window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
+		window.setVisible(true);
+		window.repaint();
+		window.pack();
+	}
+	
+	private final Grid gameGrid;
+	private final ArrayList<GUIGrid> subgrids;
+	private final Point loc;
+	private int borderSize = 5;
+	private int ownerId;
+	private byte selected = DESELECTED;
+	private Stroke gridStroke;
+	
+	public GUIGrid(PlayerGrid g)
+	{
+		this(g, null);
+	}
+
+	private GUIGrid(Grid g, Point p)
+	{
+		super(new TableLayout(new double[][] {
+				{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL},
+				{TableLayout.FILL, TableLayout.FILL, TableLayout.FILL}
+			}));
+		setBackground(new Color(0, 0, 0, 0));
+		subgrids = new ArrayList<GUIGrid>();
+		setBorder(BorderFactory.createEmptyBorder(borderSize, borderSize, borderSize, borderSize));
+		gameGrid = g;
+		ownerId = -1;
+		loc = p;
+		gameGrid.addGridListener(new GridListener()
+		{
+			@Override
+			public void markerAdded(GridEvent ge)
+			{
+				Point loc = ge.getSource().getLocation();
+				Player p = ((PlayerGrid) getHighestParent().gameGrid).getPlayer(ge.getSource().getOwner());
+				if (p instanceof GUIPlayer)
+				{
+					add(new MarkerGUI(((GUIPlayer) p).getColor(), loc.x, loc.y), loc.x+", "+loc.y);
+				}
+				revalidate();
+				repaint();
+            }
+
+			@Override
+            public void gridSelected(GridEvent ge, byte state)
+            {
+				selected = state;
+				getHighestParent().repaint();
+            }
+
+			@Override
+            public void gridOwned(int id)
+            {
+				if (getParent() instanceof GUIGrid)
+				{
+					ownerId = id;
+				}
+				else
+				{
+					JOptionPane.showMessageDialog(null, "Player "+(id+1)+" Won!");
+				}
+            }
+		});
+		for (int row = 0; row < 3; row++)
+		{
+			for (int col = 0; col < 3; col++)
+			{
+				GridObject go = g.getObjectAt(col, row);
+				if (go == null)
+				{
+					add(new Placeholder(col, row), col+", "+row);
+				}
+				else if (go instanceof Grid)
+				{
+					GUIGrid guig = new GUIGrid((Grid) go, new Point(col, row));
+					subgrids.add(guig);
+					add(guig, col+", "+row);
+				}
+			}
+		}
+		gridStroke = new BasicStroke(gameGrid.getDepth());
+		if (subgrids.size() == 0)
+		{
+			setPreferredSize(new Dimension(100, 100));
+		}
+		else
+		{
+			int largest = 100;
+			for (Component c : getComponents())
+			{
+				largest = Math.max(largest, c.getPreferredSize().height);
+			}
+			setPreferredSize(new Dimension(largest, largest));
+		}
+	}
+	
+	private GUIGrid getHighestParent()
+	{
+		if (getParent() instanceof GUIGrid)
+		{
+			return ((GUIGrid) getParent()).getHighestParent();
+		}
+		else
+		{
+			return this;
+		}
+	}
+	
+	@Override
+	public void paintComponent(Graphics g)
+	{
+		g.clearRect(1, 1, getWidth()-2, getHeight()-2);
+		if (selected == SELECTED)
+		{
+			g.setColor(new Color(200, 200, 0, 75));
+			g.fillRect(2, 2, getWidth()-3, getHeight()-3);
+		}
+		else if (selected == AVALIABLE)
+		{
+			g.setColor(new Color(0, 200, 200, 75));
+			g.fillRect(2, 2, getWidth()-3, getHeight()-3);
+			
+		}
+		if (ownerId != -1)
+		{
+			((Graphics2D) g).setStroke(new BasicStroke(gameGrid.getDepth()+1));
+			Player p = ((PlayerGrid) getHighestParent().gameGrid).getPlayer(ownerId);
+			if (p instanceof GUIPlayer)
+			{
+				g.setColor(((GUIPlayer) p).getColor());
+			}
+			g.drawRect(1, 1, getWidth()-2, getHeight()-2);
+		}
+		((Graphics2D) g).setStroke(gridStroke);
+		super.paintComponent(g);
+		((TableLayout) getLayout()).drawGrid(this, g, true, false);
+	}
+	
+	public ArrayList<Point> getGridLocation()
+	{
+		if (getParent() instanceof GUIGrid)
+		{
+			ArrayList<Point> result = ((GUIGrid) getParent()).getGridLocation();
+			result.add(loc);
+			return result;
+		}
+		else
+		{
+			return new ArrayList<Point>();
+		}
+	}
+	
+	private class MarkerGUI extends Placeholder
+	{
+		private static final long serialVersionUID = 593200601971906754L;
+		
+		public MarkerGUI(Color col, int x, int y)
+		{
+			super(x, y);
+			setBackground(col);
+		}
+		
+		@Override
+		public void paint(Graphics g)
+		{
+			super.paint(g);
+			g.setColor(getBackground());
+			int doubleBorder = 2*borderSize;
+			g.fillRect(borderSize, borderSize, getWidth()-doubleBorder, getHeight()-doubleBorder);
+		}
+	}
+	private class Placeholder extends Component
+	{
+		private static final long serialVersionUID = -4243594387683315602L;
+
+		private final Point loc;
+		
+		public Placeholder(int x, int y)
+		{
+			loc = new Point(x, y);
+			addMouseListener(new MouseAdapter()
+			{
+				@Override
+				public void mouseClicked(MouseEvent me)
+				{
+					ClickPlayer.click(Placeholder.this);
+				}
+			});
+		}
+
+		public Point[] getGridLocation()
+		{
+			ArrayList<Point> result = GUIGrid.this.getGridLocation();
+			result.add(loc);
+			return result.toArray(new Point[0]);
+		}
+	}
+}

+ 429 - 0
src/game/Grid.java

@@ -0,0 +1,429 @@
+package game;
+
+import java.awt.Point;
+import java.util.ArrayList;
+
+public class Grid implements GridConstants
+{
+	public static interface GridObject
+	{
+		public Point getLocation();
+		
+		public int getOwner();
+		
+		public boolean isFilled();
+		
+		public void setSelected(byte state);
+		
+		public byte getSelected();
+		
+		public int getDepth();
+	}
+	
+	protected class Subgrid extends Grid implements GridObject
+	{
+		private final Point loc;
+		private byte selected;
+		private Grid parent;
+		
+		public Subgrid(int levels, int x, int y, Grid parent)
+		{
+			super(levels);
+			selected = levels == 1 ? SELECTED : DESELECTED;
+			loc = new Point(x, y);
+			owner = -1;
+			this.parent = parent;
+		}
+		
+		@Override
+		public Point getLocation()
+		{
+			return loc;
+		}
+		
+		@Override
+		protected boolean checkVictory()
+		{
+			boolean result = super.checkVictory();
+			if (result)
+			{
+				parent.checkVictory();
+			}
+			return result;
+		}
+		
+		@Override
+		public boolean addMarker(int x, int y, int id)
+		{
+			if (selected == SELECTED)
+			{
+				boolean result = super.addMarker(x, y, id);
+				if (result)
+				{
+					ArrayList<Point> points = new ArrayList<Point>();
+					points.add(0, new Point(x, y));
+					passSelected(points);
+				}
+				return result;
+			}
+			else
+			{
+				return false;
+			}
+		}
+		
+		private void passSelected(ArrayList<Point> points)
+		{
+			points.add(0, loc);
+			if (parent instanceof Subgrid)
+			{
+				((Subgrid) parent).passSelected(points);
+			}
+			else
+			{
+				parent.setSelected(points, SELECTED);
+			}
+		}
+		
+		@Override
+		public void setSelected(byte state)
+		{
+			selected = state;
+			for (GridObject[] gos : griddedObjects)
+			{
+				for (GridObject go : gos)
+				{
+					if (go != null)
+					{
+						go.setSelected(state);
+					}
+				}
+			}
+			GridEvent ge = new GridEvent(this);
+			for (GridListener gl : listeners)
+			{
+				gl.gridSelected(ge, state);
+			}
+		}
+		
+		@Override
+		public byte getSelected()
+		{
+			return selected;
+		}
+	}
+	
+	private static class Marker implements GridObject
+	{
+		private final int playerId;
+		private final Point loc;
+		
+		public Marker(int id, int x, int y)
+		{
+			playerId = id;
+			loc = new Point(x, y);
+		}
+		
+		@Override
+		public Point getLocation()
+		{
+			return loc;
+		}
+		
+		@Override
+		public int getOwner()
+		{
+			return playerId;
+		}
+		
+		@Override
+		public boolean isFilled()
+		{
+			return true;
+		}
+		
+		@Override
+		public void setSelected(byte state)
+		{
+		}
+		
+		@Override
+		public byte getSelected()
+		{
+			return DESELECTED;
+		}
+		
+		@Override
+		public int getDepth()
+		{
+			return 0;
+		}
+	}
+	
+	protected final GridObject[][] griddedObjects;
+	protected transient final ArrayList<GridListener> listeners;
+	private int owner;
+	
+	public Grid(int levels)
+	{
+		griddedObjects = new GridObject[3][3];
+		listeners = new ArrayList<GridListener>();
+		if (levels > 1)
+		{
+			for (int x = 0; x < griddedObjects.length; x++)
+			{
+				for (int y = 0; y < griddedObjects[x].length; y++)
+				{
+					griddedObjects[x][y] = new Subgrid(levels - 1, x, y, this);
+				}
+			}
+		}
+		owner = -1;
+	}
+	
+	protected boolean checkVictory()
+	{
+		if (owner == -1)
+		{
+			for (int c = 0; c < 3; c++)
+			{
+				if (griddedObjects[c][0] != null
+				        && griddedObjects[c][1] != null
+				        && griddedObjects[c][2] != null
+				        && griddedObjects[c][0].getOwner() >= 0
+				        && griddedObjects[c][0].getOwner() == griddedObjects[c][1]
+				                .getOwner()
+				        && griddedObjects[c][0].getOwner() == griddedObjects[c][2]
+				                .getOwner())
+				{
+					owner = griddedObjects[c][0].getOwner();
+					for (GridListener gl : listeners)
+					{
+						gl.gridOwned(owner);
+					}
+					return true;
+				}
+				else if (griddedObjects[0][c] != null
+				        && griddedObjects[1][c] != null
+				        && griddedObjects[2][c] != null
+				        && griddedObjects[0][c].getOwner() >= 0
+				        && griddedObjects[0][c].getOwner() == griddedObjects[1][c]
+				                .getOwner()
+				        && griddedObjects[0][c].getOwner() == griddedObjects[2][c]
+				                .getOwner())
+				{
+					owner = griddedObjects[0][c].getOwner();
+					for (GridListener gl : listeners)
+					{
+						gl.gridOwned(owner);
+					}
+					return true;
+				}
+			}
+			if ((griddedObjects[0][0] != null
+			        && griddedObjects[1][1] != null
+			        && griddedObjects[2][2] != null
+			        && griddedObjects[1][1].getOwner() >= 0
+			        && griddedObjects[0][0].getOwner() == griddedObjects[1][1]
+			                .getOwner() && griddedObjects[1][1].getOwner() == griddedObjects[2][2]
+			        .getOwner())
+			        || (griddedObjects[0][2] != null
+			                && griddedObjects[1][1] != null
+			                && griddedObjects[2][0] != null
+			                && griddedObjects[1][1].getOwner() >= 0
+			                && griddedObjects[0][2].getOwner() == griddedObjects[1][1]
+			                        .getOwner() && griddedObjects[1][1]
+			                .getOwner() == griddedObjects[2][0].getOwner()))
+			{
+				owner = griddedObjects[1][1].getOwner();
+				for (GridListener gl : listeners)
+				{
+					gl.gridOwned(owner);
+				}
+				return true;
+			}
+		}
+		return false;
+	}
+	
+	/*
+	 * protected boolean checkTie()
+	 * {
+	 * }
+	 */
+	
+	public int getOwner()
+	{
+		return owner;
+	}
+	
+	public void clearSelection()
+	{
+		for (GridObject[] gos : griddedObjects)
+		{
+			for (GridObject go : gos)
+			{
+				if (go != null)
+				{
+					go.setSelected(DESELECTED);
+					if (go instanceof Grid)
+					{
+						((Grid) go).clearSelection();
+					}
+				}
+			}
+		}
+	}
+	
+	public void addGridListener(GridListener gl)
+	{
+		listeners.add(gl);
+	}
+	
+	public void removeGridListener(GridListener gl)
+	{
+		listeners.remove(gl);
+	}
+	
+	public int getDepth()
+	{
+		return griddedObjects.length > 0 && griddedObjects[0].length > 0
+		        && griddedObjects[0][0] != null ? griddedObjects[0][0]
+		        .getDepth() + 1 : 1;
+	}
+
+	public GridObject getObjectAt(int x, int y)
+	{
+		if (x < 0 || y < 0 || x >= 3 || y >= 3)
+		{
+			throw new IllegalArgumentException();
+		}
+		else
+		{
+			return griddedObjects[x][y];
+		}
+	}
+	
+	private GridObject getObjectAt(Point[] loc, int i)
+	{
+		if (loc.length > i)
+		{
+			GridObject go = getObjectAt(loc[i].x, loc[i].y);
+			if (go instanceof Grid)
+			{
+				return ((Grid) go).getObjectAt(loc, i+1);
+			}
+			else
+			{
+				throw new IllegalArgumentException();
+			}
+		}
+		else
+		{
+			return getObjectAt(loc[i].x, loc[i].y);
+		}
+	}
+	
+	public GridObject getObjectAt(Point[] loc)
+	{
+		return getObjectAt(loc, 0);
+	}
+	
+	public boolean addMarker(int x, int y, int id)
+	{
+		boolean result = !(griddedObjects[x][y] instanceof GridObject);
+		if (result)
+		{
+			griddedObjects[x][y] = new Marker(id, x, y);
+		}
+		GridEvent ge = new GridEvent(griddedObjects[x][y]);
+		for (GridListener gl : listeners)
+		{
+			gl.markerAdded(ge);
+		}
+		checkVictory();
+		return result;
+	}
+	
+	public int getOwner(int x, int y)
+	{
+		return griddedObjects[x][y].getOwner();
+	}
+	
+	public boolean isFilled()
+	{
+		for (GridObject[] gos : griddedObjects)
+		{
+			for (GridObject go : gos)
+			{
+				if (go == null || !go.isFilled())
+				{
+					return false;
+				}
+			}
+		}
+		return true;
+	}
+	
+	@SuppressWarnings("unchecked")
+	public void setSelected(ArrayList<Point> p, byte state)
+	{
+		p.remove(0);
+		ArrayList<Point> clone = (ArrayList<Point>) ((ArrayList<Point>) p)
+		        .clone();
+		if (griddedObjects[p.get(0).x][p.get(0).y].isFilled())
+		{
+			for (GridObject[] gos : griddedObjects)
+			{
+				for (GridObject go : gos)
+				{
+					if (go != null)
+					{
+						if (go.isFilled())
+						{
+							go.setSelected(DESELECTED);
+						}
+						else if (go instanceof Grid && p.size() > 1)
+						{
+							((Grid) go).setSelected(clone, AVALIABLE);
+							clone = (ArrayList<Point>) ((ArrayList<Point>) p)
+							        .clone();
+						}
+						else
+						{
+							go.setSelected(AVALIABLE);
+						}
+					}
+				}
+			}
+		}
+		else
+		{
+			for (int col = 0; col < 3; col++)
+			{
+				for (int row = 0; row < 3; row++)
+				{
+					if (col == p.get(0).x && row == p.get(0).y)
+					{
+						if (griddedObjects[col][row] instanceof Grid)
+						{
+							if (p.size() > 1)
+							{
+								((Grid) griddedObjects[col][row]).setSelected(
+								        clone, state);
+							}
+							else
+							{
+								griddedObjects[col][row].setSelected(state);
+							}
+						}
+					}
+					else
+					{
+						griddedObjects[col][row].setSelected(DESELECTED);
+					}
+				}
+			}
+		}
+	}
+}

+ 8 - 0
src/game/GridConstants.java

@@ -0,0 +1,8 @@
+package game;
+
+public interface GridConstants
+{
+	public static byte DESELECTED = 0;
+	public static byte SELECTED = 1;
+	public static byte AVALIABLE = 2;
+}

+ 18 - 0
src/game/GridEvent.java

@@ -0,0 +1,18 @@
+package game;
+
+import game.Grid.GridObject;
+
+public class GridEvent
+{
+	private final GridObject source;
+	
+	public GridEvent(GridObject source)
+	{
+		this.source = source;
+	}
+	
+	public GridObject getSource()
+	{
+		return source;
+	}
+}

+ 8 - 0
src/game/GridListener.java

@@ -0,0 +1,8 @@
+package game;
+
+public interface GridListener
+{
+	public void markerAdded(GridEvent ge);
+	public void gridSelected(GridEvent ge, byte state);
+	public void gridOwned(int id);
+}

+ 193 - 0
src/game/PlayerGrid.java

@@ -0,0 +1,193 @@
+package game;
+
+import java.awt.Point;
+import java.util.ArrayList;
+
+import arrays.ArrayMethods;
+
+public class PlayerGrid extends Grid
+{
+	@SuppressWarnings("unchecked")
+    private static ArrayList<Point[]> getAvaliables(Grid g, ArrayList<Point> heighers)
+	{
+		ArrayList<Point[]> result = new ArrayList<Point[]>();
+		if (heighers == null)
+		{
+			heighers = new ArrayList<Point>();
+		}
+		
+		for (int x = 0; x < 3; x++)
+		{
+			for (int y = 0; y < 3; y++)
+			{
+				if (g.griddedObjects[x][y] instanceof Grid)
+				{
+					ArrayList<Point> clone = (ArrayList<Point>) heighers.clone();
+					clone.add(g.griddedObjects[x][y].getLocation());
+					result.addAll(getAvaliables((Grid) g.griddedObjects[x][y], clone));
+				}
+			}
+		}
+		
+		if (g instanceof GridObject && ((GridObject) g).getSelected() == AVALIABLE)
+		{
+			result.add(heighers.toArray(new Point[0]));
+		}
+		return result;
+	}
+    
+    private static ArrayList<Point[]> getSelected(Grid g, ArrayList<Point> heighers)
+	{
+		ArrayList<Point[]> result = new ArrayList<Point[]>();
+		if (g.getDepth() == 0)
+		{
+			for (int x = 0; x < g.griddedObjects.length; x++)
+			{
+				for (int y = 0; y < g.griddedObjects[x].length; y++)
+				{
+					if (g.griddedObjects[x][y] == null)
+					{
+						result.add(new Point[] {new Point(x, y)});
+					}
+				}
+			}
+			return result;
+		}
+		if (heighers == null)
+		{
+			heighers = new ArrayList<Point>();
+		}
+		else
+		{
+			heighers.add(((GridObject) g).getLocation());
+		}
+		
+		for (int x = 0; x < 3; x++)
+		{
+			for (int y = 0; y < 3; y++)
+			{
+				if (g.griddedObjects[x][y] instanceof Grid)
+				{
+				    @SuppressWarnings("unchecked")
+					ArrayList<Point> clone = (ArrayList<Point>) heighers.clone();
+					result.addAll(getSelected((Grid) g.griddedObjects[x][y], clone));
+				}
+			}
+		}
+		
+		if (g instanceof GridObject && ((GridObject) g).getSelected() == SELECTED)
+		{
+			Point p;
+			for (int x = 0; x < 3; x++)
+			{
+				for (int y = 0; y < 3; y++)
+				{
+					if (g.griddedObjects[x][y] == null)
+					{
+						p = new Point(x, y);
+						heighers.add(p);
+						result.add(heighers.toArray(new Point[0]));
+						heighers.remove(p);
+					}
+				}
+			}
+		}
+		return result;
+	}
+
+    public static interface Player
+	{
+    	public void setGrid(Grid g);
+		public Point[] placeMarker(Point[][] arrayList);
+		public Point[] pickSector(Point[][] options);
+		public void markerPlaced(Point[] position, int player);
+	}
+	
+	private Player[] players;
+	private int turnCount;
+	
+	public PlayerGrid(int levels, Player... players)
+    {
+	    super(levels);
+	    this.players = players;
+	    for (Player p : players)
+	    {
+	    	p.setGrid(this);
+	    }
+	    turnCount = 0;
+    }
+	
+	private Grid getGrid(Point[] loc, int n)
+	{
+		Grid result = this;
+		for (int i = 0; i < n; i++)
+		{
+			result = (Grid) result.griddedObjects[loc[i].x][loc[i].y];
+		}
+		return result;
+	}
+	
+	public Thread runGame()
+	{
+		Thread result = new Thread()
+		{
+			@Override
+			public void run()
+			{
+				while (getOwner() < 0 && !isInterrupted())
+				{
+					Point[] loc = getCurrentPlayer().placeMarker(getSelected(PlayerGrid.this, null).toArray(new Point[0][0]));
+					int n = loc.length-1;
+					boolean result = getGrid(loc, n).addMarker(loc[n].x, loc[n].y, turnCount % players.length);
+					Point[][] selectableAreas = getAvaliables(PlayerGrid.this, null).toArray(new Point[0][0]);
+					while (selectableAreas.length > 0)
+					{
+						loc = getCurrentPlayer().pickSector(selectableAreas);
+						GridObject chosen = ((GridObject) getGrid(loc, loc.length));
+						if (!chosen.isFilled())
+						{
+							clearSelection();
+							chosen.setSelected(SELECTED);
+							selectableAreas = new Point[0][0];
+							for (Player player : players)
+							{
+								player.markerPlaced(loc, getCurrentPlayerId());
+							}
+						}
+					}
+					if (result)
+					{
+						turnCount++;
+					}
+				}
+			}
+		};
+		result.start();
+		return result;
+	}
+
+	public int getCurrentTurn()
+	{
+		return turnCount;
+	}
+	
+	public Player getPlayer(int i)
+	{
+		return players[i];
+	}
+
+	public int getPlayerId(Player p)
+	{
+		return ArrayMethods.getIndex(players, p);
+	}
+	
+	public int getCurrentPlayerId()
+	{
+		return turnCount % players.length;
+	}
+	
+	public Player getCurrentPlayer()
+	{
+		return players[turnCount % players.length];
+	}
+}