• 第1章 游戏之乐——中国象棋将帅问题


    中国象棋将帅问题

      中国象棋里面双方的“将”和“帅”各自呆在自己的九宫格里,一步只能横移或纵移一格,而且双方不能见面(既不能处在同一条纵线上)。在残局时有的人会用这一规则走出绝妙杀招。假设一方的“将”为A,另一方的“帅”为B,现在求双方所能出现的所有合法位置,所需变量只能用一个字节来保存。

      我们用1~9的数字来,按行优先的顺序来表示每个格点的位置,如下图所示。这样只需要用模余运算就可以得到当前的列号,从而判断A、B是否互斥。

    【解法一】用C语言实现

    一种比较正经的解法,就是用位运算,设一个char变量,前四个字节存一个变量,后四个字节存一个变量。
    #include <stdio.h>
    #define HALF_BITS_LENGTH  4    //存储单元长度的一半,即4位
    #define FULLMASK 255    //存储单元全部bit的mask(掩码),在二进制表示中,是11111111
    #define LMASK (FULLMASK << HALF_BITS_LENGTH)   //左四位,11110000
    #define RMASK (FULLMASK >> HALF_BITS_LENGTH)   //右四位。00001111
    #define RSET(b,n) (b = ((LMASK &b) | (n)))  //将b的右四位设置为n
    #define LSET(b,n) (b = ((RMASK &b) | (n) << HALF_BITS_LENGTH)) //将b左四位设置为n
    #define RGET(b) (RMASK&b)  //得到b右四位的值
    #define LGET(b) ((LMASK&b) >> HALF_BITS_LENGTH)  //得到b左四位的值
    #define GRIDW  3   // 九宫格边界长度
     
    int main()
    {
        unsigned char b;
        for(LSET(b,1);LGET(b)<=GRIDW*GRIDW;LSET(b,(LGET(b)+1)))
        {
            for(RSET(b,1);RGET(b)<=GRIDW*GRIDW;RSET(b,(RGET(b)+1)))
            {
                if(LGET(b)%GRIDW!=RGET(b)%GRIDW)
                {
                    printf("A=%d    B=%d
    ",LGET(b),RGET(b));
                }
            }
        }
     
        return 0;
    }

    同样的思路用java实现如下:

    package chapter1youxizhileChinesechess;
    /**
     * 【解法一】
     * 中国象棋将帅问题
     * @author DELL
     *
     */
    public class ChineseChess1 {
        public static final int HALF_BITS_LENGTH = 4; //存储单元长度的一半,这里是4bit
        public static final int FULLMASK = 255; //全部bit的隐码,即为11111111
        public static final int LMASK = (byte)(255 << HALF_BITS_LENGTH)& 0x0FF;  //无符号左移,11110000
        public static final int RMASK = (byte)(255 >>> HALF_BITS_LENGTH); //无符号右移,00001111
        public static int LSET(byte b, int n){  //将b的左半部分设为n
           return (RMASK & b)^((byte)n << HALF_BITS_LENGTH);
        }
        
        public static int RSET(byte b, int n){ //将b的右半部分是为n
           return (LMASK & b)^(byte)n ;
        }
        
        public static int LGET(byte b){  //获得b的左半部分
            return (LMASK & b) >> HALF_BITS_LENGTH;
        }
        
        public static int RGET(byte b){  //获得b的右半部分
            return RMASK & b;
        }
        public static final int GRIDW = 3;
        public static void main(String[] args) {
            byte b = 0;
            b = (byte) LSET(b,8);
            System.out.println(b);
            for(b=(byte) LSET(b,1);LGET(b)<=GRIDW*GRIDW;b=(byte) LSET(b,LGET(b)+1)){
                for(b=(byte) RSET(b,1);RGET(b)<=GRIDW*GRIDW;b=(byte) RSET(b,RGET(b)+1)){
                    if(LGET(b)%GRIDW != RGET(b)%GRIDW)
                        System.out.println("A = "+LGET(b)+", B = "+RGET(b));
                }
            }
        }
    
    }

     【解法二】

    package chapter1youxizhileChinesechess;
    /**
     * 中国象棋将帅问题
     * 【解法二】
     * @author DELL
     *
     */
    public class ChineseChess2 {
    
        public static void main(String[] args) {
    //        byte i = 81;
    //        while(i!=0){
    //            if(i/9%3!=i%9%3)
    //                System.out.printf("A=%d, B=%d
    ", i/9+1,i%9+1);
    //            i--;
    //        }
    
            byte i = 1;
            while(i!=80){
                if(i/9%3!=i%9%3)
                    System.out.printf("A=%d, B=%d
    ", i/9+1,i%9+1);
                i++;
            }
        }
    
    }

     【解法三】

    有人说是效率最高的:

    //中国象棋将帅问题
    //【解法三】
    #include <stdio.h>
    struct{
        unsigned char a:4;
        unsigned char b:4;
    }i;
    int main(){
        for(i.a=1;i.a<=9;i.a=i.a+1){
            for(i.b=1;i.b<=9;i.b=i.b+1){
                if(i.a%3!=i.b%3)
                    printf("A = %d, B = %d
    ",i.a,i.b);
            }
        }
        return 0;
    }
  • 相关阅读:
    学习C#的一些笔记
    SQL高级应用
    SQL SERVER 视图
    ES5 Study
    面试官技巧
    WebServicexml操作
    用JS和HTML写自己的文本编辑器
    解决Win7 x64 VS2010调试网站出现 vs2010 未能将脚本调试器附加到计算机上的进程。已附加了一个调试器
    Microsoft.Practices.Unity实现代码依赖注入、XML依赖注入和AOP切面编程
    无法对数据库'XXX' 执行删除,因为它正用于复制"的解决方法
  • 原文地址:https://www.cnblogs.com/gaopeng527/p/4599150.html
Copyright © 2020-2023  润新知