新手silverlight练习--五子棋( 三 )
在上一篇文章中,我们经过之前的千辛万苦终于让棋子在棋盘上面给显示出来了。现在我们就要想办法,让它实现下棋子的功能。
下棋子是怎么下的呢?
思考片刻:五子棋有两个人下(虽然是自己和自己下,也勉强算两个人啦),所以当你触发一次鼠标按下事件,就得下一个棋子,而且棋子的颜色会是交替的,一黑一白这样下。然后把它放在你点击的地方。
有了思路,就得按照这个是实现,要怎么做呢?方法其实很多的,我暂时想到两个:
一、可以在初始化棋盘的时候,就让每个可以放棋子的坐标点上面生成一个棋子,因为棋子其实是一个Ellipse对象,所以把他的opcity设为0,这样就透明,看不见了,就当是没有棋子在这个地方(自欺欺人下吧,反正别人不知道);然后呢,就要开始响应鼠标点击了----好棋,我就要下在这个地方了,然后我就点击这个位置,鼠标获取坐标,然后就把这个地方的棋子的opcity设为1,就不透明了,然后根据下棋的先后判断是黑棋还是白棋,把它颜色给设好,这样,一个棋子就出现在这个位置了。
二、按照正常的方法,开始的时候棋盘上是没有棋子的,然后,根据你下棋下的位置,同样通过鼠标获取坐标点,然后在这个位置生成一个棋子对象,设定棋子颜色,再加进棋盘画布。
这里,我用的是第二种方法,好了,马上开始行动----------------》
我们继续来完善GameEnigin类,刚才说了,要根据你下棋的位置,然后通过坐标生成棋子,所以,我们就来做两个函数,一个是生成黑色棋子的函数,一个是生成白色棋子的函数,这样,以后我们就根据情况来调用它们。
2 /// 创建黑色棋子
3 /// </summary>
4 /// <param name="pt"></param>
5 /// <param name="con"></param>
6
7 public void CreateBlackChessman(Point pt,Canvas con)
8 {
9 Point ptn=new Point();
10 ChessMan cm = new ChessMan(pt, radius, Colors.Black,1);
11
12 cm.DrowChessman(con);
13
14 }
15
16 /// <summary>
17 /// 创建白色棋子
18 /// </summary>
19 public void CreateWhiteChessman(Point pt, Canvas con)
20 {
21 Point ptn = new Point();
22 ChessMan cm = new ChessMan(pt, radius, Colors.White,2);
23
24 cm.DrowChessman(con);
25
26 }
27
这个函数,通过参数传进鼠标点击时的坐标,和容器对象(这里就传进棋盘画布,因为我们的棋子也是画在棋盘上的);
然后通过棋子类生成一个棋子,并设定颜色,大小等信息。这样,黑白棋子的生成函数就写好了。接着我们考虑棋子黑白交替下的方法,为了实现这个功能。我又在GameEnigin类中增加了一个GameStart函数,来控制:
/// <summary>
/// 游戏开始
/// </summary>
public void GameStart(int x,int y, Canvas con)
{
Point pt = new Point(x, y);
switch(turns)
{
case 1: {
CreateBlackChessman(pt, con);
turns = 2;
}break;
case 2: {
CreateWhiteChessman(pt, con);
turns=1;
}break;
}
}
这里通过turns来控制黑白棋子交替生成,很简单吧?嘿嘿~~
有了这个,我们就要使用他们,所以,我们回到
MainPage.xaml文件,修改Canvas如下:
这里其实就是增加了一个MouseLeftButtonDown的事件,然后在隐藏代码中会相应的出现鼠标左键按下的事件响应函数
private void Board_MouseLeftButtonDown(object sender, MouseButtonEventArgs e);于是,我们打开MainPage.xaml.cs文件。找到这个函数
开始获取坐标啊,生成棋子等操作,代码如下:

private void Board_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Point pt = e.GetPosition(this);
List <Point> pList = new List<Point>();
for(int i=350;i<=900;i+=50)
{
for (int j = 28; j <= 578; j += 50)
{
pList.Add(new Point(i, j));
}
}
ge.GameStart((int)px.X, (int)px.Y, Board);
}
这里先获取鼠标点击的坐标点,然后,再new一个Point的列表对象,然后把棋盘上可以放棋子的各个坐标点放进这个列表中,这两个for循环就是生成对应的坐标点,i,j的具体范围大家根据实际设定,因为我当初设定的间隔大小是50,所以以50递增。
然后判断当前点击时的坐标点是不是在这个列表中,如果在,就调用GameStart函数,在这个坐标点生成一个棋子,看下GameStart函数的最后一个参数。是Board,这个就是棋盘Canvas对象。最后别忘了,在MainPage.xaml.cs的类中声明下 GameEnigin ge;然后在 public MainPage()构造函数中加上:
ge = new GameEnigin(Board);因为,ge在后面都要用到。
好哦,终于离成功又进一步了,运行运行。。。。
----------------------------------问题来了 问题来了------------------------------->>
>>>啥问题?当点棋盘的时候咋没反应呢,我点呀点呀,终于有反应了,原来,坐标定位太精确了,只有在那一个点上点击才能生成棋子啊!!!
我 ¥……%&……%……#%$%
那下棋也太累了吧,每次都要点那个准。。。得想个办法把它的范围给扩大,因为现在能点的坐标只有(350,28),(400,28),(450,28).........(350,56),(350,84).......
怎么办呢?
于是,我终于想到一个笨办法,不管了,能解决问题就行(如果哪位有更好的方法,赐教),方法是这样的:
再定义一个Ponit 对象px ,然后。。。。还是看代码先:

for (int i = -23; i < 24; i++) //x轴方向范围-23---23
{
for (int j = -23; j < 24; j++) //y轴方向范围 -23--23
{
px.X = pt.X;
px.Y = pt.Y;
px.X += i;
px.Y += j;
if (pList.Contains(pt) || pList.Contains(px))
ge.GameStart((int)px.X, (int)px.Y, Board);
}
}
为什么要选范围-23--23 呢?因为和我们的格子间的距离50有关。这样选的话,可以更好的判断应该定位在哪个位置。
这样把原来坐标点边上更多的坐标点也加到了坐标列表,然后这里将通过px来定位位置,不能用pt坐标了哦。。。。
好了,现在可以在一个范围内点击,然后定位到你想下棋的位置。现在我们基本上已经能够在棋盘上下棋了,现在要做的就是要实现五子棋的基本算法啦。因此我们需要在GameEnigin类中增加一个 ChessMan[,] chess=new ChessMan[12,12];通过它,我们将实现五子棋游戏的基本逻辑。
但是这个数组的范围是12,12而我们之前得到的是屏幕坐标,因此。我们还需要做一个屏幕坐标到逻辑坐标的转换函数,以实现,通过用户的行为,而反映到具体的逻辑。那么我们接下来就来做这个转换函数吧:)
函数很简单:
///物理坐标转换成逻辑坐标
/// </summary>
public Point ChangePos(Point pt)
{
Point LogPos = new Point();
LogPos.X = (pt.X - 350) / 50;
LogPos.Y = (pt.Y - 28) / 50;
return LogPos;
}
通过它可以根据屏幕坐标,返回相应的逻辑坐标点。如,屏幕坐标最左上角的(350,28)转换后变为(0,0);依次转换、、、简单吧、、这样我们就可以通过获取屏幕坐标。然后把棋子放进逻辑数组里面,之后嘛,就根据逻辑数组,来算五子棋是不是5个同色的棋子连在一起的算法了。
今天写到这里,剩下的下次写啦。。。天气好热。。
|
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构