Ejemplo n.º 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="PixPuzzle.Data.Path"/> class.
        /// </summary>
        /// <param name="firstCell">First cell.</param>
        /// <param name="expectedLength">Expected length.</param>
        public Path(Cell firstCell, int expectedLength)
        {
            if (firstCell == null) {
                throw new ArgumentException ();
            }
            Cells = new List<Cell> ();
            Cells.Add (firstCell);
            Color = firstCell.Color;

            ExpectedLength = expectedLength;
        }
Ejemplo n.º 2
0
		/// <summary>
		/// Create a grid and register view data
		/// </summary>
		public void CreateGrid (int locationX, int locationY, IGridView view)
		{
			Logger.I ("Creating the " + Width + "x" + Height + " grid...");

			// Calculate border size
			// TODO This sucks
			BorderWidth = 4;
			int borderStartX = GridLocation.X + (BorderWidth / 2);
			int borderStartY = GridLocation.Y + (BorderWidth / 2);
			BorderStartLocation = new Point (borderStartX, borderStartY);
			GridLocation = BorderStartLocation;

			// Create the grid
			Cells = new Cell[Width][];

			for (int x=0; x<Width; x++) {

				Cells [x] = new Cell[Height];

				for (int y=0; y<Height; y++) {

					Cell c = new Cell ();
					c.X = x;
					c.Y = y;
					Cells [x] [y] = c;

					c.Rect = new Rectangle (
						GridLocation.X + c.X * CellSize, 
						GridLocation.Y + c.Y * CellSize, 
						CellSize, CellSize);
				}
			}

			// Initialize the view
			if (view == null) {
				throw new ArgumentException ();
			}

			this.View = view;
		}
Ejemplo n.º 3
0
        public void DrawLastCellIncompletePath(Cell cell, Rectangle rect, string pathValue, CellColor color)
        {
            UIColor colorUnderText = UIColor.LightGray;

            // Draw a gray circle!
            int circleReductionValue = mParent.CellSize / 8;
            mContext.SetFillColor (colorUnderText.CGColor);
            mContext.FillEllipseInRect (new RectangleF(rect.X + circleReductionValue, rect.Y + circleReductionValue, mParent.CellSize-2*circleReductionValue, mParent.CellSize-2*circleReductionValue));

            // Draw the text
            mContext.SetFillColor (UIColor.Black.CGColor);
            mContext.SelectFont ("Helvetica Neue", 12.0f, CGTextEncoding.MacRoman);
            mContext.ShowTextAtPoint (rect.X + mParent.CellSize/3, rect.Y + 2 * mParent.CellSize / 3, pathValue);
        }
Ejemplo n.º 4
0
        public void DrawCellText(Cell cell, Rectangle location, string text, CellColor color)
        {
            mContext.SelectFont ("Helvetica Neue", 16.0f, CGTextEncoding.MacRoman);

            // Get the reverse color of the background
            float sumOfComponents = 0;
            float r, g, b, a;
            color.UIColor.GetRGBA (out r, out g, out b, out a);
            sumOfComponents = r + g + b;

            UIColor textColor = UIColor.Black;
            if (sumOfComponents < 0.25f)
            {
                textColor = UIColor.White;
            } else {
                textColor = UIColor.Black;
            }

            mContext.SetFillColor (textColor.CGColor);

            // Careful with the coordinates!!!
            // Remember it's a real mess because it's inverted
            mContext.ShowTextAtPoint (location.X + mParent.CellSize/3, location.Y + 2 * mParent.CellSize / 3, text);
        }
Ejemplo n.º 5
0
        /// <summary>
        /// Removes all the cells that are after the given one
        /// </summary>
        /// <param name="cell">Cell.</param>
        public List<Cell> RemoveCellAfter(Cell cell)
        {
            int index = Cells.IndexOf (cell);

            List<Cell> cellsToRemove = new List<Cell> ();

            for (int i=index+1; i < Cells.Count; i++) {
                cellsToRemove.Add (Cells[i]);
            }

            foreach (var cellToRemove in cellsToRemove) {
                Cells.Remove (cellToRemove);

                cellToRemove.Path = null;
            }

            return cellsToRemove;
        }
Ejemplo n.º 6
0
        public Cell PreviousCell(Cell cell)
        {
            if (Cells.Contains (cell) == false)
                return null;

            int index = Cells.IndexOf (cell);

            if(index - 1 >= 0) {
                return Cells [index - 1];
            }
            return null;
        }
Ejemplo n.º 7
0
        public Cell NextCell(Cell cell)
        {
            if (Cells.Contains (cell) == false)
                return null;

            int index = Cells.IndexOf (cell);

            if(index + 1 < Cells.Count) {
                return Cells [index + 1];
            }
            return null;
        }
Ejemplo n.º 8
0
		/// <summary>
		/// Request the grid to be updated, especially some cells that may have been modified
		/// </summary>
		public virtual void UpdateView (Cell[] cellsToRefresh)
		{
			Rectangle zoneToRefresh = Rectangle.Empty;

			// Get a complete rectangle of cells
			foreach (Cell cell in cellsToRefresh) {

				int x = GridLocation.X + cell.X * CellSize;
				int y = GridLocation.Y + cell.Y * CellSize;

				Rectangle cellRect = new Rectangle (x, y, CellSize, CellSize);

				if (zoneToRefresh == Rectangle.Empty) {
					zoneToRefresh = cellRect;
				} else {
#if IOS
					if (zoneToRefresh.Contains (cellRect) == false || zoneToRefresh.IntersectsWith (cellRect) == false) {
#elif WINDOWS_PHONE
					if (zoneToRefresh.Contains (cellRect) == false || zoneToRefresh.Intersects (cellRect) == false) {
#endif
						zoneToRefresh = Rectangle.Union (cellRect, zoneToRefresh);
					}
				}
			} // foreach

			RefreshZone (zoneToRefresh);
		}

		void RefreshZone (Rectangle zoneToRefresh)
		{
			// Find cells to refresh in this rect
			int startX = zoneToRefresh.X / CellSize;
			int startY = zoneToRefresh.Y / CellSize;
			for (int x = startX; x < startX + (zoneToRefresh.Width / CellSize); x++) {
				for (int y = startY; y < startY + (zoneToRefresh.Height / CellSize); y++) {
					Cell c = GetCell (x, y);
					if (c != null) {
						c.IsToDraw = true;
					}
				}
			}
			// Trigger the refresh 
			if (zoneToRefresh != Rectangle.Empty) {
				View.Refresh (zoneToRefresh);
			}
		}
Ejemplo n.º 9
0
 public void UnselectCell(Cell cell, bool complete, bool cancel)
 {
 }
Ejemplo n.º 10
0
 /// <summary>
 /// Add a cell to the path
 /// </summary>
 /// <param name="cell">Cell.</param>
 public void AddCell(Cell cell)
 {
     Cells.Add (cell);
     cell.Path = this;
 }
Ejemplo n.º 11
0
		/// <summary>
		/// Removes the path linked to the given cell
		/// </summary>
		/// <param name="cell">Cell.</param>
		public void RemovePath (Cell cell)
		{
			if (cell != null) {
				if (cell.Path != null) {
					List<Cell> removedCells = cell.Path.DeleteItself ();
					UpdateView (removedCells.ToArray ());
				}
			}
		}
Ejemplo n.º 12
0
		/// <summary>
		/// Ends the current path creation
		/// </summary>
		/// <param name="success">If set to <c>true</c> success.</param>
		public void EndPathCreation (bool success = false)
		{
			// Make sure we're doing path work
			if (FirstPathCell != null && LastSelectedCell != null) {
				// Check if grid is complete
				// = if all cells are in a valid path
				bool isComplete = true;
				for (int x=0; x<Width; x++) {
					for (int y=0; y<Height; y++) {
						if (Cells [x] [y].Path != null) {
							isComplete &= (Cells [x] [y].Path.IsValid);
						} else {
							// Cell linked to no path, the grid is obvisouly not complete
							isComplete = false;
							break;
						}
					}
				}

				if (isComplete) {
					EndGrid ();
				}

				View.UnselectCell (LastSelectedCell, success, false);

				// Forget cells
				LastSelectedCell = null;
				FirstPathCell = null;
			}
		}
Ejemplo n.º 13
0
		/// <summary>
		/// Create a path between the current known path and the given cell.
		/// </summary>
		/// <param name="cell">Cell.</param>
		public void CreatePath (Cell cell)
		{
			bool cancelMove = false;
			string cancelReason = string.Empty;

			// The path length must be respected
			bool lengthOk = (FirstPathCell.Path.Length < FirstPathCell.Path.ExpectedLength);

			if (lengthOk == false) {
				cancelMove = true;
				cancelReason = "The path is too long!";
			} else {
				// We're in the grid and we moved (not the same cell)
				if (cell != null && cell != LastSelectedCell) {

					// Make sure we are one cell away from the previous one
					int x = cell.X - LastSelectedCell.X;
					int y = cell.Y - LastSelectedCell.Y;

					if (Math.Abs (x) > 1 || Math.Abs (y) > 1) {
						cancelMove = true;
						cancelReason = "Cannot create a path that is not in a cell next the to the first one.";
					} else {
						if (cell.Path == null) {
							// The cell is available for path

							// Add the cell to the currently edited path
							FirstPathCell.Path.AddCell (cell);
							cell.Path = FirstPathCell.Path;

							// Update the modified cells
							UpdateView (cell.Path.Cells.ToArray ());

						} else {

							// Already a path in the target cell
							bool sameColor = cell.Path.Color.Equals (FirstPathCell.Path.Color);
							bool sameLength = (cell.Path.ExpectedLength == FirstPathCell.Path.ExpectedLength);

							// Is this an end? We need to be sure we close the path
							bool fusion = false;
							if (cell.IsPathStartOrEnd) 
							{
								fusion = sameColor && sameLength && FirstPathCell != cell
									&& (FirstPathCell.Path.Length + cell.Path.Length == FirstPathCell.Path.ExpectedLength);

								if (fusion == false) {
									cancelMove = true;
									cancelReason = "Cannot close the path: invalid lengths.";
								}
							} else {
								fusion = sameColor && sameLength && FirstPathCell != cell;

								if (fusion == false) {
									cancelMove = true;
									cancelReason = "Cannot mix two differents path.";
								}
							}

							// -- It's a completely different path, do not override
							if (fusion) {

								// Fusion between two paths parts
								Logger.I ("Fusion!");
								FirstPathCell.Path.Fusion (cell.Path);
								cell.Path = FirstPathCell.Path;

								// Update the modified cells
								UpdateView (FirstPathCell.Path.Cells.ToArray ());

								// Are we ending the path?
								if (FirstPathCell.Path.IsValid) {
									// End the creation, the path is complete
									Logger.I ("Path complete!");
									EndPathCreation (true);
								}
								
							} else if (FirstPathCell.Path.Cells.Contains (cell) 
								&& Math.Abs (FirstPathCell.Path.IndexOf (LastSelectedCell) - FirstPathCell.Path.IndexOf (cell)) == 1
								&& cancelMove == false) {
								
								// We're getting back 
								// Remove all the cells past the one we jut reached
								// The current cell will NOT be removed
								List<Cell> removedCells = FirstPathCell.Path.RemoveCellAfter (cell);

								// Update the modified cells
								// And the removed ones
								List<Cell> cellsToUpdate = new List<Cell> ();
								cellsToUpdate.AddRange (cell.Path.Cells);
								cellsToUpdate.AddRange (removedCells);

								UpdateView (cellsToUpdate.ToArray ());
							}
						}
					}
				} else if (cell != FirstPathCell && cell != LastSelectedCell) {
					// The cell is invalid (probably out of the grid)
					// Stop the path
					cancelMove = true;
					cancelReason = "Invalid cell for path";

					
				}
			}

			if (cancelMove) {
				Logger.I (cancelReason);
				EndPathCreation (false);
				View.UnselectCell (cell, false, true);
			}
		
			LastSelectedCell = cell;
		}
Ejemplo n.º 14
0
		/// <summary>
		/// Starts a new path creation.
		/// </summary>
		/// <returns><c>true</c>, if a path was started, <c>false</c> otherwise.</returns>
		/// <param name="cell">Cell.</param>
		public bool StartPathCreation (Cell cell)
		{
			if (cell != null) {

				if (cell.Path != null) {

					// Check if the cell has a valid path object.
					// If not or already closed path, do nothing
					// (you cannot take a cell without path and start messing around)
					bool isPathClosed = cell.Path.IsClosed;
					bool isPathLastCell = cell.Path.IsLastCell (cell);

					if (isPathClosed == false && isPathLastCell) {
						FirstPathCell = cell.Path.FirstCell;

						LastSelectedCell = cell;

						View.SelectCell (cell);

						return true;
					} 
				}
			}

			return false;
		}
Ejemplo n.º 15
0
        public void DrawPath(Cell cell, Rectangle pathRect, Point direction, CellColor color)
        {
            mContext.DrawImage (pathRect, UIImageEx.GetImageWithOverlayColor(mPathImage, color.UIColor).CGImage);

            // The old drawing code for perfect paths
            //			context.SetFillColor (color.UIColor.CGColor);

            // Draw in 2 parts:
            // First a rect
            //			context.FillRect (pathRect);
            //
            //			// Then an arc to the end
            //			if (direction.X < 0) {
            //				context.MoveTo (pathRect.Right, pathRect.Top);
            //				context.AddCurveToPoint (
            //					pathRect.Right + pathRect.Width / 3,
            //					pathRect.Top + pathRect.Height / 3,
            //					pathRect.Right + pathRect.Width / 3,
            //					pathRect.Top + 2 * pathRect.Height / 3,
            //					pathRect.Right,
            //					pathRect.Bottom
            //					);
            //			} else if (direction.X > 0) {
            //				context.MoveTo (pathRect.Left, pathRect.Top);
            //				context.AddCurveToPoint (
            //					pathRect.Left - pathRect.Width / 3,
            //					pathRect.Top + pathRect.Height / 3,
            //					pathRect.Left - pathRect.Width / 3,
            //					pathRect.Top + 2 * pathRect.Height / 3,
            //					pathRect.Left,
            //					pathRect.Bottom
            //					);
            //			}
            //			if (direction.Y < 0) {
            //				context.MoveTo (pathRect.Left, pathRect.Bottom);
            //				context.AddCurveToPoint (
            //					pathRect.Left + pathRect.Width / 3,
            //					pathRect.Bottom + pathRect.Height / 3,
            //					pathRect.Left + 2 * pathRect.Width / 3,
            //					pathRect.Bottom + pathRect.Height / 3,
            //					pathRect.Right,
            //					pathRect.Bottom
            //					);
            //			} else if (direction.Y > 0) {
            //				context.MoveTo (pathRect.Left, pathRect.Top);
            //				context.AddCurveToPoint (
            //					pathRect.Left + pathRect.Width / 3,
            //					pathRect.Top - pathRect.Height / 3,
            //					pathRect.Left + 2 * pathRect.Width / 3,
            //					pathRect.Top - pathRect.Height / 3,
            //					pathRect.Right,
            //					pathRect.Top
            //					);
            //			}
            //
            //			context.FillPath ();
        }
Ejemplo n.º 16
0
 /// <summary>
 /// Place in the chain
 /// </summary>
 /// <returns>The of.</returns>
 /// <param name="cell">Cell.</param>
 public int IndexOf(Cell cell)
 {
     return Cells.IndexOf (cell);
 }
Ejemplo n.º 17
0
 public void SelectCell(Cell cell)
 {
 }
Ejemplo n.º 18
0
        /// <summary>
        /// Check if the cell is the last of the path
        /// </summary>
        /// <returns><c>true</c> if this instance is last cell the specified cell; otherwise, <c>false</c>.</returns>
        /// <param name="cell">Cell.</param>
        public bool IsLastCell(Cell cell)
        {
            if (Cells.Count == 0)
                return false;

            return Cells [Cells.Count -1] == cell;
        }
Ejemplo n.º 19
0
        public void DrawCellBase(Cell cell)
        {
            bool isValid = cell.Path != null && cell.Path.IsValid;
            CellColor cellColor = cell.Color;

            if (cell.Path != null) {
                cellColor = cell.Path.Color;
            }

            CGColor color = cellColor.UIColor.CGColor;
            mContext.SetFillColor (color);

            if (mParent.ShouldDisplayFilledCells == false) {

                // Draw a circle of the color
                // But reduce the circle value
                int circleReductionValue = mParent.CellSize / 10;

                RectangleF cellValueRect = new RectangleF (cell.Rect.X + circleReductionValue, cell.Rect.Y + circleReductionValue, mParent.CellSize - 2 * circleReductionValue, mParent.CellSize - 2 * circleReductionValue);

                UIImage image = null;

                if (isValid == false) {
                    image = mSplashImage;

                    image = UIImageEx.GetImageWithOverlayColor (image, cellColor.UIColor);

                    mContext.DrawImage (cellValueRect, image.CGImage);

                } else {

                    mContext.FillRect (cell.Rect);
                }
            } else {

                // Fill the whole cell to preview puzzle
                mContext.FillRect (cell.Rect);
            }
        }
Ejemplo n.º 20
0
		/// <summary>
		/// Create a path from a given cell.
		/// </summary>
		/// <returns>The last cell.</returns>
		/// <param name="firstCell">First cell.</param>
		private Cell InitializePath (Cell firstCell)
		{
			Cell lastCell = firstCell;

			// Start from the first cell
			int count = 0;

			Stack<Cell> cellToExplore = new Stack<Cell> ();
			cellToExplore.Push (firstCell);

			// Try to move in another direction
			// Flood fill algorithm
			while (cellToExplore.Count > 0) {

				// Get the first cell to explore
				Cell currentCell = cellToExplore.Pop ();
				count++;

				// Mark this cell
				currentCell.IsMarked = true;

				// Get the neighbors
				// -- We use a 4-directional algorithms
				List<CellPoint> availableDirections = new List<CellPoint> () {
					new CellPoint(-1,0),
					new CellPoint(1,0),
					new CellPoint(0,-1),
					new CellPoint(0,1)
				};
				// -- Use a random direction for better results
				int borders = 0;
				while (availableDirections.Count > 0) {

					int index = mRandom.Next (availableDirections.Count);

					CellPoint p = availableDirections [index];
					availableDirections.Remove (p);

					Cell nextCell = GetCell (currentCell.X + p.X, currentCell.Y + p.Y);
					if (nextCell != null && nextCell.IsMarked == false && nextCell.Color.Equals (firstCell.Color)) {
						cellToExplore.Push (nextCell);
					} else {
						borders += 1;
					}
				}
				bool stopFloodFill = false;

				// If we got stuck in a corner
				if (borders == 4) {
					stopFloodFill = true;
				}

				// Limit maximum path lengh randomly
				int max = mRandom.Next (2, MaxPathLength);

				if (currentCell == GetCell (0, 0)) {
					max += 1;
				}

				if (count >= max) {
					stopFloodFill = true;
				}

				// Stop flood fill
				if (stopFloodFill) {
					cellToExplore.Clear ();

					// Mark as last
					lastCell = currentCell;
				}
			}

			firstCell.DefineCellAsPathStartOrEnd (count);
			lastCell.DefineCellAsPathStartOrEnd (count);

			return lastCell;
		}