Silverlight+WCF 實戰-網絡象棋最終篇之十字軌跡(一)

前言

05233129_VFPo.gif
繼之前Silverlight+WCF 新手實例 象棋系列四十篇之後,一個多月的時間都在寫CYQ.Data框架系列[CYQ.Data 輕量數據層之路 框架開源系列 索引],

讓各位對該Silverlight+WCF 象棋系列有興趣的網友久候了,上一系列詳見:[Silverlight+WCF 新手實例 象棋 專題索引]

今天開始就在之前四十篇續上,直到把 [Silverlight+WCF 新手實例 象棋 在線演示] 上的最新代碼寫完,謝謝支持!

 

亂七雜八說兩句:

一個多月沒碰VS2010了,今天回頭看原來的象棋系列代碼,感覺到有點陌生了,

好多原來的思路,都忘的差不多了,要續寫這系列文章,感覺還得像個新手一樣重溫下代碼才行呢。

本系列爲進階優化系列,會在原來的基礎上,慢慢改動很多代碼的哦,歡迎持續關注!

 

正文:

我們先回顧下,截一張上一系列 最後一節[Silverlight+WCF 新手實例 象棋 主界面-棋譜-回放-結局(四十) ]裏的一張圖片先:

 

OK,從這圖片我知道雙方是在下棋了,可是我們並不知道現在該誰下了?

當然了,認真看一下棋譜,還是知道剛剛是黑方下了一步,不過還是要很用力的猜車一平二是怎麼個平法。

十字軌跡的出現,解決了這個問題,如果到QQ平臺下過棋,也見過的,就是那個棋子周圍加上的一個邊框了,那這個爲啥叫十字軌跡?這個這個...

 

 

好!大夥知道十字軌跡是什麼就好了,現在說說實現思路

大夥想啊,十字軌跡是在棋步移動之後,在棋盤上就有兩個出現了,一個在移動的棋子的原來位置,一個在移動後的位置,而且整個棋盤就只能有兩個,於是,我們的思路定位就很簡單了。

一:在棋盤上先創建好兩個十字軌跡,默認隱藏

二:在棋手移動完棋子之後,把兩個十字軌跡移動到相應的位置

 

 

就這麼兩步,很簡單吧,該出手時就出手。

 

實現步驟如下:

 

一:棋盤Board類畫十字軌跡

 

1:增加兩個十字軌跡屬性

05233129_VFPo.gif
    ///   <summary>
    
///  棋盤 by 路過秋天
    
///   http://cyq1162.cnblogs.com
    
///   </summary>
     public   class  Board
    {
        
///   <summary>
        
///  十字軌跡框
        
///   </summary>
         public  Canvas TrackFrom
        {
            
get ;
            
set ;
        }
        
///   <summary>
        
///  十字軌跡框
        
///   </summary>
         public  Canvas TrackTo
        {
            
get ;
            
set ;
        }
        
// 下面省略N多代碼
     }

2:增加一函數,用於畫十字軌跡

05233129_VFPo.gif
         private   void  DrawTrack(Panel panel)
        {
            
double  width  =  panel.Width  -   8 ;
            
// 橫線4條
            DrawLine( 0 0 , width  /   4 0 3 , panel,  false ); // L-
            DrawLine( 0 , width, width  /   4 , width,  3 , panel,  false ); // LB-
            DrawLine(width  *   3   /   4 0 , width,  0 3 , panel,  false ); // R-
            DrawLine(width  *   3   /   4 , width, width, width,  3 , panel,  false ); // RB-


            
// 直線四條
            DrawLine( 0 0 0 , width  /   4 3 , panel,  false ); // L| ok
            DrawLine(width,  0 , width, width  /   4 3 , panel,  false ); // R| ok
            DrawLine( 0 , width,  0 , width  *   3   /   4 3 , panel,  false ); // LB|
            DrawLine(width, width  *   3   /   4 , width, width,  3 , panel,  false ); // RB|
        }

說明:

畫這麼個框,記得以前還真費了不少勁,在那調座標和寬度;

注意哦,DrawLine方法變成5個參數了,以前只有四個的。

3:DrawLine方法小調整

05233129_VFPo.gif
        private   void  DrawLine( double  x1,  double  y1,  double  x2,  double  y2)//保留原有方法原型,不用改其它畫線代碼
        {
            DrawLine(x1, y1, x2, y2, 
1 , container,  true );
        }
        
private   void  DrawLine( double  x1,  double  y1,  double  x2,  double  y2,  int  thick, Panel panel,  bool  auto)
        {
            
double  tempGap  =  ((x1  +  y1)  >   19   ||   ! auto)  ?   1  : gap; // 就這行加了一個!Auto,其它沒變過
            Line line  =   new  Line()
            {
                X1 
=  x1  *  tempGap  +  marginLeft,
                Y1 
=  y1  *  tempGap  +  marginTop,
                X2 
=  x2  *  tempGap  +  marginLeft,
                Y2 
=  y2  *  tempGap  +  marginTop,
                Stroke 
=   new  SolidColorBrush(Colors.Black),
                StrokeThickness 
=  thick
            };
            panel.Children.Add(line);
        }

說明:

增加一個auto是幹蝦米用的呢?這是因爲在畫十字軌跡時,我們傳進的是實際像素值,然而又可能出現x1 + y1 < 19的情況,爲了保證它是按像素計算,所以...你懂的!
還有,爲啥是19,其實應該是17[數一下橫線+直線有多少條,索引從0開始],這個問題在以前就說過了,這裏不多解釋了,保留19也沒錯。

4:初始化畫棋盤時,把十字軌跡也畫上

05233129_VFPo.gif
         private   void  Draw()
        {
            
// 省略畫棋盤線代碼
      
            
#region  畫棋步軌跡
            
// 創建兩個十字修飾框
            TrackFrom  =   new  Canvas()
            {
                Width 
=  gap,
                Height 
=  gap,
                Margin 
=   new  Thickness( - marginLeft  *   12 - marginLeft  *   12 0 0 )
            };
            TrackTo 
=   new  Canvas()
            {
                Width 
=  gap,
                Height 
=  gap,
                Margin 
=   new  Thickness( - marginLeft  *   12 - marginLeft  *   12 0 0 )
            };
            DrawTrack(TrackFrom);
            DrawTrack(TrackTo);
            container.Children.Add(TrackFrom);
            container.Children.Add(TrackTo);
            
#endregion
            
#region  畫楚河漢界
              DrawFont(
" 路過秋天 " );
            
#endregion
        }

 

二:Chess象棋類增加設置十字焦點方法

 

1:增加設置十字焦點方法

05233129_VFPo.gif
         ///   <summary>
        
///  設置軌跡十字框
        
///   </summary>
         public   void  SetFocus(Point from, Point to)
        {
            from 
=  SwitchPixelArray(from);
            to 
=  SwitchPixelArray(to);
            
double  offset  =  Board.TrackFrom.Width  /   2   -  Board.marginLeft  *   11   -   4 ; // 要減去默認初始位置,默認是*-12
            Canvas.SetLeft(Board.TrackFrom, from.X  -  offset);
            Canvas.SetTop(Board.TrackFrom, from.Y 
-  offset);
            Canvas.SetLeft(Board.TrackTo, to.X 
-  offset);
            Canvas.SetTop(Board.TrackTo, to.Y 
-  offset);
        }

 

說明:

在移動棋步的時候,我們調用一下這個方法,把兩個軌跡移動到相應的位置就OK了,

重點是:移動時,要減去原來的默認初始的位置,這個調整起來很麻煩。

 

三:ChessAction棋子動作類

 

1:棋手移動時調用設置十字軌跡焦點函數

05233129_VFPo.gif
         ///   <summary>
        
///  移動棋子
        
///   </summary>
        
///   <param name="chessman"> 棋子 </param>
        
///   <param name="toX"> 移動到X座標 </param>
        
///   <param name="toY"> 移動到Y座標 </param>
         public   bool  MoveTo(Chessman chessman, Point moveTo)
        {
            
if  (Rule.IsCanMove(chessman, moveTo))
            {
                chessman.ReadyMove 
=   false ;
                chessman.chessman.Background 
=   null ;
                PlayMove(chessman, moveTo);
                Parent.SetFocus(chessman.MovePoint, moveTo);
// 就這一行代碼增加
                HelpMoveStepEvent(chessman, moveTo);
                chessman.MovePoint 
=  moveTo;
                
                
return   true ;
            }
            
return   false ;
        }

 

2:對方棋手下棋手,系統會自動移動棋子,也要自動設置十字軌跡焦點

05233129_VFPo.gif
        ///   <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);
                Parent.SetFocus(from, to);
// 就這一行代碼增加
                chessman.MovePoint  =  to;
                
if  (eatChessman  !=   null )
                {
                    SetIsGameEnd(eatChessman);
                    eatChessman.GoToDead();
                }
            }
        }

 

四:F5看運行結果

 

1:運行後直接上圖了

OK,大夥看到效果了吧!

 

轉載於:https://my.oschina.net/secyaher/blog/274049