最近一直想自己写点windows phone 上的应用,但是一直都在纠结主题和素材。最终决定了先做点什么出来,不管是不是很foolish。
我想写个小游戏,可以锻炼大家短暂记忆力的那种,目前在很多平台上都有类似的。大概思路如下:
默认会有n*m张牌倒扣着,只能看到背面。当点击某两张时,对比是否相同,如果相同则消掉,给予相对应的分数奖励,否则这两张牌都重新显示背面(用短暂记忆去记住牌色),直到全部消掉。
原始核心思路:
牌的属性:
1. 颜色。(如果是高级难度的,可以加张png图片,同时比较颜色和图片是否相同)
2. 位置。(是在第几列第几行)。
1. 生成随机List<Color>,List<Card>。listColor中的元素个数需要是listCard个数的一半,因为每种颜色需要在两张牌上显示。
2. 实例化n*m张牌,用List<Color>中的颜色填充牌,每个颜色填充两张
(n*m必须是偶数)
for(i=0; i<n*m/2;i++)
{
Card c1 = new Card();
Card c2 = new Card();
c1.Color = list[i];
c2.Color = list[i];
listCard.Add(c1);
listCard.Add(c2);
}
3.for循环把listCard中的每张牌放到不同的位置上。
想到这里,自己感觉这样做很棘手,for循环嵌套最好不用,并且第三步比较复杂,位置是不能重复的,也就是说这里再用简单的random无法达到我的目的。
于是我需要一个简单的算法,摒弃这些繁琐的操作。
经过与同事的交流,我们把随机做了一次,就只是一次而已,就搞定了一切……
1. 扔掉listCard,只需要吧原来的listColor*2 形成一个新的List
2. 然后把这个大的list随机排布
3. 再for循环这个随机list,把每种颜色分别付给新的Card
4. 然后这些Card顺序摆放就OK了。
后续工作:
5. 如果点击某两张牌,则对比颜色,如果一样则消失(如果全消掉了,就提示胜利,返回主页),否则再次显示背面。
private Card tempCard_1; private Card tempCard_2; private const int CARD_WIDTH=70; private const int CARD_HEIGHT=70; private const int CARD_MARGIN = 5; private const int ROWS_COUNT = 2; private const int COLUMNS_COUNT = 2; private ListlistColor; private List listImage; public ContentPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(ContentPage_Loaded); } void ContentPage_Loaded(object sender, RoutedEventArgs e) { int multiply = ROWS_COUNT * COLUMNS_COUNT; if (multiply / 2 != multiply / 2.0) MessageBox.Show("Error,please update the row number or collumn number."); InitializeGrid(ROWS_COUNT,COLUMNS_COUNT); listColor = new List (); Random r = new Random(); for (int i = 0; i < ROWS_COUNT * COLUMNS_COUNT / 2; i++) { Color c = Color.FromArgb(255, (byte)r.Next(256), (byte)r.Next(256), (byte)r.Next(256)); listColor.Add(c); listColor.Add(c); } //add image to list listColor = RandomSortList(listColor); for (int i = 0; i < listColor.Count;i++ ) { Card card = new Card(listColor[i], null); card.Width = CARD_WIDTH; card.Height = CARD_HEIGHT; card.Margin = new Thickness(CARD_MARGIN); Grid.SetRow(card, i / COLUMNS_COUNT); Grid.SetColumn(card, i % COLUMNS_COUNT); LayoutRoot.Children.Add(card); card.Tap += new EventHandler (Card_Tap); } } private void InitializeGrid(int rows,int collumns) { for (int i = 0; i < rows; i++) { RowDefinition r = new RowDefinition(); r.Height = new GridLength(CARD_HEIGHT + CARD_MARGIN*2); LayoutRoot.RowDefinitions.Add(r); } for (int i = 0; i < collumns; i++) { ColumnDefinition c = new ColumnDefinition(); c.Width = new GridLength(CARD_WIDTH + CARD_MARGIN * 2); LayoutRoot.ColumnDefinitions.Add(c); } } void Card_Tap(object sender, System.Windows.Input.GestureEventArgs e) { //当tempCard_2还未清除时,不响应新的事件 if (tempCard_2 != null) return; //当tempCard_1为null时,把当前对象赋给tempCard_1,旋转显示tempCard_1 if (tempCard_1 == null) { tempCard_1 = sender as Card; tempCard_1.Transform(); } else { //当tempCard_1不为null,而tempCard_2为null时,给tempCard_2赋值当前对象,并旋转显示。 //旋转StoryBoard结束后(sb_Completed),对比两张卡片并进行后续处理 tempCard_2 = sender as Card; tempCard_2.Event += new EventHandler (sb_Completed); tempCard_2.Transform(); } } void sb_Completed(object sender, EventArgs e) { //这里必须先取消sb_Completed事件,避免多次注册事件 tempCard_2.Event -= new EventHandler (sb_Completed); if (tempCard_1.BgColor == tempCard_2.BgColor) { //如果颜色相同则消失 tempCard_1.Break(); tempCard_2.Break(); LayoutRoot.Children.Remove(tempCard_1); LayoutRoot.Children.Remove(tempCard_2); if (LayoutRoot.Children.Count <= 0) { MessageBox.Show("You win, click button to return Mainpage."); NavigationService.Navigate(new Uri("/MainPage.xaml",UriKind.Relative)); } } else { //否则旋转回去,继续显示背面(在Transform中会有判断,继而决定是转向背面还是前面) tempCard_1.Transform(); tempCard_2.Transform(); } tempCard_1 = null; tempCard_2 = null; } /// /// 随机排列List /// ////// /// public List RandomSortList (List list) { Random r = new Random(); List tempList = new List (); int listCount = list.Count; for (int i = 0; i < listCount; i++) { int tempInt = r.Next(list.Count); tempList.Add(list[tempInt]); list.RemoveAt(tempInt); } return tempList; }
为什么一次就行,为什么Card顺序摆放而不是随机呢??
多个随机算法与一个随机算法没有差别,可以简单的随机一次,达到你想要的目的。
源代码: