您的位置:首页 > 其它

Silverlight+WCF 新手实例 象棋 棋子移动-规则[兵、车](七)

2012-03-09 00:00 459 查看
上两节实现了棋子的两种走法,吃子和没移动到线交叉点。不过我们都是没有规则的走,这节为棋子的走法增加规则,棋的规则我就不多说了,基本要找个不会下象棋的很难,就是找到的估计也不会看这文章。

当我们移动棋子的时候,总是要判断一下移动是不是合规则的,合规则的才让下,不合规则的就不能下了,什么马象田马日车炮跑,将军卫士陷九宫,[本人涅造句子]之类的。

好了,原始冲动,新建棋子规则类,也是本棋子裤的最后一个类了:

对着项目内裤右键-》添加类->输入:ChessRule.cs。


///

<summary>

///
棋子规则-by 路过秋天

///

</summary>

public

class
ChessRule
{

}

我们为之新增加一个方法IsCanMove方法,就是棋子要走的时候,用此方法来判断是不是符合规则,返回值就是bool型了。






///

<summary>

///
棋子规则-by 路过秋天

///

</summary>

public

class
ChessRule
{

///

<summary>

///
移动规则

///

</summary>

///

<param name="move">
棋子
</param>

///

<param name="eat">
移动的位置的数组
</param>

///

<returns></returns>

public

bool
IsCanMove(Chessman chessman, Point moveTo)
{

//
实现判断

return

false
;
}
}

每种棋子都有各自的规则,因此我们要用Switch来分支,这里我们在类的外面加上个棋子枚举:


public

enum
ChessType
{
Bing,
Pao,
Che,
Ma,
Xiang,
Shi,
Jiang
}

懂点汉语的一看就知道这E文是什么意思了。

好,我们为规则ChessRule类再加个方法,通过棋子的名称来返回ChessType







public
ChessType GetChessTypeByName(
string
name)
{

switch
(name)
{

case

"

"
:

case

"

"
:

return
ChessType.Bing;

case

"

"
:

return
ChessType.Pao;

case

"

"
:

return
ChessType.Che;

case

"

"
:

return
ChessType.Ma;

case

"

"
:

case

"

"
:

return
ChessType.Shi;

case

"

"
:

case

"

"
:

return
ChessType.Jiang;

case

"

"
:

case

"

"
:

return
ChessType.Xiang;
}

throw

new
Exception(
"
未知名称:
"

+
name);
}

OK,这时候我们再修改下IsCanMove方法就能改成这样了:







public

bool
IsCanMove(Chessman chessman, Point moveTo)
{

//
实现判断

ChessType chessType
=
GetChessTypeByName(chessman.Name);

switch
(chessType)
{

case
ChessType.Bing:

//
待实现

break
;

case
ChessType.Che:

//
待实现

break
;

case
ChessType.Jiang:

//
待实现

break
;

case
ChessType.Ma:

//
待实现

break
;

case
ChessType.Shi:

//
待实现

break
;

case
ChessType.Xiang:

//
待实现

break
;

case
ChessType.Pao:

//
待实现

break
;
}

return

false
;
}

这里增加了一个枚举和方法获取来进行分支,要是嫌麻烦了,就用加枚举了,直接在里面

Swith(chessman.Name){

case "兵": case "卒": //待实现

case "将": case "帅": //待现

case "车": case "帅": //待现

case "炮": //待实现

}

这样也是行的。

好了,现在开始步步一个一个的实现规则。

我们先把几个坐标拿出来弄为x1,y1,x2,y2先,然后进行第一步判断,如果移动的位置超出棋盘范围之内,或者原地走就拒绝,于是代码简单的变成:

由于棋盘有九条直线,十条横线,对应到x,y坐标的范围就是x->(0,8) y->(0,9),原地的话就是(x1,y1)点=(x2,y2)点







public

bool
IsCanMove(Chessman chessman, Point moveTo)
{

//
实现判断

int
x1
=
(
int
)chessman.MovePoint.X;

int
y1
=
(
int
)chessman.MovePoint.Y;

int
x2
=
(
int
)moveTo.X;

int
y2
=
(
int
)moveTo.Y;

if
(x2
>=

&&
x2
<

9

&&
y2
>=

&&
y2
<

10

&&

!
(x1
==
x2
&&
y1
==
y2))
//
在棋盘之内,非原步。

{
ChessType chessType
=
GetChessTypeByName(chessman.Name);

switch
(chessType)
{

case
ChessType.Bing:

//
待实现

break
;

case
ChessType.Che:

//
待实现

break
;

case
ChessType.Jiang:

//
待实现

break
;

case
ChessType.Ma:

//
待实现

break
;

case
ChessType.Shi:

//
待实现

break
;

case
ChessType.Xiang:

//
待实现

break
;

case
ChessType.Pao:

//
待实现

break
;
}
}

return

false
;
}

OK,现在来开始实现第一个兵规则。其实一开始我想啊想:

兵:没过河,只能往前走,过了河,只能直走和横着走。而且每次只能走一步

好,一步一步限制。

1.先判断一下是不是走一步


if
(Math.Abs(y2
-
y1)
+
Math.Abs(x2
-
x1)
!=

1
)
//
只能走一步

{

break
;
}

由于我们第一个判断限制只能走一步,接我们来判断一下棋子是不是往前直走。


if
(x1
==
x2
&&
y1
>
y2){
return

true
;}

接下来我们判断一下棋子是横着走,并且过了河。


if
(y1
==
y2
&&
y1
<

5
){
return

true
;}

由于下棋者,正常都只用位于棋子下方的棋的,所以只要判断下面的棋子的规则就行了。

[备注,当然了,如果你想对上面的棋子也进行潜规则,也是可以的,待讲完发完整代码时再对上面的棋子进行潜规则]

好了,将后面两个合起来,完整的代码就是:







case
ChessType.Bing:

if
(Math.Abs(y2
-
y1)
+
Math.Abs(x2
-
x1)
!=

1
)
//
只能走一步

{

break
;
}

if
((x1
==
x2
&&
y1
>
y2)
||
(y1
==
y2
&&
y1
<

5
))
{
//
只能直走 或者 过了河左右走

return

true
;
}

break
;

看,一个兵的规则,咋家用两个if搞定了。看来,规则判断也不是那么难的。

好,下一个是什么呢?车

车:能够直走或横着走,不能越过棋子,吃倒是可以,自家颜色不给吃[这个我们在外面点击棋子就有判断等于切换棋子了]

我想了想,想出一个方法,获取一颗棋子原始点和移动到的点之间在X和Y方向的障碍物[就是有几颗棋子顶着个肺]

一方法又产生了:







///

<summary>

///
获取障碍物数量

///

</summary>

public

void
OutCount(Point start, Point end,
out

int
xCount,
out

int
yCount)
{
xCount
=

;
yCount
=

;

//
待实现

}

好,有了这个方法,车子的移动规则就相当的简单了,看下说明就清楚了:






case
ChessType.Che:

int
xCount, yCount;
OutCount(chessman.MovePoint, moveTo,
out
xCount,
out
yCount);

if
(x1
==
x2
&&
yCount
==

||
y1
==
y2
&&
xCount
==

)
{
//
坚走/横走没有障碍别

return

true
;
}

break
;

没想到车子的移动规则也变的这么简单了。

呵呵,那个获取障碍物的方法还没有实现呢

接下来实现一下吧,这里我们要为棋子规则ChessRule类引入一个构造函数,为什么要引入Action呢,因为移动规则只有在移动的时候才现身出来闪一下。其它时候规则是退隐江湖的。







///

<summary>

///
动作类

///

</summary>

public
ChessAction Action
{

get
;

set
;
}

public
ChessRule(ChessAction action)
{
Action
=
action;
}

既然构造里引入ChessAction,同样,在ChessAction里也得实例化下这个ChessRule,不然怎么将自身传过来啊。

回到ChessAction的构造函数,同时加一属性:






public
ChessRule Rule
//
新加的属性

{

get
;

set
;
}

public
ChessAction(Chess ownChess)
{
OwnChess
=
ownChess;
Rule
=

new
ChessRule(
this
);
//
新加的实例化

}

OK,现在可以实现那个获取障碍物棋子数的方法了:







///

<summary>

///
获取障碍物数量

///

</summary>

public

void
OutCount(Point start, Point end,
out

int
xCount,
out

int
yCount)
{
xCount
=
yCount
=

;
Point point;

for
(
int
i
=

; i
<
Action.Parent.ChessmanList.Count; i
++
)
{
point
=
Action.Parent.ChessmanList[i].MovePoint;

if
(start.Y
==
point.Y
&&
Math.Min(start.X, end.X)
<
point.X
&&
point.X
<
Math.Max(start.X, end.X))
{
xCount
++
;
}

if
(start.X
==
point.X
&&
Math.Min(start.Y, end.Y)
<
point.Y
&&
point.Y
<
Math.Max(start.Y, end.Y))
{
yCount
++
;
}
}
}

小小解说一下:

1。遍历所有的棋子的坐标

2。start.Y==point.Y时,说明是Y坐标相同,就是横线上的比较

3。start.X==point.X时,说明是X坐标相同,就是直线上的比较

4。接下来就是 起始点[最小值]<被遍历棋子坐标<终点[最大值],在这里面的棋子数就是障碍物数量了。

最后,把那个返回值默认返回return false;

目前完整代码如下:






public

enum
ChessType
{
Bing,
Pao,
Che,
Ma,
Xiang,
Shi,
Jiang
}

///

<summary>

///
棋子规则-by 路过秋天

///

</summary>

public

class
ChessRule
{

///

<summary>

///
动作类

///

</summary>

public
ChessAction Action
{

get
;

set
;
}

public
ChessRule(ChessAction action)
{
Action
=
action;
}

///

<summary>

///
移动规则

///

</summary>

///

<param name="move">
棋子
</param>

///

<param name="eat">
移动的位置的数组
</param>

///

<returns></returns>

public

bool
IsCanMove(Chessman chessman, Point moveTo)
{

//
实现判断

int
x1
=
(
int
)chessman.MovePoint.X;

int
y1
=
(
int
)chessman.MovePoint.Y;

int
x2
=
(
int
)moveTo.X;

int
y2
=
(
int
)moveTo.Y;

if
(x2
>=

&&
x2
<

9

&&
y2
>=

&&
y2
<

10

&&

!
(x1
==
x2
&&
y1
==
y2))
//
在棋盘之内,非原步。

{
ChessType chessType
=
GetChessTypeByName(chessman.Name);

switch
(chessType)
{

case
ChessType.Bing:

if
(Math.Abs(y2
-
y1)
+
Math.Abs(x2
-
x1)
!=

1
)
//
只能走一步

{

break
;
}

if
((x1
==
x2
&&
y1
>
y2)
||
(y1
==
y2
&&
y1
<

5
))
{
//
只能直走 或者 过了河左右走

return

true
;
}

break
;

case
ChessType.Che:

int
xCount, yCount;
OutCount(chessman.MovePoint, moveTo,
out
xCount,
out
yCount);

if
(x1
==
x2
&&
yCount
==

||
y1
==
y2
&&
xCount
==

)
{
//
坚走/横走没有障碍别

return

true
;
}

break
;

case
ChessType.Jiang:

//
待实现

break
;

case
ChessType.Ma:

//
待实现

break
;

case
ChessType.Shi:

//
待实现

break
;

case
ChessType.Xiang:

//
待实现

break
;

case
ChessType.Pao:

//
待实现

break
;
}
}

return

false
;
}

public
ChessType GetChessTypeByName(
string
name)
{

switch
(name)
{

case

"

"
:

case

"

"
:

return
ChessType.Bing;

case

"

"
:

return
ChessType.Pao;

case

"

"
:

return
ChessType.Che;

case

"

"
:

return
ChessType.Ma;

case

"

"
:

case

"

"
:

return
ChessType.Shi;

case

"

"
:

case

"

"
:

return
ChessType.Jiang;

case

"

"
:

case

"

"
:

return
ChessType.Xiang;
}

throw

new
Exception(
"
未知名称:
"

+
name);
}

///

<summary>

///
获取障碍物数量

///

</summary>

public

void
OutCount(Point start, Point end,
out

int
xCount,
out

int
yCount)
{
xCount
=
yCount
=

;
Point point;

for
(
int
i
=

; i
<
Action.Parent.ChessmanList.Count; i
++
)
{
point
=
Action.Parent.ChessmanList[i].MovePoint;

if
(start.Y
==
point.Y
&&
Math.Min(start.X, end.X)
<
point.X
&&
point.X
<
Math.Max(start.X, end.X))
{
xCount
++
;
}

if
(start.X
==
point.X
&&
Math.Min(start.Y, end.Y)
<
point.Y
&&
point.Y
<
Math.Max(start.Y, end.Y))
{
yCount
++
;
}
}
} }

OK,这节先实现兵和车的规则,下小节再实现其它棋子规则。

打完,收工!

作者博客:http://cyq1162.cnblogs.com/

原文链接:
http://www.cnblogs.com/cyq1162/archive/2010/07/09/1774210.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐