/******************************************************************
 *						Author:	Zhou Yundong
 *						Time: 20080516 00:19
 ******************************************************************/
#include "Stdafx.h"
#include "Think.h"

void initialSodoku()
{
	moveSum('0', 'l'); // 0 to leftSum
	moveIdx('0', 'l'); // 0 to leftIdx
	movePare('0', 'l'); // 0 to leftPare
	moveKilpare('0', 'l'); // 0 to leftPare
	moveHead('0', 'l'); // 0 to leftHead
	moveUniq('0', 'l'); // 0 to leftUniq
	moveSaw('0', 'l'); // 0 to leftSaw
	moveExtra('0', 'l'); // 0 to leftExtra
	editKind = 0;
	gameKind = 0;
	firstIntoSodoku = true;
}

void moveBoard(char from, char to)
{
	int i;
	if(from == 'l' && to == 'r')
	{
		for(i=0; i<81; i++)
		{
			rightBoard[i] = leftBoard[i];
		}
	}
	else if(from == 'r' && to == 'l')
	{
		for(i=0; i<81; i++)
		{
			leftBoard[i] = rightBoard[i];
		}
	}
	else if(from == 'l' && to == 'b')
	{
		for(i=0; i<81; i++)
		{
			board[i] = leftBoard[i];
		}
	}
	else if(from == '0' && to == 'r')
	{
		for(i=0; i<81; i++)
		{
			rightBoard[i] = 0;
		}
	}
	else if(from == '0' && to == 'l')
	{
		for(i=0; i<81; i++)
		{
			leftBoard[i] = 0;
		}
	}
	else if(from == '0' && to == 'b')
	{
		for(i=0; i<81; i++)
		{
			board[i] = 0;
		}
	}
	else if(from == 'a' && to == 'r')
	{
		for(i=0; i<81; i++)
		{
			rightBoard[i] = answerBoard[i];
		}
	}
	else if(from == 'b' && to == 'r')
	{
		for(i=0; i<81; i++)
		{
			rightBoard[i] = board[i];
		}
	}
	else if(from == 'b' && to == 'a')
	{
		for(i=0; i<81; i++)
		{
			answerBoard[i] = board[i];
		}
	}
	else if(from == 'a' && to == 'b')
	{
		for(i=0; i<81; i++)
		{
			board[i] = answerBoard[i];
		}
	}
	else if(from == 'b' && to == 'k')
	{
		for(i=0; i<81; i++)
		{
			bakBoard[i] = board[i];
		}
	}
	else if(from == 'k' && to == 'b')
	{
		for(i=0; i<81; i++)
		{
			board[i] = bakBoard[i];
		}
	}
	else if(from == 't' && to == 'b')
	{
		for(i=0; i<81; i++)
		{
			board[i] = tempBoard[i];
		}
	}
	else if(from == 'b' && to == 't')
	{
		for(i=0; i<81; i++)
		{
			tempBoard[i] = board[i];
		}
	}
	else if(from == 'b' && to == 'l')
	{
		for(i=0; i<81; i++)
		{
			leftBoard[i] = board[i];
		}
	}
	else if(from == 't' && to == 'r')
	{
		for(i=0; i<81; i++)
		{
			rightBoard[i] = tempBoard[i];
		}
	}
	else if(from == 't' && to == 'a')
	{
		for(i=0; i<81; i++)
		{
			answerBoard[i] = tempBoard[i];
		}
	}
}

bool legalCheck(char* str)
{
	int i;
	for(i=0; i<81; i++)
	{
		if((str[i] < '0' || str[i] > '9') && str[i] != '.') return false;
	}
	for(i=81; i<243; i++)
	{
		if(str[i] < '0' || str[i] > '9') return false;
	}
	for(i=243; i<405; i+=2)
	{
		if((str[i] < '0' || str[i] > '7') && (str[i] != '8' || str[i+1] != '0')) return false;
	}
	for(i=405; i<549; i++)
	{
		if(str[i] < '0' || str[i] > '2') return false;
	}
	for(i=549; i<693; i++)
	{
		if(str[i] < '0' || str[i] > '3') return false;
	}
	for(i=693; i<855; i+=2)
	{
		if((str[i] < '0' || str[i] > '7') && (str[i] != '8' || str[i+1] != '0')) return false;
	}
	for(i=855; i<936; i++)
	{
		if(str[i] < '0' || str[i] > '9') return false;
	}
	return true;
}

bool readFileR(char* fileName)
{
	int i;
	FILE *fp;
	char str[1000];
	if((fp=fopen(fileName, "r")) == NULL) return false;
	fgets(str, 1000, fp);
	if(!legalCheck(str))
	{
		return false;
	}
	for(i=0; i<81; i++)
	{
		if(str[i] >= '0' && str[i] <= '9')
		{
			rightBoard[i] = str[i] - '0';
		}
		else
		{
			rightBoard[i] = 0;
		}
	}
	return true;
}

bool readFile(char* fileName)
{
	int i;
	FILE *fp;
	char str[1000];
	if((fp=fopen(fileName, "r")) == NULL) return false;
	fgets(str, 1000, fp);
	if(!legalCheck(str))
	{
		return false;
	}
	for(i=0; i<81; i++)
	{
		if(str[i] >= '0' && str[i] <= '9')
		{
			leftBoard[i] = str[i] - '0';
		}
		else
		{
			leftBoard[i] = 0;
		}
	}
	for(i=81; i<243; i+=2)
	{
		leftSum[(i-81)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=243; i<405; i+=2)
	{
		leftIdx[(i-243)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=405; i<549; i++)
	{
		leftPare[i-405] = str[i]-'0';
	}
	for(i=549; i<693; i++)
	{
		leftKilpare[i-549] = str[i]-'0';
	}
	for(i=693; i<855; i+=2)
	{
		leftSaw[(i-693)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=855; i<936; i++)
	{
		leftExtra[i-855] = str[i] - '0';
	}
	fclose(fp);
	return true;
}

bool writeFile(char* pathName)
{
	int i;
	FILE *fp;
	char str[1000];
	if((fp=fopen(pathName, "w+")) == NULL) return false;
	for(i=0; i<81; i++)
	{
		str[i] = leftBoard[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+81] = leftSum[i] / 10 + '0';
		str[2*i+82] = leftSum[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+243] = leftIdx[i] / 10 + '0';
		str[2*i+244] = leftIdx[i] % 10 + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+405] = leftPare[i] + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+549] = leftKilpare[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+693] = leftSaw[i] / 10 + '0';
		str[2*i+694] = leftSaw[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[i+855] = leftExtra[i] + '0';
	}
	str[936] = '\0';
	fputs(str, fp);
	fclose(fp);
	return true;
}

bool readStrBoard(char *str)
{
	int i;
	if(!legalCheck(str))
	{
		return false;
	}
	for(i=0; i<81; i++)
	{
		if(str[i] >= '0' && str[i] <= '9')
		{
			board[i] = str[i] - '0';
		}
		else
		{
			board[i] = 0;
		}
	}
	for(i=81; i<243; i+=2)
	{
		sum[(i-81)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=243; i<405; i+=2)
	{
		idx[(i-243)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=405; i<549; i++)
	{
		pare[i-405] = str[i]-'0';
	}
	for(i=549; i<693; i++)
	{
		kilpare[i-549] = str[i]-'0';
	}
	for(i=693; i<855; i+=2)
	{
		saw[(i-693)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=855; i<936; i++)
	{
		extra[i-855] = str[i] - '0';
	}
	return true;
}

char* writeStrAnswer(char *str)
{
	int i;
	for(i=0; i<81; i++)
	{
		str[i] = answerBoard[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+81] = answerSum[i] / 10 + '0';
		str[2*i+82] = answerSum[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+243] = answerIdx[i] / 10 + '0';
		str[2*i+244] = answerIdx[i] % 10 + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+405] = answerPare[i] + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+549] = kilpare[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+693] = saw[i] / 10 + '0';
		str[2*i+694] = saw[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[i+855] = extra[i] + '0';
	}
	str[936] = '\0';
	return str;
}

bool readStr(char *str)
{
	int i;
	if(!legalCheck(str))
	{
		return false;
	}
	for(i=0; i<81; i++)
	{
		if(str[i] >= '0' && str[i] <= '9')
		{
			leftBoard[i] = str[i] - '0';
		}
		else
		{
			leftBoard[i] = 0;
		}
	}
	for(i=81; i<243; i+=2)
	{
		leftSum[(i-81)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=243; i<405; i+=2)
	{
		leftIdx[(i-243)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=405; i<549; i++)
	{
		leftPare[i-405] = str[i]-'0';
	}
	for(i=549; i<693; i++)
	{
		leftKilpare[i-549] = str[i]-'0';
	}
	for(i=693; i<855; i+=2)
	{
		leftSaw[(i-693)/2] = (str[i]-'0')*10+(str[i+1]-'0');
	}
	for(i=855; i<936; i++)
	{
		leftExtra[i-855] = str[i] - '0';
	}
	return true;
}

char* writeStr(char *str)
{
	int i;
	for(i=0; i<81; i++)
	{
		str[i] = leftBoard[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+81] = leftSum[i] / 10 + '0';
		str[2*i+82] = leftSum[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+243] = leftIdx[i] / 10 + '0';
		str[2*i+244] = leftIdx[i] % 10 + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+405] = leftPare[i] + '0';
	}
	for(i=0; i<144; i++)
	{
		str[i+549] = leftKilpare[i] + '0';
	}
	for(i=0; i<81; i++)
	{
		str[2*i+693] = leftSaw[i] / 10 + '0';
		str[2*i+694] = leftSaw[i] % 10 + '0';
	}
	for(i=0; i<81; i++)
	{
		str[i+855] = leftExtra[i] + '0';
	}
	str[936] = '\0';
	return str;
}

/////////////////////////////以下关于变换/////////////////////////////
int transCourse[40]; // 1:数值交换 2:行交换 3:列交换 4:三行交换 5:三列交换
int pTransCourse;
void swapMode1(int a, int b, bool flag=true)
{
	for(int i=0; i<81; i++)
	{
		if(board[i] == a)
		{
			board[i] = b;
		}
		else if(board[i] == b)
		{
			board[i] = a;
		}
	}
	if(flag)
	{
		transCourse[pTransCourse++] = (1<<24) + (a<<8) + b;
	}
}

void swapMode2(int a, int b, bool flag=true)
{
	int temp;
	int skip = mult9[b-a];
	for(int i=mult9[a]; i<mult9[a]+9; i++)
	{
		temp = board[i];
		board[i] = board[i+skip];
		board[i+skip] = temp;
	}
	if(flag)
	{
		transCourse[pTransCourse++] = (2<<24) + (a<<8) + b;
	}
}

void swapMode3(int a, int b, bool flag=true)
{
	int i;
	int temp;
	int skip = b - a;
	for(i=a; i<81; i+=9)
	{
		temp = board[i];
		board[i] = board[i+skip];
		board[i+skip] = temp;
	}
	if(flag)
	{
		transCourse[pTransCourse++] = (3<<24) + (a<<8) + b;
	}
}

void swapMode4()
{
	swapMode2(3, 6);
	swapMode2(4, 7);
	swapMode2(5, 8);
}

void swapMode5()
{
	swapMode3(3, 6);
	swapMode3(4, 7);
	swapMode3(5, 8);
}

void swapMode31(int a, int b)
{
	swapMode3(a, b);
	swapMode1(a+1, b+1);
}

bool handleUnify()
{
	int i;
	int startPoint[7] = {3, 3, 4, 6, 6, 7};
	int endPoint[7] = {4, 5, 5, 7, 8, 8};
	// 唯一解判断与备份与得到全盘面
	moveBoard('b', 'k'); // board to bakBoard
	getAnswer();
	if(flagAnswer != 1)
	{
		return false; // 无解或者多解
	}
	moveBoard('a', 'b'); // answerBoard to board
	// 记录变换过程
	pTransCourse = 0;
	// 数值变换：得到第一行123456789
	for(i=0; i<8; i++)
	{
		if(board[i] != i+1)
		{
			swapMode1(board[i], i+1);
		}
	}
	// 继续变换：要求[9]<[18]
	if(board[9] > board[18])
	{
		swapMode2(1, 2);
	}
	switch(board[9])
	{
		case 4:
			switch(board[18])
			{
				case 6:
					swapMode31(4, 5);
					break;
				case 8:
					swapMode31(6, 7);
					break;
				case 9:
					swapMode31(6, 8);
					break;
			}
			break;
		case 5:
			swapMode31(3, 4);
			switch(board[18])
			{
				case 6:
					swapMode31(4, 5);
					break;
				case 8:
					swapMode31(6, 7);
					break;
				case 9:
					swapMode31(6, 8);
					break;
			}
			break;
		case 6:
			swapMode31(3, 5);
			switch(board[18])
			{
				case 8:
					swapMode31(6, 7);
					break;
				case 9:
					swapMode31(6, 8);
					break;
			}
			break;
		case 7:
		case 8:
			swapMode5();
			swapMode1(4, 7);
			swapMode1(5, 8);
			swapMode1(6, 9);
			if(board[9] == 4 && board[18] == 6)
			{
				swapMode31(4, 5);
			}
			else if(board[9] == 5)
			{
				swapMode31(3, 4);
				swapMode31(4, 5);
			}
			break;
	}
	// 继续变换：要求[27]<[36]<[45], [54]<[63]<[72]
	for(i=0; i<6; i++)
	{
		if(board[mult9[startPoint[i]]] > board[mult9[endPoint[i]]])
		{
			swapMode2(startPoint[i], endPoint[i]);
		}
	}
	// 继续变换：要求[27]<[54]
	if(board[27] > board[54])
	{
		swapMode4();
	}
	// 继续变换：要求[36]<[63]
	if(board[36]== 6 && board[63] == 5)
	{
		swapMode31(4, 5);
	}
	// 继续变换：要求[36]<[72]
	if(board[36]== 8 && board[72] == 7)
	{
		swapMode31(6, 7);
	}
	// 继续变换：要求[45]<[72]
	if(board[45]== 9 && board[72] == 8)
	{
		swapMode31(7, 8);
	}
	// 继续变换：要求[45]<[63]
	if(board[45]== 8 && board[63] == 7)
	{
		swapMode31(6, 7);
	}
	moveBoard('k', 'b'); // bakBoard to board
	// 对board重新变换
	for(i=0; i<pTransCourse; i++)
	{
		if((transCourse[i]>>24) == 1)
		{
			swapMode1((transCourse[i]>>8)&0xFF, transCourse[i]&0xFF, false);
		}
		else if((transCourse[i]>>24) == 2)
		{
			swapMode2((transCourse[i]>>8)&0xFF, transCourse[i]&0xFF, false);
		}
		else if((transCourse[i]>>24) == 3)
		{
			swapMode3((transCourse[i]>>8)&0xFF, transCourse[i]&0xFF, false);
		}
	}
	return true;
}
