Silverlight版拼图游戏

     Silverlight2.0出来也有一段时间了,一直想好好学学,主要是考虑将来使用Silverlight做数据结构方面的动画及课件,这样可以很方便地挂在网上观看。前几天终于下定决心学习。这几天的感觉就是很庆幸之前没有学得太早,测试版跟正式版之前有不少改动,还好没做小白鼠。不过现在学其实还是逃不出小白鼠的命运,感觉Silverlight将来还会有不少改动。

     拼图游戏相信很多人玩过,之前我在《C#程序设计基础教程与实训》中使用WindowForm应用程序实现过,共84行代码,很精简。学了一些Silverlight后,我就迫不急待地想使用Silverlight实现这个游戏,因为我对Silverlight的期待就是可以像WindowForm一样很方便地编程。但实践证明,两者还是有一定差距的,希望Silverlight3.0或4.0版本可以做到这点。

     好,先来看看效果,这里需要注意,必须安装Silverlight 2.0 RTW 才能正常运行游戏,下载地址:http://www.microsoft.com/silverlight/resources/install.aspx?v=2.0

     猜猜她是谁?

    

     在程序中自定义了一个控件Img,也就是C# WindowForm中的Image控件,虽然Silverlight中也有Image控件,但没有ImageList控件,控制起来也不是很方便,所以将Image做进一步地包装可以使代码更容易读懂,看上去更舒服些。

     首先新建一个Silverlight项目,起名为PictureGame。找一张完整的240*240的图片分割分9等份,命名为“pic0”至“pic9”。把这9张图片加入到项目中。在【解决方案资源管理器】中,右击PictureGame项目,在弹出菜单中选中【添加】→【新建项】,在弹出的【添加新项窗口】中选中【Silverlight用户控件】,给控件起名“Img”,点确定。

     【Img.xaml】文件的代码如下所示:

 

<UserControl x:Class="PictureGame.Img"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml">
<Canvas x:Name="LayoutRoot" Width="80" Height="80">
<Image x:Name="image" Width="80" Height="80"/>
<Rectangle x:Name="border" Stroke="DimGray" StrokeThickness="2"
Width
="80" Height="80"
Canvas.Left
="0" Canvas.Top="0">
</Rectangle>
</Canvas>
</UserControl>

这里主要是在Canvas中放一个Image控件,然后加上边框。

      接下来按F7切换到【Img.xaml.cs】文件,输入新代码将如下所示:

 

using System;
using System.Windows.Controls;
using System.Windows.Media.Imaging;

namespace PictureGame
{
public partial class Img : UserControl
{
public Img()
{
InitializeComponent();
}
int index;
public double Left
{
get { return (double)this.GetValue(Canvas.LeftProperty); }
set { this.SetValue(Canvas.LeftProperty, value); }
}
public double Top
{
get { return (double)this.GetValue(Canvas.TopProperty); }
set { this.SetValue(Canvas.TopProperty, value); }
}
public bool Visible //是否可见
{
get { return image.Opacity == 0.0; }
set { image.Opacity = value ? 100.0 : 0.0; }
}
public bool BorderVisible //边框可见性
{
get { return border.Opacity == 0.0; }
set { border.Opacity = value ? 100.0 : 0.0; }
}
public BitmapImage Source //Image中显示的图片
{
set { image.Source = value; }
}
public int ImageIndex //图片在数组中的索引号
{
get { return index; }
set { index = value; }
}
}
}

 



这里实际上就是对Image控件做个包装,使得我们可以像在C# WindowForm一样使用控件。有一个问题没弄明白,就是如何使用程序控制控件的可见性,一时没找到,只好使用Opacity属

性来摸拟了。
接下来更改程序的主xaml文件【Page.xaml】:

<UserControl x:Class="PictureGame.Page"
xmlns
="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"
FontFamily
="微软雅黑" FontSize="12"
Width
="260" Height="315"
Loaded
="UserControl_Loaded">
<Canvas x:Name="LayoutRoot" Background="Chocolate">
<Rectangle Stroke="DimGray" StrokeThickness="2"
Width
="244" Height="244"
Canvas.Left
="8" Canvas.Top="8"/>
<Button x:Name="btnStart" Width="80" Height="23"
Canvas.Left
="90" Canvas.Top="260"
Content
="开始游戏" Click="btnStart_Click"/>
<TextBlock x:Name="msgBox" Width="260" Height="20"
Canvas.Left
="0" Canvas.Top="288" TextAlignment="Center"
Foreground
="White" Text="http://www.cnblogs.com/abatei"/>
</Canvas>
</UserControl>

这里画了一个矩形边框,一个按钮和一个用于显示消息的TextBlock。注意在
Loaded="UserControl_Loaded"
Click="btnStart_Click"
两句代码上左击选中【定位到事件处理程序】可以在cs文件中自动生成相应的事件方法,很方便。
最后在【Page.xaml.cs】文件中输入如下代码:
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Imaging;

namespace PictureGame
{
public partial class Page : UserControl
{
public Page()
{
InitializeComponent();
}
Img[,] imgs
= new Img[3, 3];
BitmapImage[] bmps
= new BitmapImage[9];
int unRow = 0, unCol = 0;
bool playing = false;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 9; i++)
{
bmps[i]
= new BitmapImage(new Uri("pic" + i.ToString() + ".jpg", UriKind.Relative));
}
for (int i = 0; i < 9; i++)
{
Img img
= new Img();
img.MouseLeftButtonDown
+= new MouseButtonEventHandler(img_MouseLeftButtonDown);
img.Left
= 10.0 + i % 3 * 80.0;
img.Top
= 10.0 + i / 3 * 80.0;
LayoutRoot.Children.Add(img);
imgs[i
/ 3, i % 3] = img;
}
}
//开始游戏按钮
private void btnStart_Click(object sender, RoutedEventArgs e)
{
imgs[unRow, unCol].Visible
= true;
int[] arrNum = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
Random rm
= new Random();
for (int i = 0; i < 8; i++)
{
int rmNum = rm.Next(i, 9);
int temp = arrNum[i];
arrNum[i]
= arrNum[rmNum];
arrNum[rmNum]
= temp;
}
for (int i = 0; i < 9; i++)
{
imgs[i
/ 3, i % 3].Source = bmps[arrNum[i]];
imgs[i
/ 3, i % 3].ImageIndex = arrNum[i];
imgs[i
/ 3, i % 3].BorderVisible = true;
}
int cover = rm.Next(0, 9);
unRow
= cover / 3;
unCol
= cover % 3;
imgs[unRow, unCol].Visible
= false;
playing
= true;
}
//鼠标单击事件
void img_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (!playing)
{
return;
}
int row = (int)((Img)sender).Top / 80;
int col = (int)((Img)sender).Left / 80;
if (Math.Abs(row - unRow) + Math.Abs(col - unCol) == 1)
{
int temp = imgs[unRow, unCol].ImageIndex;
imgs[unRow, unCol].ImageIndex
= imgs[row, col].ImageIndex;
imgs[unRow, unCol].Source
= bmps[imgs[row, col].ImageIndex];
imgs[row, col].ImageIndex
= temp;
imgs[row, col].Source
= bmps[temp];
imgs[unRow, unCol].Visible
= true;
imgs[row, col].Visible
= false;
unRow
= row;
unCol
= col;
}
for (int i = 0; i < 9; i++)
{
if (imgs[i / 3, i % 3].ImageIndex != i)
{
break;
}
if (i == 8)
{
imgs[unRow, unCol].Visible
= true;
foreach (Img img in imgs)
{
img.BorderVisible
= false;
}
playing
= false;
msgBox.Text
= "恭喜您通过游戏!";
}
}
}
}
}

大功告成,这里需要注意,有一半的机会会碰到无解的情况,最方便的判断就是如果将两个相邻的图片调换就可以完成游戏,那么这是无解的。
posted @ 2008-11-22 13:46  abatei  阅读(3767)  评论(7编辑  收藏  举报