在线演示地址:Silverlight+WCF 新手实例 象棋 在线演示
正如我们在:Silverlight+WCF 新手实例 象棋 主界面-事件区-求和认输(三十二)里面提到的一样:
“游戏结束了,要干点什么呢?当然就是棋盘复位了,按钮重置了,如果还有棋谱之类的,全都得重置。这些,我们留下到另一节优化处理吧。”
所以,本节就做这些手尾工作了。
由于游戏结束,我们复位的工作很多,至少有N个控件需要复位,因此,Silverlight+WCF 新手实例 象棋 主界面-控件消息传递(二十六)
我们本节又要用到了:我们需要统筹全局的Index来做这件事:
我们在EventButton.xaml.cs里,那里有游戏结束通知:
我们添加一个代理,两行代码,这里我们多了个参数,传递Player:
public
partial
class
EventButton : UserControl
{
public
delegate
void
HelpSetGameEnd(Player player);
public
event
HelpSetGameEnd HelpSetGameEndEvent;
public
EventButton()
{
//
...省略N行...
}
//
...省略N行...
}
有了代理了,游戏结束时,只管调就是了:
void
client_NotifyEndGameReceived(
object
sender, GameService.NotifyEndGameReceivedEventArgs e)
{
//
接收游戏结束消息
switch
(e.player.AttachInfo)
{
//
...省略N行...
}
switch
(e.player.AttachInfo)
{
case
"
0
"
:
//
用户主动认输,游戏结束
case
"
1
"
:
//
将军被吃,游戏结束
case
"
2
"
:
//
双方同意平手,游戏结束
HelpSetGameEndEvent(e.player);
break
;
}
}
咦!怎么两个switch,是不是写错了还是写多了?不是了,这里多加的switch,只是把游戏结束的标志都抽出来,单独的执行一下游戏结束重置而已。
好了,这里的事情况就做完了,然后该Index出手了。
public
partial
class
Index : UserControl
{
//
...省略N行...
EventButton eventButtonControl;
public
Index()
{
//
...省略N行...
eventButtonControl
=
new
EventButton();
eventButtonBoard.Child
=
eventButtonControl;
//
下面为委托事件 ...省略1行...
eventButtonControl.HelpSetGameEndEvent
+=
new
EventButton.HelpSetGameEnd(eventButtonControl_HelpSetGameEndEvent);
}
void
eventButtonControl_HelpSetGameEndEvent(GameService.Player player)
{
//
这里实现游戏结束后所有的复位
}
//
...省略N行...
}
好了,接下来,我们要为一些控件做一些“重置”工作:
我们先为Chess象棋类增加一个Reset方法,用于把所有象棋相关参数重置为初始状态:
///
<summary>
///
象棋 by 路过秋天
///
http://cyq1162.cnblogs.com
///
</summary>
public
class
Chess
{
//
...省略N多行...
public
void
Reset()
{
container.Children.Clear();
//
棋盘和棋子一并清掉了
InitBoard();
//
只好重新初始棋盘了
InitChessman();
//
只好重新初始棋子了
IsCanMove
=
false
;
//
设置状态不能移动了
IsGaming = false;//这个差点忘了
}
//
...省略N多行...
}
OK,有了这个方法,我们的Index就首先可以添加一行了:
void
eventButtonControl_HelpSetGameEndEvent(GameService.Player player)
{
//
这里实现游戏结束后所有的复位
App.chess.Reset();
}
接着要复位事件区的按钮,先为事件区控件添加一个Reset方法[以后的控件基本上都添加一个]:
public
partial
class
EventButton : UserControl
{
//
...省略2行...
public
EventButton()
{
//
...省略N行...
}
public
void
Reset()
{
btnGameDeuce.IsEnabled
=
false
;
btnGameLose.IsEnabled
=
false
;
btnGameStart.IsEnabled
=
false
;
}
//
...省略N行...
}
OK,我们可以实现总复位方法了:
void
eventButtonControl_HelpSetGameEndEvent(GameService.Player player)
{
//
这里实现游戏结束后所有的复位
App.chess.Reset();
eventButtonControl.Reset();
if
(App.player.ColorValue
==
player.ColorValue)
{
eventButtonControl.btnGameStart.IsEnabled
=
true
;
}
}
最后一个,总得有一个人的“开始按钮”得激活的吧,不然怎么重新开始游戏呢?
OK,现在如果回头看看上面的结束标志,那个:
case
"
1
"
:
//
将军被吃,游戏结束
这个怎么产生的?哪产生的呢?其实很容易了,回到棋子“GoToDead"的地方,我们添加N行语句判断一下:
if
(Name
==
"
将
"
||
Name
==
"
帅
"
)
{
//
发送游戏结束到服务器
}
可是,棋子并不能自己发送消息,所以,正常思维就是添加代理了。可是呢,如果一个棋子一个代理,36颗子不就要产生36个代理了?
所以,代理的位置要移动一下了,一开始呢,我是在Chess类里添加一个代理,然后在棋子GoToDead里调用一个Chess的代理方法。
不过呢!刚想到了,直接在ChessAction的吃子动作里加代理和判断就行了,说动就动。
///
<summary>
///
棋子动作类 by 路过秋天
///
</summary>
public
class
ChessAction
{
public
delegate
void
GameEndDelegate(
int
colorValue);
public
event
GameEndDelegate HelpSetGameEndEvent;
//
...省略N多行
public
void
SetIsGameEnd(Chessman man)
{
if
(man.Name
==
"
将
"
||
man.Name
==
"
帅
"
)
{
GameEndEvent(man.Color
==
Colors.Red
?
1
:
2
);
}
}
public
void
EatChessman(Chessman moveChessman, Chessman eatChessman)
{
if
(MoveTo(moveChessman, eatChessman.MovePoint))
{
SetIsGameEnd(eatChessman);
eatChessman.GoToDead();
}
}
///
<summary>
///
系统自动移动棋子
///
</summary>
public
void
AutoMoveTo(Point from, Point to)
{
Chessman chessman
=
Parent.FindChessman(from);
Chessman eatChessman
=
Parent.FindChessman(to);
if
(chessman
!=
null
)
{
PlayMove(chessman, to);
chessman.MovePoint
=
to;
if
(eatChessman
!=
null
)
{
SetIsGameEnd(eatChessman);
eatChessman.GoToDead();
}
}
}
//
...省略N多行
}
我们添加了一个代理,由于,除了我们人为移动,还有系统自己移动,所以我们添加了一个公共方法,在吃子前都SetIsGameEnd来看看是不是游戏结束了,由于棋子谁输谁赢,所以要传递一个Color用于说明谁的将/帅被吃了。
OK,接着我们回到Chess.xaml.cs里,实现一下这个代理方法:
public
partial
class
Chess : UserControl
{
ChessNewInstance.Chess chess;
//
这里我们同时把它提到全局对象
public
Chess()
{
//
...省略N行...
chess.Action.HelpSetGameEndEvent
+=
new
ChessNewInstance.ChessAction.GameEndDelegate(Action_HelpSetGameEndEvent);
//
...省略N行...
}
void
Action_HelpSetGameEndEvent(
int
colorValue)
{
//
将帅被吃,游戏结束
if
(App.player.ColorValue
+
colorValue
==
3
)
{
App.player.AttachInfo
=
"
1
"
;
App.client.EndGameAsync(App.player);
}
}
//
...省略N行...
}
颜色值相加=3就是对手了。由于将帅被吃,无论是棋手还是看棋者,都会产生这个事件,所以要过滤判断。
OK,至此,我们F5看下效果了:

再走一步,吃将军:

状态重置成功了,可是一点提示都没有,于是,我们回到游戏结束EventButton.xaml.cs那里,添加一下结束通知弹出消息了:
void
client_NotifyEndGameReceived(
object
sender, GameService.NotifyEndGameReceivedEventArgs e)
{
//
接收游戏结束消息
switch
(e.player.AttachInfo)
{
//
...省略N行...
case
"
1
"
:
MessageBox.Show(e.player.NickName
+
"
赢了!
"
,
"
游戏结果通知
"
, MessageBoxButton.OK);
break
;
}
//
...省略N行...
}
继续F5运行看下效果:
吃掉对方将军时,终于有提示了:

确认后,游戏重置所有状态:看按钮,也重置了:

OK,本节点到为止了。