public static BindingList <T> ForEachNewOrExistingItem <T>(this BindingList <T> source, Action <T> handler) { source.ForEachNewItem(handler).ForEach(handler); return(source); }
public SolitaireGame() { Width = DefaultWidth; Height = DefaultHeight; System.Console.WriteLine("--- solitare ---"); this.MyStatus = new StatusControl().AttachContainerTo(this).MoveContainerTo( (DefaultWidth - StatusControl.Width) / 2, (DefaultHeight - StatusControl.Height) ); var GameOverBox = new TextBox { Width = DefaultWidth, TextAlignment = System.Windows.TextAlignment.Center, Foreground = Brushes.White, Background = Brushes.Transparent, BorderThickness = new Thickness(0), IsReadOnly = true, FontSize = 24, }.MoveTo(0, DefaultHeight / 2).AttachTo(this); // add autoscroll ? this.MyDeck.SizeTo(DefaultWidth, DefaultHeight); this.MyDeck.AttachContainerTo(this); this.MyDeck.GetRank = e => (int)RankMapping[e]; System.Console.WriteLine("adding card infos... "); MyDeck.UnusedCards.AddRange(CardInfo.FullDeck()); this.MyStatus.Score = -1; this.MyStatus.CardsLeft = this.MyDeck.UnusedCards.Count; this.MyStatus.Update(); MyDeck.Stacks.ListChanged += (sender, args) => { if (args.ListChangedType == ListChangedType.ItemAdded) { // fixme: dynamically set backside for this card //var s = MyDeck.Stacks[args.NewIndex]; //s.SetBackground(MyDeck.GfxPath + "/spider.empty.png"); } }; System.Console.WriteLine("creating stacklists... "); PlayStacks = MyDeck.CreateStackList(); TempStacks = MyDeck.CreateStackList(); GoalStacks = MyDeck.CreateStackList(); PlayStacks.ForEachNewItem( delegate(CardStack s) { s.CardMargin = new Vector { Y = 20 }; s.Update(); s.Cards.ListChanged += (sender, args) => { if (args.ListChangedType == ListChangedType.ItemDeleted) s.RevealLastCard(); }; } ); GameOver += delegate { GameOverBox.Text = "Congratulations! You Won!"; }; System.Console.WriteLine("creating goalstack... "); var Margin = (DefaultWidth - CardInfo.Width * 7) / 8; var ReserveStack = new CardStack().MoveTo(Margin, Margin); var UsedChoiceStack = new CardStack().MoveTo(Margin + CardInfo.Width + Margin, Margin); var ChoiceStack = new CardStack().MoveTo(Margin + CardInfo.Width + Margin, Margin); TempStacks.AddRange( ReserveStack, UsedChoiceStack, ChoiceStack ); ReserveStack.CardMargin.X = 0; ReserveStack.CardMargin.Y = 0; UsedChoiceStack.CardMargin.X = 0; UsedChoiceStack.CardMargin.Y = 0; ChoiceStack.CardMargin.X = 20; ChoiceStack.CardMargin.Y = 0; #region rules Func<bool> Rule_WinConditionMet = delegate { if (PlayStacks.All(s => s.Cards.Count > 0)) return false; if (TempStacks.All(s => s.Cards.Count == 0)) return false; return true; }; Func<Card, Card, bool> RuleForStackingCardsInGoalStack = (Previous, Current) => { if (Cheat) return true; if (Previous == null) return Current.Info.Rank == CardInfo.RankEnum.RankAce; if (Previous.Info.Suit != Current.Info.Suit) return false; if (Previous.Rank != Current.Rank + 1) return false; return true; }; Func<Card, Card, bool> RuleForStackingCardsInPlayStack = (Previous, Current) => { if (Cheat) return true; if (Previous.Info.SuitColor == Current.Info.SuitColor) return false; if (Previous.Rank + 1 != Current.Rank) return false; return true; }; #endregion MyDeck.ApplyCardRules += delegate(Card card) { card.MovedByLocalPlayer += delegate { MyStatus.Moves++; MyStatus.Update(); }; card.ValidateDragStart = delegate { if (Cheat) return true; // cannot remove cards from goal stack if (GoalStacks.Contains(card)) return false; if (TempStacks.Contains(card)) { return (card == ChoiceStack.LastOrDefault()); } // cannot drag a pile of cards unless alternate colors and descending numbers return card.SelectedCards.AllWithPrevious(RuleForStackingCardsInPlayStack); }; card.ValidateDragStop = CandidateStack => { if (Cheat) return true; if (TempStacks.Contains(CandidateStack)) { return false; } if (PlayStacks.Contains(CandidateStack)) { if (CandidateStack.Cards.Count == 0) return card.Info.Rank == CardInfo.RankEnum.RankKing; return (RuleForStackingCardsInPlayStack(CandidateStack.Cards.Last(), card)); } if (GoalStacks.Contains(CandidateStack)) { if (card.StackedCards.Length > 0) return false; return (RuleForStackingCardsInGoalStack(CandidateStack.Cards.LastOrDefault(), card)); } return false; }; }; GoalStacks.ForEachNewItem( s => { s.CardMargin.X = 0; s.CardMargin.Y = 0; s.Cards.ForEachNewItem( card => { this.MyStatus.CardsLeft--; this.MyStatus.Update(); if (card.Info.Rank == CardInfo.RankEnum.RankKing) { card.VisibleSide = Card.SideEnum.BackSide; if (Rule_WinConditionMet()) { // winner! MyDeck.Sounds.win(); if (this.GameOver != null) this.GameOver(); } } } ); } ); GoalStacks.AddRange( Enumerable.Range(0, 4).ToArray( i => new CardStack().MoveTo(DefaultWidth - ((CardInfo.Width + Margin) * 4) + i * (CardInfo.Width + Margin), Margin) ) ); System.Console.WriteLine("creating playstack... "); PlayStacks.AddRange( Enumerable.Range(0, 7).ToArray( i => new CardStack().MoveTo(Margin + i * (CardInfo.Width + Margin), Margin * 3 + CardInfo.Height).Apply(s => s.Cards.AddRange(MyDeck.FetchCards(i + 1))) ) ); ReserveStack.Cards.AddRange(MyDeck.FetchCards(MyDeck.UnusedCards.Count)); ReserveStack.Update(); PlayStacks.ForEach(k => k.Last().VisibleSide = Card.SideEnum.TopSide); UsedChoiceStack.Cards.ForEachNewItem( card => card.VisibleSide = Card.SideEnum.BackSide ); ChoiceStack.Cards.ForEachNewItem( card => card.VisibleSide = Card.SideEnum.TopSide ); ChoiceStack.Click += delegate { ChoiceStack.Update(); } ; ReserveStack.Overlay.Cursor = Cursors.Hand; ReserveStack.Cards.ForEachNewItem( card => card.VisibleSide = Card.SideEnum.BackSide ); var ReserveStackEnabled = true; ReserveStack.Click += delegate { if (!ReserveStackEnabled) return; if (ReserveStack.Cards.Count == 0) { MyDeck.Sounds.deal(); ChoiceStack.FirstOrDefault().Apply( card => { card.AnimatedMoveToStack(ReserveStack, null, null); } ); UsedChoiceStack.FirstOrDefault().Apply( card => { card.AnimatedMoveToStack(ReserveStack, null, null); } ); } else { ReserveStackEnabled = false; ChoiceStack.Cards.ToArray().ForEach( card => { card.AttachToStack(UsedChoiceStack); } ); UsedChoiceStack.Update(); 3.Times( SignalNext => ReserveStack.LastOrDefault().Apply( card => { card.BringToFront(); Console.WriteLine(card.ToString()); card.AnimatedMoveToStack(ChoiceStack, null, null); MyDeck.Sounds.deal(); 200.AtDelay(SignalNext); } ) ); } // a timepoint when movements are done.. this should ba an event actually 2000.AtDelay(() => ReserveStackEnabled = true); }; }
public FreeCellGame() { Width = DefaultWidth; Height = DefaultHeight; var Margin = (DefaultWidth - CardInfo.Width * 8) / 9; var GameOverBox = new TextBox { Width = DefaultWidth, TextAlignment = System.Windows.TextAlignment.Center, Foreground = Brushes.White, Background = Brushes.Transparent, BorderThickness = new Thickness(0), IsReadOnly = true, FontSize = 24, }.MoveTo(0, DefaultHeight / 2).AttachTo(this); GameOver += delegate { GameOverBox.Text = "Congratulations! You Won!"; }; #region king var KingCanvas = new Canvas { Width = 96, Height = 96 }.AttachTo(this).MoveTo( (DefaultWidth - 32) / 2, Margin * 2 + (CardInfo.Height - 32) / 2 ); var KingRight = new kingbitm().AttachTo(KingCanvas); var KingLeft = new kingleft().AttachTo(KingCanvas); var KingSmile = new kingsmil().AttachTo(KingCanvas); KingSmile.Hide(); #endregion this.MyDeck.Overlay.MouseMove += (sender, args) => { var p = args.GetPosition(this.MyDeck.Overlay); if (p.X < DefaultWidth / 2) { KingLeft.Show(); KingRight.Hide(); } else { KingLeft.Hide(); KingRight.Show(); } }; this.MyStatus = new StatusControl().AttachContainerTo(this).MoveContainerTo( (DefaultWidth - StatusControl.Width) / 2, (DefaultHeight - StatusControl.Height) ); //this.MyStatus.Container.Hide(); // add autoscroll ? this.MyDeck.SizeTo(DefaultWidth, DefaultHeight); this.MyDeck.AttachContainerTo(this); this.MyDeck.GetRank = e => (int)RankMapping[e]; System.Console.WriteLine("--- freecell ---"); System.Console.WriteLine("adding card infos... "); MyDeck.UnusedCards.AddRange(CardInfo.FullDeck()); this.MyStatus.CardsLeft = MyDeck.UnusedCards.Count; this.MyStatus.Score = -1; this.MyStatus.Update(); System.Console.WriteLine("creating stacklists... "); PlayStacks = MyDeck.CreateStackList(); PlayStacks.ForEachNewItem( k => { k.CardMargin = new Vector { Y = 20 }; k.Update(); } ); TempStacks = MyDeck.CreateStackList(); Func<bool> Rule_WinConditionMet = delegate { if (PlayStacks.All(s => s.Cards.Count > 0)) return false; if (TempStacks.All(s => s.Cards.Count == 0)) return false; return true; }; Action MyStatus_UpdateCardsLeft = delegate { MyStatus.CardsLeft = 0; PlayStacks.ForEach(q => MyStatus.CardsLeft += q.Cards.Count); TempStacks.ForEach(q => MyStatus.CardsLeft += q.Cards.Count); }; GoalStacks = MyDeck.CreateStackList(); GoalStacks.ForEachNewItem( k => { k.CardMargin.Y = 0; k.Cards.ForEachNewItem( card => { Console.WriteLine("GoalStacks ForEachNewItem " + new { k.CardMargin.Y }); if (card.Info.Rank == CardInfo.RankEnum.RankKing) { KingSmile.Show(); card.VisibleSide = Card.SideEnum.BackSide; if (Rule_WinConditionMet()) { // winner! MyDeck.Sounds.win(); if (this.GameOver != null) this.GameOver(); } else { 600.AtDelay(KingSmile.Hide); } } MyStatus_UpdateCardsLeft(); MyStatus.Update(); } ); } ); Func<Card, Card, bool> RuleForStackingCardsInGoalStack = (Previous, Current) => { if (Cheat) return true; if (Previous == null) return Current.Info.Rank == CardInfo.RankEnum.RankAce; if (Previous.Info.Suit != Current.Info.Suit) return false; if (Previous.Rank != Current.Rank + 1) return false; return true; }; Func<Card, Card, bool> RuleForStackingCardsInPlayStack = (Previous, Current) => { if (Cheat) return true; if (Previous.Info.SuitColor == Current.Info.SuitColor) return false; if (Previous.Rank + 1 != Current.Rank) return false; return true; }; #region rules MyDeck.ApplyCardRules += delegate(Card card) { #region MovedByLocalPlayer card.MovedByLocalPlayer += delegate { var FrozenTokens = new { card.CurrentStack, card.PreviousStack }; Console.WriteLine(new { HistoryMove = card, StackedCards = card.StackedCards.Length, Previous = card.PreviousStack, Current = card.CurrentStack }.ToString()); History.History.Add( delegate { // we already are at the state we want to be if (card.CurrentStack == FrozenTokens.PreviousStack) return; card.VisibleSide = Card.SideEnum.TopSide; card.AnimatedMoveToStack(FrozenTokens.PreviousStack, null); this.MyDeck.Sounds.deal(); MyStatus.Moves--; MyStatus_UpdateCardsLeft(); MyStatus.Update(); }, delegate { MyStatus.Moves++; MyStatus.Update(); // we already are at the state we want to be if (card.CurrentStack == FrozenTokens.CurrentStack) return; card.AnimatedMoveToStack(FrozenTokens.CurrentStack, null); this.MyDeck.Sounds.deal(); } ); }; #endregion card.VisibleSide = Card.SideEnum.TopSide; card.ValidateDragStart = delegate { if (Cheat) return true; // cannot remove cards from goal stack if (GoalStacks.Contains(card)) return false; // cannot drag a pile of cards unless alternate colors and descending numbers return card.SelectedCards.AllWithPrevious(RuleForStackingCardsInPlayStack); }; card.ValidateDragStop = CandidateStack => { if (Cheat) return true; if (TempStacks.Contains(CandidateStack)) { // temp only holds one card if (CandidateStack.Cards.Count > 0) return false; // and only one card can be inserted if (card.StackedCards.Length > 0) return false; return true; } if (PlayStacks.Contains(CandidateStack)) { if (CandidateStack.Cards.Count == 0) return true; return (RuleForStackingCardsInPlayStack(CandidateStack.Cards.Last(), card)); } if (GoalStacks.Contains(CandidateStack)) { if (CandidateStack.Cards.Count == 0) { return (RuleForStackingCardsInGoalStack(null, card)); } return (RuleForStackingCardsInGoalStack(CandidateStack.Cards.Last(), card)); } return false; }; }; #endregion System.Console.WriteLine("creating goalstack... "); GoalStacks.AddRange( Enumerable.Range(0, 4).ToArray( i => new CardStack { Name = "GoalStack " + i }.MoveTo( DefaultWidth - Margin / 2 - ((CardInfo.Width + Margin / 2) * 4) + i * (CardInfo.Width + Margin / 2), Margin * 2 ) ) ); System.Console.WriteLine("creating tempstack... "); TempStacks.AddRange( Enumerable.Range(0, 4).ToArray( i => new CardStack { Name = "TempStack " + i }.MoveTo( Margin + i * (CardInfo.Width + Margin / 2), Margin * 2 ) ) ); System.Console.WriteLine("creating playstack... "); PlayStacks.AddRange( Enumerable.Range(0, 8).ToArray( i => new CardStack { Name = "PlayStack " + i }.MoveTo( Margin + (i) * (CardInfo.Width + Margin), Margin * 4 + CardInfo.Height ).Apply( s => { var Count = 6; if (i < 4) Count = 7; s.Cards.AddRange(MyDeck.FetchCards(Count)); } ) ) ); }
public GameSocialLinks(Canvas Container) { this.Container = Container; Buttons.ForEachNewItem( e => { var i = true; //var x = Buttons.Where(k => i).Aggregate(Margin, // (s, k) => // { // if (k == e) // { // i = false; // return s; // } // return s + k.Width + Margin; // } //); //var y = this.Container.Height - Margin - e.Height; e.Y = Buttons.Where(k => i).Aggregate(Margin, (s, k) => { if (k == e) { i = false; return(s); } return(s + k.Height + Margin); } ); e.X = Margin; e.Image = new Image { Source = e.Source, Width = e.Width, Height = e.Height, Name = "GameSocialLinks_Button_Image", Opacity = 0.6 }.AttachTo(this).MoveTo(e.X, e.Y); e.Overlay = new Rectangle { Fill = Brushes.White, Width = e.Width, Height = e.Height, Opacity = 0, Cursor = Cursors.Hand, Name = "GameSocialLinks_Button_Overlay", }.AttachTo(this).MoveTo(e.X, e.Y); var ImageOpacity = e.Image.ToAnimatedOpacity(); ImageOpacity.Opacity = 0.4; e.Overlay.MouseEnter += delegate { ImageOpacity.Opacity = 1; }; e.Overlay.MouseLeave += delegate { ImageOpacity.Opacity = 0.4; }; e.Overlay.MouseLeftButtonUp += delegate { if (e.Click != null) { e.Click(); } if (e.Hyperlink != null) { e.Hyperlink.NavigateTo(); } }; } ); }