Silverlight+WCF 新手實例 象棋 主界面-棋譜-回放-結局(四十)
查看本系列其他相關文章請點擊:Silverlight+WCF 新手實例象棋專題索引
在線演示地址:Silverlight+WCF 新手實例 象棋 在線演示
在Silverlight+WCF 新手實例 象棋 主界面-棋譜-回放(三十九)中,我們實現了用戶的棋譜回放,在文章的下面,我們曾留下了兩個問題:
- 下棋者在下棋過程,要不要開放“回放”功能,如果開放,需要注意什么?
- 觀眾在回放過程中,突然又傳來一個棋步,需要注意什么?
在解答這兩個問題之前,我們先來解答上一篇的截圖中發現的問題:
不知有沒有人發現?圖中有三個“炮”或三個”馬“,出現這個事故的原因,
是由于在每次重置chess.Reset的時候,我們沒有清除棋子列表,造成了有重復的棋子。找到了原因,解決的方法就相當的簡單了,
只要在chess象棋類里的確Reset方法里,添加一行棋子列表.clear方法清除下就行了,增加的只有第一行:

{
ChessmanList.Clear();//增加棋子列表清除
container.Children.Clear();//棋盤和棋子一并清掉了
InitBoard();//只好重新初始棋盤了
InitChessman();//只好重新初始棋子了
IsCanMove = false;//設置狀態不能移動了
IsGaming = false;//這個差點忘了
}
好了,一行代碼解決了我們上一節隱藏在圖片中的bug。
接下來,我們要對上節留下的兩個問題做一下解答了:
我們把問題順序倒一下,先解答第二個問題吧:觀眾在回放過程中,突然又傳來一個棋步,需要注意什么?
我們在上一節,曾定義過一個全局變量:
而上節中,我只說了后面會用到[很后哦],所以,這節我們要用到了,因為這個變量可以解答問題:
我們假設:當觀眾在回放棋步的過程中,棋手雙方在不停的下棋,不斷的傳遞新的棋步過來;
這時,我們僅需要處理的,只是不執行自動播放而已,至于寫棋譜區文字和添加到棋譜列表的照常就行了。
所以,我們要做的事情就是:開始播放時,設置App.chessManualPlaying為true;播放結束后,設置為false;
于是我們回到播放時的代碼增加:

{
if (App.stepList.Count > 0)
{
//播放前復位棋子
App.chess.Reset();
App.chessManualPlaying = true;//增加的一行
timer.Interval = TimeSpan.FromSeconds(slPlayerInternal.Value);
timer.Start();
}
}
于是我們再回到播放結束時的代碼增加:

{
//...省略N行...
if (moveStepIndex == App.stepList.Count)//棋步結束
{
moveStepIndex = 0;//重置索引
timer.Stop();//停止timer
App.chessManualPlaying = false;//增加的一行
}
}
標識位加完了,我們回到設置自動移動棋步的地方,加判斷,如果播放中,切斷棋步自動移動:
接收棋步的通知在Chess.xaml.cs里,我們只需要添加半行代碼[下面的!App.chessManualPlaying]:

{
App.stepList.Add(e.player.Step);//添加棋步
if (!App.chessManualPlaying && App.player.ID != e.player.ID)//非棋步播放中,非自己
{
//...省略棋步移動相關代碼...
}
HelpSetChessManualEvent(e.player.Step);//寫棋譜區
}
第二個問題,至此就解決了,總共添加了2.5行代碼。
現在轉回第一個問題了:下棋者在下棋過程,要不要開放“回放”功能,如果開放,需要注意什么?
不開放:只需要把“回放”按鈕啟用狀態設置為false就行了;
開放:其實也不難:我們只要限制在播放過程中,不讓棋手下棋就行了,
同時棋手播放過程也會產生第一個問題:不過,我們剛才已經解決,加的代碼對棋手也是同樣有效。
如何限制棋手不讓下棋,其實很簡單了,chess.IsCanMove屬性就能限制了,只要播放時,設置為false,播放完,設置回原值就行了;
是不是感覺和第一個問題太相似了?動手吧,還是播放開始和結束,只不過,也要增加一個變量,來存棋手的下棋狀態:
增加一行全局變量:

{
//...省略2行代碼...
bool tempIsCanMove;//保存棋手之前的狀態
public ChessManual()
{
//...省略N行代碼...
}
//...省略N行代碼...
}
播放時,先取狀態,再設置IsCanMove=false[這句在Reset重置里已經有了,可以省了];

{
if (App.stepList.Count > 0)
{
//播放前復位棋子
tempIsCanMove = App.chess.IsCanMove;//先存之前狀態
App.chess.Reset();//重置狀態時會設置IsCanMove=false,所以不用寫多一行
App.chessManualPlaying = true;
timer.Interval = TimeSpan.FromSeconds(slPlayerInternal.Value);
timer.Start();
}
}
接著播放結束時,狀態設置回來[最后一行代碼]:

{
//...省略N行代碼...
if (moveStepIndex == App.stepList.Count)//判斷棋步結束沒有
{
moveStepIndex = 0;//重置索引
timer.Stop();//停止timer
App.chessManualPlaying = false;
App.chess.IsCanMove = tempIsCanMove;//增加的一行
}
}
OK,至此,我們用了同樣的方法,解決了上節的兩個問題,接下來又到F5的showtime時間:
正常,上圖,這下棋步回放是正常的了:
1:棋手正下棋不久:
2:觀眾進來了,播放了棋步,定位到實時狀態:
3:觀眾想看下棋過程,開始“回放”棋步:
4:“回放”到第三步棋中:
5:回放到第五步棋中:
OK,截圖到就到此了,本系列文章,一不小心就寫了40節了,在這系列的40節里,所有功能已完全的開放源碼并講解完了!
有興趣的讀者歡迎關注本系列文章,明天公司又要搬家了,本系列有沒有后續文章,目前情況不明......
順路更新下索引:Silverlight+WCF 新手實例 象棋 專題索引