天天看點

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

在本節中,我們要進行最一步了,棋譜回放:

首先,當使用者進入清單後,擷取完棋譜資訊之後,第一個動作,就是要把棋譜按順序播放一下,這樣,使用者看到棋局就是雙方正在下的棋局了,之後,就跟下棋一樣,一步步接收棋步,然後一步步的自動移動就行了。

我們播放哪裡的棋譜呢的?

界面上顯示的listbox顯然是不能用來循環讀取的,畢竟那顯示的是格式化後的字元串,從字元串解析回棋步是不現實的;

一開始擷取的清單不是可以循環?那也隻有一部分,之後棋手雙方下的呢?

是以,說了這麼多,其實不就是想找多個變量來存棋譜清單麼,于是,我們在app.xaml.cs全局又添加一個全局變量了:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

public partial class app : application

    {

     //...省略n行代碼...

        public static list<gameservice.movestep> steplist = new list<gameservice.movestep>();//棋譜

        public static bool chessmanualplaying = false;//棋譜正回放中

        //...省略n行代碼...

        public app()

        {

         //...省略n行代碼...

        }

}

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

這裡又順路添加了一個全局屬性,用于設定棋譜是不是正在回放中,後面我們會用到[很後哦]。

ok,全局棋譜存貯變量有了,我們就得為它增加棋譜資料了,我們會在兩個地方添加棋譜,

1:一個是使用者下棋時傳遞時的棋譜:

我們進入chess.xaml.cs,找到收到棋譜通知的代碼,隻需要添加一行,第一行,把棋步添加一下就行了:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

void client_notifymovestepreceived(object sender, notifymovestepreceivedeventargs e)

            app.steplist.add(e.player.step);//隻需要一行

            if (app.player.id != e.player.id)//非自己

            {

               //...省略n行...

            }

            helpsetchessmanualevent(e.player.step);

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

2:進入頁面時擷取的棋譜清單讀取到棋譜區時:

我們進入chessmanual.xaml.cs,找到擷取棋譜清單的代碼,同樣隻需要一行:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

 void client_getmovesteplistcompleted(object sender, gameservice.getmovesteplistcompletedeventargs e)

            //擷取完棋譜後,這裡循環調用添加就可以了

            if (e.result != null && e.result.count > 0)

                app.steplist = e.result;//這裡隻需要一行代碼

                foreach (gameservice.movestep step in e.result)

                {

                    lbchessmanual.items.add(step.id + ":" + step.name);

                }

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

ok,我們對全局棋譜的傳值,兩行代碼就搞定了,于是在播放棋譜時,理論上我們循環全局的steplist就行了:

我們先産生一個方法,用于播放一個棋步,就是傳進一個棋步,然後自動播放:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

void automove(gameservice.movestep step)

            point from = new point(step.fromx, step.fromy);

            point to = new point(step.tox, step.toy);

            if (app.player.colorvalue + step.colorvalue == 3 || (step.colorvalue == 2 && app.player.colorvalue == 3))//旁觀者 黑色棋子

                from = app.chess.reversearray(from);

                to = app.chess.reversearray(to);

            app.chess.action.automoveto(from, to);

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

這個方法其實有點簡單,隻要調用aotomoveto就搞完了,唯一的複雜點,就是判斷要不要反轉坐标了。

[兩種情況:如果是下棋者,棋步是對手的,要反轉坐标;觀衆預設是紅色的,收到黑色棋步,也要反轉坐标]

好了,有了單步的方法,我們for一下step裡,然後循環傳值就ok了?no,如果這樣循環,棋步刷的一下就沒了,還看啥回放?

是以,我們需要定間隔播放了,是以,我們需要先産生間隔的秒數,我們通過滑動塊來設定文本框的數字:

我們設定一下滑動塊的屬性[預設值為0,最大值為9,最小滑動為0.5,最大滑動為1]:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

我們同時添加滑動事件:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

而我們滑動時隻需要一行代碼,為文本框指派就行了:

private void slplayerinternal_valuechanged(object sender, routedpropertychangedeventargs<double> e)

            txtvalue.text = e.newvalue.tostring();

我們增加一個方法,叫playstep,用于循環播放棋步:

private void playstep()

{     

   //待實作

好了,接着我們輕按兩下一下“回放”按鈕,裡面調用一下這個playstep就行了:

private void btnplay_click(object sender, routedeventargs e)

{

  playstep();

預設我們加載完棋步清單後,也要定位棋步,是以也調用一下playstep:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

void client_getmovesteplistcompleted(object sender, gameservice.getmovesteplistcompletedeventargs e)

                playstep();//加完後馬上調用播放棋步,預設0秒,是以刷一下就播放完了

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

于是,所有的重點隻剩下怎麼實作這個playstep了。

我們每一步棋步都需要間隔n秒走一步,一開始我竟然用線程的sleep來操作,結果是,程式卡住了,直接播放完了才能動,那個汗-_-!

于是,n久之後,非線程阻塞的timer出來了,讓它定時每n秒走一步就行了:

全局定義一下timer先,順路加上移動的索引:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

public partial class chessmanual : usercontrol

        system.windows.threading.dispatchertimer timer;//定義timer

        int movestepindex = 0;//移動到第幾步了

         //...下面省略n行...

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

接着初始化timer及事件:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

 public partial class chessmanual : usercontrol

        public chessmanual()

            //...省略n行...

            timer = new system.windows.threading.dispatchertimer();

            timer.tick += new eventhandler(timer_tick);

        void timer_tick(object sender, eventargs e)

            //待實作

     }

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

我們這裡沒有初始化timer的間隔時間,是因為把間隔時間設定放到playstep函數裡了,說到playstep,我們可以實作它了:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

            if (app.steplist.count > 0)

                //播放前複位棋子

                  app.chess.reset();

                timer.interval = timespan.fromseconds(slplayerinternal.value);

                timer.start();

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

我們隻用了小小幾行代碼,其實就是設定一下時間,然後讓timer它start起來就完事了,于是重心又一步轉移到timer的tick事件裡了:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)
Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

 void timer_tick(object sender, eventargs e)

            gameservice.movestep step = app.steplist[movestepindex];//擷取棋步

            lbchessmanual.selectedindex = movestepindex;//定位棋步索引

            lbchessmanual.updatelayout();//需要更新下布局

            lbchessmanual.scrollintoview(lbchessmanual.selecteditem);//滾動到先中的項

            automove(step);//移動棋步

            movestepindex++;//索引加1

            if (movestepindex == app.steplist.count)//判斷棋步結束沒有

                movestepindex = 0;//重置索引

                timer.stop();//停止timer

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

這裡每一步都有注釋,相信不會看不懂的了。ok,至此,我們是可以f5看效果了:

1:目前正在下棋,下到一半中:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

2:觀衆進來了,擷取完棋步,并播放了一次,定位到最後一步:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

3:設定為2秒,點“回放”,自動播放了第一步:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

4:回放走到第二步:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

5:回放走到最後一步了:

Silverlight+WCF 新手執行個體 象棋 主界面-棋譜-回放(三十九)

ok,到此,我們的棋譜回放功能基本完成了,隻是有一些細節,我們是需要另外處理了:

1:下棋者在下棋過程,要不要開放“回放”功能,如果開放,需要注意什麼?

2:觀衆在回放過程中,突然又傳來一個棋步,需要注意什麼?

這兩個小細節,下節處理,本系列到這裡,所有基礎區的功能都基本完成了差不多了,那本系列是不是也接近尾聲了?

版權聲明:本文原創發表于部落格園,作者為路過秋天,原文連結:

http://www.cnblogs.com/cyq1162/archive/2010/08/09/1795873.html

<a href="http://files.cnblogs.com/cyq1162/chessnewinstance_part8.rar"></a>

繼續閱讀