博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Silverlight+WCF 新手实例 象棋 棋子移动-规则[兵、车](七)
阅读量:6089 次
发布时间:2019-06-20

本文共 7389 字,大约阅读时间需要 24 分钟。

hot3.png

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

 

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

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

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

///
 
<summary>
    
///
 棋子规则-by 路过秋天
    
///
 
</summary>
    
public
 
class
 ChessRule
    {
    }

 

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

05233157_Ye2j.gif
///
 
<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

05233157_Ye2j.gif
 
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方法就能改成这样了:

05233157_Ye2j.gif
 
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)点

05233157_Ye2j.gif
 
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 
>=
 
0
 
&&
 x2 
<
 
9
 
&&
 y2 
>=
 
0
 
&&
 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
;}

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

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

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

05233157_Ye2j.gif
 
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方向的障碍物[就是有几颗棋子顶着个肺]

一方法又产生了:

05233157_Ye2j.gif
 
///
 
<summary>
        
///
 获取障碍物数量
        
///
 
</summary>
        
public
 
void
 OutCount(Point start, Point end, 
out
 
int
 xCount, 
out
 
int
 yCount)
        {
            xCount 
=
 
0
;
            yCount 
=
 
0
;
            
//
待实现
        }

 

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

05233157_Ye2j.gif
case
 ChessType.Che:
                         
int
 xCount, yCount;
                        OutCount(chessman.MovePoint, moveTo, 
out
 xCount, 
out
 yCount);
                        
if
 (x1 
==
 x2 
&&
 yCount 
==
 
0
 
||
 y1 
==
 y2 
&&
 xCount 
==
 
0
)
                        {
//
坚走/横走没有障碍别
                            
return
 
true
;
                        }
                        
break
;

 

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

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

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

05233157_Ye2j.gif
 
///
 
<summary>
        
///
 动作类
        
///
 
</summary>
        
public
 ChessAction Action
        {
            
get
;
            
set
;
        }
        
public
 ChessRule(ChessAction action)
        {
            Action 
=
 action;
        }

 

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

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

05233157_Ye2j.gif
public
 ChessRule Rule
//
新加的属性
        {
            
get
;
            
set
;
        }
        
public
 ChessAction(Chess ownChess)
        {
            OwnChess 
=
 ownChess;
            Rule 
=
 
new
 ChessRule(
this
);
//
新加的实例化
        }

 

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

 

05233157_Ye2j.gif
 
///
 
<summary>
        
///
 获取障碍物数量
        
///
 
</summary>
        
public
 
void
 OutCount(Point start, Point end, 
out
 
int
 xCount, 
out
 
int
 yCount)
        {
            xCount 
=
 yCount 
=
 
0
;
            Point point;
            
for
 (
int
 i 
=
 
0
; 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;

目前完整代码如下:

 

05233157_Ye2j.gif
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 
>=
 
0
 
&&
 x2 
<
 
9
 
&&
 y2 
>=
 
0
 
&&
 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 
==
 
0
 
||
 y1 
==
 y2 
&&
 xCount 
==
 
0
)
                        {
//
坚走/横走没有障碍别
                            
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 
=
 
0
;
            Point point;
            
for
 (
int
 i 
=
 
0
; 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,这节先实现兵和车的规则,下小节再实现其它棋子规则。

 打完,收工!

作者博客:

转载于:https://my.oschina.net/secyaher/blog/274065

你可能感兴趣的文章
默认虚拟主机设置
查看>>
php中的短标签 太坑人了
查看>>
[译] 可维护的 ETL:使管道更容易支持和扩展的技巧
查看>>
### 继承 ###
查看>>
数组扩展方法之求和
查看>>
astah-professional-7_2_0安装
查看>>
函数是对象-有属性有方法
查看>>
uva 10107 - What is the Median?
查看>>
Linux下基本栈溢出攻击【转】
查看>>
c# 连等算式都在做什么
查看>>
使用c:forEach 控制5个换行
查看>>
java web轻量级开发面试教程摘录,java web面试技巧汇总,如何准备Spring MVC方面的面试...
查看>>
使用ansible工具部署ceph
查看>>
linux系列博文---->深入理解linux启动运行原理(一)
查看>>
Android反编译(一) 之反编译JAVA源码
查看>>
结合当前公司发展情况,技术团队情况,设计一个适合的技术团队绩效考核机制...
查看>>
python-45: opener 的使用
查看>>
cad图纸转换完成的pdf格式模糊应该如何操作?
查看>>
Struts2与Struts1区别
查看>>
网站内容禁止复制解决办法
查看>>