zoukankan      html  css  js  c++  java
  • Silverlight+WCF 新手实例 象棋 棋子移动规则[兵、车](七)

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

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

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

    对着项目内裤右键-》添加类->输入: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 >= 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;}

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

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

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

     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 
    = 0;
                yCount 
    = 0;
                
    //待实现
            }

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

    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呢,因为移动规则只有在移动的时候才现身出来闪一下。其它时候规则是退隐江湖的。

     /// <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 = 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;

    目前完整代码如下:

    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,这节先实现兵和车的规则,下小节再实现其它棋子规则。

     打完,收工!

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

    版权声明:本文原创发表于 博客园,作者为 路过秋天 本文欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则视为侵权。
    个人微信公众号
    创业QQ群:617713515
    Donation(扫码支持作者):支付宝:
    Donation(扫码支持作者):微信:
  • 相关阅读:
    建立十字链表
    KMP算法
    魔术师发牌问题(循环链表)
    约瑟夫问题(循环链表)
    中缀表达式 转 (逆)波兰表达式
    中缀表达式求值
    迷宫问题(回溯法)
    范数
    AUC
    概率论
  • 原文地址:https://www.cnblogs.com/cyq1162/p/1774210.html
Copyright © 2011-2022 走看看