前言
繼之前Silverlight+WCF 新手實例 象棋系列四十篇之後,一個多月的時間都在寫CYQ.Data框架系列[CYQ.Data 輕量數據層之路 框架開源系列 索引],
讓各位對該Silverlight+WCF 象棋系列有興趣的網友久候了,上一系列詳見:[Silverlight+WCF 新手實例 象棋 專題索引]
今天開始就在之前四十篇續上,直到把 [Silverlight+WCF 新手實例 象棋 在線演示] 上的最新代碼寫完,謝謝支持!
讓各位對該Silverlight+WCF 象棋系列有興趣的網友久候了,上一系列詳見:[Silverlight+WCF 新手實例 象棋 專題索引]
今天開始就在之前四十篇續上,直到把 [Silverlight+WCF 新手實例 象棋 在線演示] 上的最新代碼寫完,謝謝支持!
亂七雜八說兩句:
一個多月沒碰VS2010了,今天回頭看原來的象棋系列代碼,感覺到有點陌生了,
好多原來的思路,都忘的差不多了,要續寫這系列文章,感覺還得像個新手一樣重溫下代碼才行呢。
本系列爲進階優化系列,會在原來的基礎上,慢慢改動很多代碼的哦,歡迎持續關注!
好多原來的思路,都忘的差不多了,要續寫這系列文章,感覺還得像個新手一樣重溫下代碼才行呢。
本系列爲進階優化系列,會在原來的基礎上,慢慢改動很多代碼的哦,歡迎持續關注!
正文:
我們先回顧下,截一張上一系列 最後一節[Silverlight+WCF 新手實例 象棋 主界面-棋譜-回放-結局(四十) ]裏的一張圖片先:
OK,從這圖片我知道雙方是在下棋了,可是我們並不知道現在該誰下了?
當然了,認真看一下棋譜,還是知道剛剛是黑方下了一步,不過還是要很用力的猜車一平二是怎麼個平法。
十字軌跡的出現,解決了這個問題,如果到QQ平臺下過棋,也見過的,就是那個棋子周圍加上的一個邊框了,那這個爲啥叫十字軌跡?這個這個...
當然了,認真看一下棋譜,還是知道剛剛是黑方下了一步,不過還是要很用力的猜車一平二是怎麼個平法。
十字軌跡的出現,解決了這個問題,如果到QQ平臺下過棋,也見過的,就是那個棋子周圍加上的一個邊框了,那這個爲啥叫十字軌跡?這個這個...
好!大夥知道十字軌跡是什麼就好了,現在說說實現思路
大夥想啊,十字軌跡是在棋步移動之後,在棋盤上就有兩個出現了,一個在移動的棋子的原來位置,一個在移動後的位置,而且整個棋盤就只能有兩個,於是,我們的思路定位就很簡單了。
一:在棋盤上先創建好兩個十字軌跡,默認隱藏
二:在棋手移動完棋子之後,把兩個十字軌跡移動到相應的位置
一:在棋盤上先創建好兩個十字軌跡,默認隱藏
二:在棋手移動完棋子之後,把兩個十字軌跡移動到相應的位置
就這麼兩步,很簡單吧,該出手時就出手。
實現步驟如下:
一:棋盤Board類畫十字軌跡
1:增加兩個十字軌跡屬性
///
<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多代碼
}
/// 棋盤 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:增加一函數,用於畫十字軌跡
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|
}
{
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個參數了,以前只有四個的。
注意哦,DrawLine方法變成5個參數了,以前只有四個的。
3:DrawLine方法小調整
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);
}
{
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:初始化畫棋盤時,把十字軌跡也畫上
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
}
{
// 省略畫棋盤線代碼
#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:增加設置十字焦點方法
///
<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);
}
/// 設置軌跡十字框
/// </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:棋手移動時調用設置十字軌跡焦點函數
///
<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 ;
}
/// 移動棋子
/// </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:對方棋手下棋手,系統會自動移動棋子,也要自動設置十字軌跡焦點
///
<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();
}
}
}
/// 系統自動移動棋子
/// </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,大夥看到效果了吧!