- Code: Select all
#include <string.h>
#include "sd.h"
//Common Table
int TblMult3[81];
int TblDivide3[81];
int TblRmder3[81];
int TblMult9[9];
//Basis Table
int TblCombineMask[512];
int TblTailZero[512];
int TblNumberOne[512];
int TblAnother1[27];
int TblAnother2[27];
int TblShiftLeft[27];
//Table of Decompose Board
int TblBoard_Block[81];
int TblBoard_BlockMask[81];
int TblBoard_GridUniq[81];
//Table of Initial
int TblSelfMask[81];
int TblOtherMask[81];
//Complex Friend Method
int TblMaskSingle[512];
int TblMaskDouble[512];
//Other Table
int TblColumnMask[8];
bool TblUniqFlag[8];
//Complex Method
byte TblShrinkMask[32768];
int TblComplexMask[512];
int TblColumnSingle[512];
int TblShrinkSingle[512];
void CreateTblCommon()
{
for (int i = 0; i < 81; i++)
{
TblMult3[i] = i * 3;
TblDivide3[i] = i / 3;
TblRmder3[i] = i % 3;
}
for (int i = 0; i < 9; i++)
{
TblMult9[i] = i * 9;
}
}
void CreateTblCombineMask()
{
for (int i = 0; i < 512; i++)
{
TblCombineMask[i] = (i | (i << 9) | (i << 18)) ^ BIT_SET_27;
}
}
void CreateTblAnother()
{
for (int i = 0; i < 27; i++)
{
switch (i % 3)
{
case 0: //At Top
TblAnother1[i] = i + 1;
TblAnother2[i] = i + 2;
break;
case 1: //At Middle
TblAnother1[i] = i - 1;
TblAnother2[i] = i + 1;
break;
case 2: //At Bottom
TblAnother1[i] = i - 2;
TblAnother2[i] = i - 1;
break;
}
}
}
void CreateTblTailZero()
{
memset(TblTailZero, 0, sizeof(TblTailZero));
for (int i = 0; i < 512; i++)
{
for (int j = 0; j < 9; j++)
{
if (i & (1 << j))
break;
TblTailZero[i]++;
}
}
}
void CreateTblNumberOne()
{
memset(TblNumberOne, 0, sizeof(TblNumberOne));
for (int i = 0; i < 512; i++)
{
for (int j = 0; j < 9; j++)
{
if (i & (1 << j))
TblNumberOne[i]++;
}
}
}
void CreateTblShiftLeft()
{
for (int i = 0; i < 27; i++)
{
TblShiftLeft[i] = 1 << i;
}
}
void CreateTblBasis()
{
CreateTblCombineMask();
CreateTblAnother();
CreateTblTailZero();
CreateTblNumberOne();
CreateTblShiftLeft();
}
void CreateTblBoard()
{
for (int i = 0; i < 81; i++)
{
TblBoard_Block[i] = i / 27;
TblBoard_BlockMask[i] = 1 << i % 27;
TblBoard_GridUniq[i] = 1 << i % 27 / 9;
}
}
void CreateTblSelfMask()
{
int Mask[3] = { 0x7E3F1F8, 0x71F8FC7, 0x0FC7E3F };
int Row[3] = { 0x7FFFE00, 0x7FC01FF, 0x3FFFF };
for (int i = 0; i < 81; i++)
{
int Palace = i % 9 / 3;
TblSelfMask[i] = Mask[Palace] & Row[i % 27 / 9] | TblBoard_BlockMask[i];
}
}
void CreateTblOtherMask()
{
for (int i = 0; i < 81; i++)
{
TblOtherMask[i] = TblCombineMask[1 << i % 9];
}
}
void CreateTblMaskSingle()
{
for (int i = 0; i < 512; i++)
{
TblMaskSingle[i] = i;
int v = i >> 6; //High 3 bit
if (v != 4 && v != 2 && v != 1)
TblMaskSingle[i] &= 0x3F;
v = i >> 3 & 0x7; //Middle 3 bit
if (v != 4 && v != 2 && v != 1)
TblMaskSingle[i] &= 0x1C7;
v = i & 0x7; //Low 3 bit
if (v != 4 && v != 2 && v != 1)
TblMaskSingle[i] &= 0x1F8;
TblMaskSingle[i] = TblCombineMask[TblMaskSingle[i]];
}
}
void CreateTblMaskDouble()
{
for (int i = 0; i < 512; i++)
{
TblMaskDouble[i] = i;
int v = i >> 6; //High 3 bit
if (v != 6 && v != 5 && v != 3)
TblMaskDouble[i] &= 0x3F;
v = i >> 3 & 0x7; //Middle 3 bit
if (v != 6 && v != 5 && v != 3)
TblMaskDouble[i] &= 0x1C7;
v = i & 0x7; //Low 3 bit
if (v != 6 && v != 5 && v != 3)
TblMaskDouble[i] &= 0x1F8;
TblMaskDouble[i] = TblCombineMask[TblMaskDouble[i]];
}
}
void CreateTblColumnMask()
{
memset(TblColumnMask, 0, sizeof(TblColumnMask));
for (int i = 0; i < 8; i++)
{
for (int j = 0; j < 3; j++)
{
if (i & (1 << j))
TblColumnMask[i] |= 0x1FF << TblMult9[j];
}
}
}
void CreateTblUniqFlag()
{
memset(TblUniqFlag, 0, sizeof(TblUniqFlag));
for (int i = 0; i < 8; i++)
{
if (TblNumberOne[i] >= 2)
TblUniqFlag[i] = true;
}
}
void CreateTblShrinkMask()
{
memset(TblShrinkMask, 0, sizeof(TblShrinkMask));
for (int i = 0; i < 32768; i++)
{
TblShrinkMask[i] |= i & 0x7000 ? 16 : 0;
TblShrinkMask[i] |= i & 0xE00 ? 8 : 0;
TblShrinkMask[i] |= i & 0x1C0 ? 4 : 0;
TblShrinkMask[i] |= i & 0x38 ? 2 : 0;
TblShrinkMask[i] |= i & 0x7 ? 1 : 0;
}
}
void CreateTblComplexMask()
{
int MaskH[9] = { 0x7FFFE07, 0x7FFFE38, 0x7FFFFC0, 0x7FC0FFF, 0x7FC71FF, 0x7FF81FF, 0x1FFFFF, 0xE3FFFF, 0x703FFFF }; //A B C
int MaskV[9] = { 0x7E3F1FF, 0x71F8FFF, 0xFC7FFF, 0x7E3FFF8, 0x71FFFC7, 0xFFFE3F, 0x7FFF1F8, 0x7FF8FC7, 0x7FC7E3F }; //A 0 0
int index;
for (int i = 0; i < 512; i++)
{
if (!(i & 0x7) || !(i & 0x38) || !(i & 0x1C0) || !(i & 0x124) || !(i & 0x92) || !(i & 0x49))
{
TblComplexMask[i] = 0;
continue;
}
TblComplexMask[i] = BIT_SET_27;
//Like Locked Candidate
for (int j = 0; j < 3; j++)
{
for (int k = 0; k < 3; k++)
{
index = TblMult3[k] + j;
if ((i & (1 << index)) && !(i & (1 << (TblMult3[TblAnother1[k]] + j))) && !(i & (1 << (TblMult3[TblAnother2[k]] + j))))
TblComplexMask[i] &= MaskH[index]; //Horizontal
index = TblMult3[j] + k;
if ((i & (1 << index)) && !(i & (1 << TblAnother1[index])) && !(i & (1 << TblAnother2[index])))
TblComplexMask[i] &= MaskV[index]; //Vertical
}
}
}
for (int i = 0; i < 512; i++)
{
if ((i & FULL_TO_SHRINK(TblComplexMask[i])) == 0)
TblComplexMask[i] = 0;
else if ((i & FULL_TO_SHRINK(TblComplexMask[i])) == i)
TblComplexMask[i] = BIT_SET_27;
}
}
void CreateTblColumnSingle()
{
memset(TblColumnSingle, 0, sizeof(TblColumnSingle));
for (int i = 0; i < 512; i++)
{
if (TblNumberOne[i & 0x7] == 0 || TblNumberOne[i & 0x38] == 0 || TblNumberOne[i & 0x1C0] == 0)
continue;
if (TblNumberOne[i & 0x7] == 1) //Low 3 bit
TblColumnSingle[i] |= 0x49;
if (TblNumberOne[i & 0x38] == 1) //Middle 3 bit
TblColumnSingle[i] |= 0x92;
if (TblNumberOne[i & 0x1C0] == 1) //High 3 bit
TblColumnSingle[i] |= 0x124;
}
}
void CreateTblShrinkSingle()
{
for (int i = 0; i < 512; i++)
{
int j = i & FULL_TO_SHRINK(TblComplexMask[i]);
TblShrinkSingle[i] = j;
if (TblNumberOne[j & 0x7] != 1) //Low 3 bit
TblShrinkSingle[i] &= 0x1F8;
if (TblNumberOne[j & 0x38] != 1) //Middle 3 bit
TblShrinkSingle[i] &= 0x1C7;
if (TblNumberOne[j & 0x1C0] != 1) //High 3 bit
TblShrinkSingle[i] &= 0x3F;
}
}
void CreateTable()
{
CreateTblCommon();
CreateTblBasis();
CreateTblBoard();
CreateTblSelfMask();
CreateTblOtherMask();
CreateTblMaskSingle();
CreateTblMaskDouble();
CreateTblColumnMask();
CreateTblUniqFlag();
CreateTblShrinkMask();
CreateTblComplexMask();
CreateTblColumnSingle();
CreateTblShrinkSingle();
}