下棋者在下棋過程,要不要開放“回放”功能,如果開放,需要注意什麼?
觀衆在回放過程中,突然又傳來一個棋步,需要注意什麼?
在解答這兩個問題之前,我們先來解答上一篇的截圖中發現的問題:
不知有沒有人發現?圖中有三個“炮”或三個”馬“,出現這個事故的原因,
是由于在每次重置chess.Reset的時候,我們沒有清除棋子清單,造成了有重複的棋子。找到了原因,解決的方法就相當的簡單了,
隻要在chess象棋類裡的确Reset方法裡,添加一行棋子清單.clear方法清除下就行了,增加的隻有第一行:

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

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

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

void client_NotifyMoveStepReceived(object sender, NotifyMoveStepReceivedEventArgs e)
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,播放完,設定回原值就行了;
是不是感覺和第一個問題太相似了?動手吧,還是播放開始和結束,隻不過,也要增加一個變量,來存棋手的下棋狀态:
增加一行全局變量:

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

tempIsCanMove = App.chess.IsCanMove;//先存之前狀态
App.chess.Reset();//重置狀态時會設定IsCanMove=false,是以不用寫多一行
App.chessManualPlaying = true;
接着播放結束時,狀态設定回來[最後一行代碼]:

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