| 8.3 ハッシュ関数の実装 |
本節では、前節定義したハッシュ関数の実装を行います。
修正するファイルは"board.c"です。
最初にBoardクラスにメンバ変数を追加します。
追加する変数はハッシュ値の差分(マスの状態に応じてハッシュ値とのXORをとる値)です。
Board構造体の定義は以下のようになります。
struct _Board
{
int Disk[NUM_DISK];
int Stack[NUM_STACK];
int *Sp;
int DiskNum[3];
int Pattern[NUM_PATTERN_ID];
int PatternID[NUM_DISK][NUM_PATTERN_DIFF];
int PatternDiff[NUM_DISK][NUM_PATTERN_DIFF];
HashValue HashDiffBlack[NUM_DISK];
HashValue HashDiffWhite[NUM_DISK];
HashValue HashDiffTurn;
};
乱数を生成するマクロget_rand()を追加します。
他のファイルにも定義されていませすが、以下の定義を"board.h"にも追加します。
0〜(in_max-1)までの整数をランダムに返します。
#define get_rand(in_max) ((int)((double)(in_max) * rand() / (RAND_MAX + 1.0)))
ハッシュ値の差分を初期化する関数Board_InitializeHashDiff()を追加します。
関数の内部は以下のようになっています。
static void Board_InitializeHashDiff(Board *self)
{
int i;
self->HashDiffTurn.Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);;
self->HashDiffTurn.High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);;
for (i = 0; i < NUM_DISK; i++) {
self->HashDiffBlack[i].Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);
self->HashDiffBlack[i].High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);
self->HashDiffWhite[i].Low = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);
self->HashDiffWhite[i].High = (unsigned long)get_rand(256) | ((unsigned long)get_rand(256) << 8) |
((unsigned long)get_rand(256) << 16) | ((unsigned long)get_rand(256) << 24);
}
}
差分毎に乱数を割り当てています。
またBoardクラスの生成関数でBoard_InitializeHashDiff()を呼ぶようにします。
Board *Board_New(void)
{
Board *self;
self = malloc(sizeof(Board));
if (self) {
Board_InitializePatternDiff(self);
Board_InitializeHashDiff(self);
Board_Clear(self);
}
return self;
}
最後にハッシュ関数Board_HashValue()を実装します。
void Board_HashValue(Board *self, int in_color, HashValue *out_value)
{
int i;
out_value->Low = 0;
out_value->High = 0;
for (i = 0; i < NUM_DISK; i++) {
switch (self->Disk[i]) {
case BLACK:
out_value->Low ^= self->HashDiffBlack[i].Low;
out_value->High ^= self->HashDiffBlack[i].High;
break;
case WHITE:
out_value->Low ^= self->HashDiffWhite[i].Low;
out_value->High ^= self->HashDiffWhite[i].High;
break;
default:
break;
}
}
if (in_color == WHITE) {
out_value->Low ^= self->HashDiffTurn.Low;
out_value->High ^= self->HashDiffTurn.High;
}
}
各マスの状態を調べ、XORをとっているだけです。
また白番のときにはHashDiffTurnとのXORもとるようにします。
次節からは置換表の実装を行います。