/// <summary> /// Initializes a new instance of the <see cref="GameBoard"/> class. /// </summary> public GameBoard() { InitializeComponent(); _game = new Core.Game(); _grdCascades = new CascadeGrid(_game) { Margin = new Thickness(16, 16, 16, 16), HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch, VerticalAlignment = System.Windows.VerticalAlignment.Stretch }; grdMain.Children.Add(_grdCascades); Initialize(); }
/// <summary> /// Initializes a new instance of the <see cref="CascadeGrid"/> class. /// </summary> /// <param name="game">The game.</param> public CascadeGrid(FreeCell.Core.Game game) { _game = game; _game.LayoutChanged += new EventHandler(Game_LayoutChanged); for (int i = 0; i < _game.Rules.NumberOfCascades; i++) { ColumnDefinition cd = new ColumnDefinition(); cd.MouseDown += new System.Windows.Input.MouseButtonEventHandler(Column_MouseDown); this.ColumnDefinitions.Add(cd); } }
/// <summary> /// Gets the number of possible moves that can be made in the specified game /// </summary> /// <param name="game">The game to get possible moves for.</param> /// <returns>Number of possible moves for specified game</returns> public static int GetNumberOfPossibleMoves(Game game) { int moves = 0; foreach (Cell cell in game.Cells) { if (cell.HasCard) { foreach (Cascade cascade in game.Cascades) { if (game.Rules.CanMoveToCascade(cell.Card, cascade)) moves++; } foreach (Foundation foundation in game.Foundations) { if (game.Rules.CanMoveToFoundation(cell.Card, foundation)) moves++; } } } foreach (Cascade cascade in game.Cascades) { if (cascade.Count != 0) { List<Card> tableaux = GetTableauxFromCascade(cascade, game.Rules); foreach (Cascade c2 in game.Cascades) { if (cascade != c2) { if (game.Rules.CanMoveToCascade(tableaux, c2, game)) moves++; } } foreach (Foundation foundation in game.Foundations) { if (tableaux.Count != 0 && game.Rules.CanMoveToFoundation(tableaux.Last(), foundation)) moves++; } foreach (Cell cell in game.Cells) { if (!cell.HasCard) moves++; } } } return moves; }
/// <summary> /// Gets the maximum number of moves for the specified game. /// </summary> /// <param name="game">The game to get maximum number of moves for.</param> /// <param name="destinationIsEmpty">if set to <c>true</c> destination cascade is empty.</param> /// <returns></returns> public static int GetMaximumMovesForGame(Game game, bool destinationIsEmpty) { int emptyCells = (from c in game.Cells where !c.HasCard select c).Count<Cell>(); int emptyCascades = (from c in game.Cascades where c.Count == 0 select c).Count<Cascade>(); if (destinationIsEmpty) emptyCascades--; int maxMoves = ((emptyCells + 1) * (emptyCascades + 1)); if (destinationIsEmpty) maxMoves = ((emptyCells + 1) * (emptyCascades)); return maxMoves; }
/// <summary> /// Initializes a new instance of the <see cref="State"/> class. /// </summary> /// <param name="game">The game.</param> public State(Game game) { Cascades = new List<Cascade>(); foreach (Cascade c in game.Cascades) Cascades.Add(c.Clone()); Foundations = new List<Foundation>(); foreach (Foundation f in game.Foundations) Foundations.Add(f.Clone()); Cells = new List<Cell>(); foreach (Cell c in game.Cells) Cells.Add(c.Clone()); }
/// <summary> /// Checks to see if it is possible to move the specified <see cref="Card"/> to the specified <see cref="Cascade"/>. /// </summary> /// <param name="tableaux">The tableaux to try to move to the cascade.</param> /// <param name="cascade">The <see cref="Cascade"/> that will be holding the specified <see cref="Card"/></param> /// <returns><c>true</c> if the specified <see cref="Card"/> can be moved to the specified <see cref="Stack"/>; otherwise <c>false</c></returns> public virtual bool CanMoveToCascade(List<Card> tableaux, Cascade cascade, Game game) { if (!EnforceRules) return true; if (cascade.Count == 0) return true; Card landingCard = cascade.Last(); if (tableaux.Count == 1) { // MOVING ONE CARD if (this.CanMoveToCascade(tableaux.Last(), cascade)) { return true; } else { return false; } } else { // MOVING MULTIPLE CARDS... FIND THE MAXIMUM NUMBER OF MOVES AVAILABLE. int maxMoves = Utility.GetMaximumMovesForGame(game, (cascade.Count == 0)); int level = 1; // WALK BACKWARDS OVER TABLEAUX TRYING EACH CARD AS A LINK TO LANDING CARD. for (int i = (tableaux.Count - 1); i >= 0; i--) { // CHECK FOR THE LINK BETWEEN CURRENT TABLEAUX CARD AND LANDING CARD. if (this.DoCardsLinkInCascade(tableaux[i], landingCard)) { // CARDS LINK, CHECK TO SEE IF WE'VE EXCEEDED OUT MAX NUMBER OF MOVES ALLOWED. if (level > maxMoves) { // MAX NUMBER OF MOVES EXCEEDED, MOVE FAILS return false; } else { // MOVE SUCCESSFUL return true; } } else { // CARDS DO NOT LINK, CONTINUE ONTO THE NEXT TABLEAUX CARD. if (i == 0) { // THIS IS THE LAST CARD IN THE TABLEAUX, MOVE FAILS BECAUSE NO LINKING CARDS FOUND IN STACK. return false; } } level++; } } return false; }
/// <summary> /// /// </summary> /// <param name="args">The args.</param> static void Main(string[] args) { Game = new Game(); Game.LayoutChanged += new EventHandler(Game_LayoutChanged); Game.MoveFinished += new EventHandler<MoveFinishedEventArgs>(Game_MoveFinished); Game.StartGame(1947380511); DrawGame(); while (true) { switch (Console.ReadKey(true).Key) { case ConsoleKey.U: Game.Undo(); break; case ConsoleKey.LeftArrow: FocusIndex -= 1; break; case ConsoleKey.RightArrow: FocusIndex += 1; break; case ConsoleKey.UpArrow: case ConsoleKey.DownArrow: if (FocusLocation == Location.Banks || FocusLocation == Location.Cells) { FocusLocation = Location.Stacks; } else { if (FocusIndex > 3) FocusLocation = Location.Banks; else FocusLocation = Location.Cells; } break; case ConsoleKey.Enter : if (FocusIndex == SelectedIndex && FocusLocation == SelectedLocation) { SelectedIndex = -1; } else { if (SelectedIndex == -1) { SelectedLocation = FocusLocation; SelectedIndex = FocusIndex; } else { // TRY TO MOVE A CARD ITarget source = null; ITarget dest = null; if (SelectedLocation == Location.Stacks) source = Game.Cascades[SelectedIndex]; if (SelectedLocation == Location.Cells) source = Game.Cells[SelectedIndex]; if (FocusLocation == Location.Stacks) dest = Game.Cascades[FocusIndex]; if (FocusLocation == Location.Cells) dest = Game.Cells[FocusIndex]; if (FocusLocation == Location.Banks) dest = Game.Foundations[FocusIndex]; Game.Move(source, dest); } } break; case ConsoleKey.Escape: break; } if (FocusLocation == Location.Cells && FocusIndex >= Game.Rules.NumberOfCells) { FocusIndex = 0; FocusLocation = Location.Banks; } if (FocusLocation == Location.Cells && FocusIndex < 0) { FocusIndex = 3; FocusLocation = Location.Banks; } if (FocusLocation == Location.Banks && FocusIndex >= 4) { FocusIndex = 0; FocusLocation = Location.Cells; } if (FocusLocation == Location.Banks && FocusIndex < 0) { FocusIndex = (Game.Rules.NumberOfCells - 1); FocusLocation = Location.Cells; } if (FocusLocation == Location.Stacks && FocusIndex >= Game.Rules.NumberOfCascades) FocusIndex = 0; if (FocusLocation == Location.Stacks && FocusIndex < 0) FocusIndex = (Game.Rules.NumberOfCascades - 1); DrawGame(); } }