ビットボードの任意のラインを8ビットに変換・逆変換
本記事で用いるビットボード
符号なし64ビット整数を8×8の行列と考えたものを用います。
63ビット目がA1、0ビット目がH8に対応します。
また、ビットの行数、列数を以下のように考えます。
よって、本記事ではあるビットの行数、列数を取得する、以下の2つの関数を使用します。
- あるビットの行数を取得する
int getRow(int bit) {
return bit / 8;
}
- あるビットの列数を取得する
int getColumn(int bit) {
return bit % 8;
}
本記事で用いるA1-H8方向、A8-H1方向とは
本記事では、左斜め上から右斜め下に向かう方向をA1-H8方向と呼び、左斜め下から右斜め上に向かう方向をA8-H1方向と呼びます。
A1-H8方向(左斜め上から右斜め下に向かう方向)
A8-H1方向(左斜め下から右斜め上に向かう方向)
あるビットの水平方向のラインを8ビットに変換する
あるビットの水平方向のラインをマスクし、あるビットの行数の8倍だけ右シフトすれば良いです。
- コード例
using ull = unsigned long long;
unsigned char convertHorizontalTo8(ull x, int bit) {
int const SHIFT = getRow(bit) * 8;
ull const MASK = 0x00000000000000FF << SHIFT;
return (x & MASK) >> SHIFT;
}
あるビットの垂直方向のラインを8ビットに変換する
あるビットの垂直方向のラインをマスクし、列数だけ右シフトすることで右端に集め、0x0102040810204080を掛けることで垂直方向のラインが上位8ビットに集まるので、56ビットだけ右シフトすれば良いです。
- コード例
unsigned char convertVerticalTo8(ull x, int bit) {
int const CLMN = getColumn(bit);
ull const MASK = 0x0101010101010101 << CLMN;
return (((x & MASK) >> CLMN) * 0x0102040810204080) >> 56;
}
あるビットのA1-H8方向のラインを8ビットに変換する
あるビットのA1-H8方向のマスクをあらかじめ配列に持っておき、マスクを取って0x0101010101010101を掛けることで、あるビットのA1-H8方向のラインが上位8ビットに集まるので、これを56ビットだけ右シフトすれば良いです。
- 例1
- 例2
ここで、あるビットのA1-H8方向のマスクは、0から63までのビットに対して個別に用意しなくとも、(あるビットの行数 - あるビットの列数)の値が一緒ならマスクも同じものが使えるので、(行数 - 列数 + 7)を添え字としてマスクの配列を参照すれば良いです。
ull const DIA_A1H8_MASK[] = {
0x0000000000000080, 0x0000000000008040, 0x0000000000804020,
0x0000000080402010, 0x0000008040201008, 0x0000804020100804,
0x0080402010080402, 0x8040201008040201, 0x4020100804020100,
0x2010080402010000, 0x1008040201000000, 0x0804020100000000,
0x0402010000000000, 0x0201000000000000, 0x0100000000000000
};
ull getDiagonalA1H8Mask(int bit) {
return DIA_A1H8_MASK[(getRow(bit) - getColumn(bit)) + 7];
}
unsigned char convertDiagonalA1H8To8(ull x, int bit) {
ull const MASK = getDiagonalA1H8Mask(bit);
return ((x & MASK) * 0x0101010101010101) >> 56;
}
あるビットのA8-H1方向のラインを8ビットに変換する
あるビットのA8-H1方向のマスクをあらかじめ配列に持っておき、マスクを取って0x0101010101010101を掛けることで、あるビットのA8-H1方向のラインが上位8ビットに集まるので、これを56ビットだけ右シフトすれば良いです。
- 例1
- 例2
先程と同様に、あるビットのA8-H1方向のマスクは、0から63までのビットに対して個別に用意しなくとも、(あるビットの行数 + あるビットの列数)の値が一緒ならマスクも同じものが使えるので、(行数 + 列数)を添え字としてマスクの配列を参照すれば良いです。
ull const DIA_A8H1_MASK[] = {
0x0000000000000001, 0x0000000000000102, 0x0000000000010204,
0x0000000001020408, 0x0000000102040810, 0x0000010204081020,
0x0001020408102040, 0x0102040810204080, 0x0204081020408000,
0x0408102040800000, 0x0810204080000000, 0x1020408000000000,
0x2040800000000000, 0x4080000000000000, 0x8000000000000000
};
ull getDiagonalA8H1Mask(int bit) {
return DIA_A8H1_MASK[getRow(bit) + getColumn(bit)];
}
unsigned char convertDiagonalA8H1To8(ull x, int bit) {
ull const MASK = getDiagonalA8H1Mask(bit);
return ((x & MASK) * 0x0101010101010101) >> 56;
}
あるビットの水平方向のラインを変換した8ビットを元のビットボードに逆変換する
8ビットを、あるビットの行数の8倍だけ左シフトすればよいです。
- コード例
ull convert8ToHorizontal64(unsigned char x, int bit) {
return (ull)x << (getRow(bit) * 8);
}
あるビットの垂直方向のラインを変換した8ビットを元のビットボードに逆変換する
8ビットに0x0101010101010101を掛けて、A1からH8の対角線のマスクを取ったものに0x00000000000000FFを掛けると、左端に垂直方向のラインが現れるので、左端のマスクを取り、(7 - あるビットの列数)だけ右シフトすれば良いです。
- 8ビット
- 0x0101010101010101を掛ける
- A1からH8の対角線のマスクを取る
- 0x00000000000000FFを掛けると、左端に垂直方向のラインが現れる
- 左端のマスクを取る
- (7 - あるビットの列数)だけ右シフトする
- コード例
ull convert8ToVertical64(unsigned char x, int bit) {
return (((((ull)x
* 0x0101010101010101) & 0x8040201008040201)
* 0x00000000000000FF) & 0x8080808080808080)
>> (7 - getColumn(bit));
}
あるビットのA1-H8方向のラインを変換した8ビットを元のビットボードに逆変換する
8ビットに0x0101010101010101を掛け、あるビットのA1-H8方向のマスクを取れば良いです。
- コード例
ull convert8ToDiagonalA1H8(unsigned char x, int bit) {
ull const MASK = getDiagonalA1H8Mask(bit);
return ((ull)x * 0x0101010101010101) & MASK;
}
あるビットのA8-H1方向のラインを変換した8ビットを元のビットボードに逆変換する
先程のA1-H8方向と同様に、8ビットに0x0101010101010101を掛け、あるビットのA8-H1方向のマスクを取れば良いです。
- コード例
ull convert8ToDiagonalA8H1(unsigned char x, int bit) {
ull const MASK = getDiagonalA8H1Mask(bit);
return ((ull)x * 0x0101010101010101) & MASK;
}
感想
オセロとかで使えます。
Author And Source
この問題について(ビットボードの任意のラインを8ビットに変換・逆変換), 我々は、より多くの情報をここで見つけました https://qiita.com/ysuzuk81/items/1749d4c90456a9a080eb著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .