上图,将帅不能碰面,列出将帅不碰面的所有可能情况,要求:程序只能用一个只有8位的变量(#define这样的就不算了)

为了更加符合程序员的口味,给将帅位置编号如下:

0--1--2

|    |   |

3--4--5

|    |   |

6--7--8

输出将帅所有可能情况,(0,1)等等

--------------------------------------------------------------------------------------------------------------------------------------------------

思路一:程序框架应该如下,关键是怎么样用一个变量表示将帅位置.

遍历将位置

       遍历帅位置

            如果将帅位置不矛盾,输出

只用8位的变量,要表示2个数,看来可以试试位操作每个表示位置的变量4个位,4位可以表示0-15,足以!

 

方法一:

位字段(为此还复习了位操作...http://www.cnblogs.com/jiayith/p/3500367.html)

如下:

#include <iostream>

using namespace std;

/*定义一个结构体,两个标签,各自4位,总共一个变量的话为8位*/
struct myBits
{
    unsigned char a:4;   //4位可以表示0-15的值了
    unsigned char b:4;
};


int main(void)
{
    myBits my;

    for (my.a=0;my.a<=8;my.a++)
    {
        for (my.b=0;my.b<=8;my.b++)
        {
            if (my.a%3!=my.b%3)
            {
                cout<<"("<<(int)my.a<<","<<(int)my.b<<")"<<endl;
            }
        }
    }

    cin.get();
    return 0;
}

 方法二:

既然都用了位字段,那位操作也应该没什么问题

用一个char,我的机器八位,左4位表示将的位置,右位表示帅的位置,关键是怎么给一个8位的char的左右半边赋值再获得左右半边的值.位操作!

#include <iostream>

/*下面几个宏用于掩码,在获得左右半边的值时用*/
#define  FULLMASK 255                   // 11111111
#define  RMASK (FULLMASK>>4)   //00001111
#define  LMASK (FULLMASK<<4)   //11110000

/*下面是几个获得左右半边值的宏*/
#define GETR(t) (t&RMASK)   //获得右半边4位的值,用掩码,掩盖住左半边的值,注意这个位操作不改变原有值
#define GETL(t) ((t&LMASK)>>4)   //获得左半边4位的值,先掩盖右4位,再把值右移4位,注意这里要价格括号...我猜临时值放在某寄存器里 

/*下面是设置左右半边值的宏*/
#define SETR(t,val) (t=(t&LMASK)|val)//((t=t&LMASK),(t=t|val))   //用十进制val设置右4位,但要保证val可以用4位表示,即val表示值的位在低4位.(这里先清空右四位,再与左4位全是0而右4位是值的val或)
#define SETL(t,val) (t=((t&RMASK)|(val<<4)))//((t=t&RMASK),(t=t|(val<<4)))   //用十进制val设置左4位 (先清空左4位,再把val右边4位的值移动到左边,再与)

int main(void)
{
    using namespace std;

   unsigned char my;   //注意这里一定要用无符号的,要不放最高位为1就麻烦了.... 

    
    for (SETL(my,0);(int)GETL(my)<=8;SETL(my,(int)GETL(my)+1))
    {
        for (SETR(my,0);(int)GETR(my)<=8;SETR(my,(int)GETR(my)+1))
        {
            if (((int)GETL(my)%3)!=((int)GETR(my)%3))
            {
                cout<<"("<<(int)GETL(my)<<","<<(int)GETR(my)<<")\n";
            }
        }
    }

    cin.get();
    return 0;
}

--------------------------------------------------------------------------------------------------------------------------------------------------

 思路二:不用上面的程序模式了,换个思路.

将有9种情况,帅也有9种情况,组合起来共81种情况.

能不能用一个变量表示这81种情况,对于每个情况的值,获得将和帅的值???

可以!

将=0,帅=(0,1,2,3,4,5,6,7,8) 值可以从0到8

将=1,帅=(0,1,2,3,4,5,6,7,8) 值可以从9到17

将=2,帅=(0,1,2,3,4,5,6,7,8)  ..

将=3,帅=(0,1,2,3,4,5,6,7,8) ..

将=4,帅=(0,1,2,3,4,5,6,7,8)

将=5,帅=(0,1,2,3,4,5,6,7,8)

将=6,帅=(0,1,2,3,4,5,6,7,8)

将=7,帅=(0,1,2,3,4,5,6,7,8)

将=8,帅=(0,1,2,3,4,5,6,7,8) 值从72到80

即用一个八位的值val表示所以上述从0到80的81种情况,

val/9即将的值,val%9即帅的值,搞定!

#include <iostream>


int main(void)
{
    using namespace std;

   char val=0;
   while (val<=80)
   {
       if ((val/9%3)!=(val%9%3))
       {
           cout<<"("<<val/9<<","<<val%9<<")"<<endl;
       }
       val++;
   }

    cin.get();
    return 0;
}

--------------------------------------------------------------------------------------------------------------------------------------------------

总结:

1.多角度看问题

2.C/C++位操作的强大,及几种位操作运算符的使用

posted on 2014-01-01 12:15  简单的信仰  阅读(309)  评论(0编辑  收藏  举报