プログラミングの美しさ:第一章1.2中国将棋の将帥問題


/*中国将棋将帥問題:昔から将帥は顔を合わすことができなかった10は9 8 8 7 6 4 4 3 2 1帥a b c d e f g h i Aを将、Bを帥、Aは{d 10,f 10,d 8,f 8}に制限され、Bは{d 3,f 3,d 1,f 1}に制限される.各ステップA、Bは、横方向または縦方向に1つ移動することができる.AとBは同じ長手方向の直線上ではいけません.例えば、Aはd 10の位置にあり、Bはd 1,d 2,d 3の位置にありません.
A、Bのすべての合法的な位置を出力するプログラムを書いてください.コードに変数を格納するには、1バイトしか使用できません.最初は全配列の問題です
アルゴリズム:Aの位置を巡るBの位置判断A、Bの位置の組み合わせが要求を満たしていれば出力
記憶する必要があるのはA,Bの位置情報であり,ループごとに更新する必要がある.各格子点の位置を1~9で行優先の順序で表す論理座標システムを作成する.これにより,モジュール演算により現在のカラム番号が得られ,AとBが反発しているか否かが判断される.
AとBの2つのサブの位置情報は、1つの変数のみで記憶される.したがって,ビットから文章を作成することしかできず,バイト8ビット,256個の値でA,Bの位置情報を十分に表すことができる.したがって,このバイトを1つに分けて,上位4ビットがA,下位4ビットがBとなるように,各駒に16種類の位置表示方法があり,十分である(牛が追い詰めている)
byte b(10100101)の右4ビット(0101)をn(0011)1としてbの右側のbitsを先にクリアし、11110000&10100101で10100000|000001で10100011を得る
2 byte b(10100101)の左4ビット(1010)を(0011)にして左の4 bitをクリアしながら右の4 bitを保存し、00001111&10100101と得られた00000101でn 0011を4ビット左にシフトしたn<<4=0011000または演算00000101|0011000で0010101を得る
3得られるbyteのデータの右4ビットまたは左4ビット(10100101の1010および0101)b左側のbitsをクリアし、右側のbits 00001111&10100101を保持して00000101右側のbitsをクリアするとともに、左のbits 11110000&1010001を保持して10100000結果右シフト4ビット10100000>>4=00001010
他の変数制約を宣言せずにforループを作成する方法1 byteメモリユニットを繰り返し利用し,これをループカウンタとして前述したアクセスと読み込み技術で判断することができる.マクロでコードを抽象化することもできます.for( LEST(b,1) ; LEST(b) <= GRIDW * GRIDW ; LSET(b,(LGET(b) + 1))) */
/*キー:1そのためこのバイトを2つに分けて、上位4位がA、下位4位がBとなるように、駒ごとに16種類の位置表示方法があるので、十分です(牛逼啊)2アルゴリズム:Aの位置を巡るBの位置判断A、Bの位置の組み合わせが要求を満たしていれば3#define LEFT_を出力しますMASK(FULL_MASK<<4)//注意、defineで物を定義する場合、2つの変数がある場合はカッコ4#define RIGHT_を付ける必要がありますMASK(FULL_MASK>>4)//右マスクは右4位がすべて1 5#define LSET(b,n)(b=((b&RIGHT_MASK)|((n)<<4)))/ビットbの左をnに設定し、主にループで使用する.採用する方法は、//左クリア(右マスク(00001111)に対応)してから、数nを左に4桁ずらして、上記の2つの数を使ってもいいし、値付け操作を漏らさないように注意//注意nは括弧で囲んで、1文字6#define LGET(b)((b&LEFT_MASK)>4)//ビットbの左4桁を取得する方法です.まず右4位をクリアし、//さらに右に4位移動すると7 if(LGET(b)%STEP!=RGET(b)%STEP//牛逼,用九宫格模拟两者取模后的余数不同,表示//不是一条竖线上*/
#include <stdio.h>
#define FULL_MASK 255
//#define HALF_MOVE 4
#define LEFT_MASK (FULL_MASK << 4) //  , define       ,      ,     
#define RIGHT_MASK (FULL_MASK >> 4) //       4   1
#define LSET(b,n) (b = ((b & RIGHT_MASK) | ((n) << 4) ) )//   b      n,         。      ,
//    (      (00001111)    ),    n   4 ,            ,         
//  n       ,      ,      
#define RSET(b,n) (b = ((b & LEFT_MASK) | (n) ) )//   b      n,      :
//    (       (11110000)  ),     n  
#define LGET(b) ( (b & LEFT_MASK) >> 4)//    b   4     ,    4   ,
//   4   
#define RGET(b) (b & RIGHT_MASK)//    b   4     ,     4         
#define STEP 3

void ChineseChess_define()
{
 unsigned char b;
 int iCnt = 0;
 for(LSET(b,1) ; LGET(b) <= STEP * STEP ; LSET(b,(LGET(b) + 1) ) )
 {
  for(RSET(b,1) ; RGET(b) <= STEP * STEP ; RSET(b,(RGET(b) + 1) ) )
  {
   if(LGET(b) % STEP != RGET(b) % STEP)//  ,                 ,   
    //          
   {
    printf("A=%d,B=%d
",LGET(b),RGET(b)); iCnt++; } } } printf("%d
",iCnt); } void ChineseChess_mod() { unsigned char i = 81;//?BYTE int iCnt = 0; while(i--) { if(i / 9 % 3 == i % 9 % 3)//? { continue; } printf("A=%d,B=%d
",i / 9 + 1 , i % 9 + 1); iCnt++; } printf("%d
",iCnt); } typedef struct Num { unsigned char a:3; unsigned char b:4; }Num; void ChineseChess_struct() { int iCnt = 0; Num Num1; for(Num1.a = 1 ; Num1.a <= 9 ; Num1.a++) { for(Num1.b = 1 ; Num1.b <= 9; Num1.b++) { if(Num1.a % 3 != Num1.b % 3) { printf("A=%d,B=%d
",Num1.a,Num1.b); iCnt++; } } } printf("%d
",iCnt); } void process() { ChineseChess_define(); //ChineseChess_mod(); //ChineseChess_struct();// } int main(int argc,char* argv[]) { process(); getchar(); return 0; }