display.cpp

来自「一个在VISUAL C++下编程的soduku系统 里面有界面 有出盘 也比较简」· C++ 代码 · 共 1,214 行 · 第 1/3 页

CPP
1,214
字号
	r = row - (row % 3);
	c = col - (col % 3);

	for (j=r; j<r+3; j++){
		for (k=c; k<c+3; k++){
			if (NoOfPoss(all[j][k]) <= poss){
				if ( (all[j][k] & ~cell) == 0 ){
					found++;
					if (!QuickSolve && setBlue)
						BlueBits[j][k] = cell;
				}
			}
		}
	}
	return found;
}

/*------------------------------------------------------------
  Eliminate values defined by cell from a row
------------------------------------------------------------*/
unsigned CDisplay::eliminate_row_dup(unsigned row, unsigned cell)
{
	unsigned i, eliminated;
	
	eliminated = 0;
	
	for (i=0; i<9; i++){
		if ( (all[row][i] & cell) && ((all[row][i] & ~cell) != 0) ) {
			all[row][i] &= ~cell;
			if (!QuickSolve)
				RedBits[row][i] = cell;
			eliminated++;
		}
	}
	return eliminated;
}

/*------------------------------------------------------------
  Eliminate values defined by cell from a col
------------------------------------------------------------*/
unsigned CDisplay::eliminate_col_dup(unsigned col, unsigned cell)
{
	unsigned i, eliminated;
	
	eliminated = 0;
	
	for (i=0; i<9; i++){
		if ( (all[i][col] & cell) && ((all[i][col] & ~cell) != 0) ) {
			all[i][col] &= ~cell;
			eliminated++;
			if (!QuickSolve)
				RedBits[i][col] = cell;
		}
	}
	return eliminated;
}

/*------------------------------------------------------------
  Eliminate values defined by cell from a 3x3
------------------------------------------------------------*/
unsigned CDisplay::eliminate_3x3_dup(unsigned row, unsigned col, unsigned cell)
{

	unsigned r, c, j, k, eliminated;
	
	eliminated = 0;
	r = row - (row % 3);
	c = col - (col % 3);

	for (j=r; j<r+3; j++){
		for (k=c; k<c+3; k++){
		if ( (all[j][k] & cell) && ((all[j][k] & ~cell) != 0) ) {
				all[j][k] &= ~cell;
				eliminated++;
				if (!QuickSolve)
					RedBits[j][k] = cell;
			}
		}
	}
	return eliminated;
}

/*------------------------------------------------------------
  Calculate no of values to eliminate
------------------------------------------------------------*/
unsigned CDisplay::total_poss()
{
	unsigned char j,k;
	unsigned t=0;
	
	for (j=0; j<9; j++)
		for (k=0; k<9; k++){
			t += NoOfPoss( all[j][k] ) - 1;
		}
	return t;
}

signed CDisplay::solve()
{
	unsigned t, left, this_loop, j, k;
	int 	tt;
	
	printf("Orignal puzzle is\n");
	//dump_all();
	
	msgstr = _T("");
	for (j=0; j<9; j++)
		for (k=0; k<9; k++)
			pCell[j][k]->SetBackgroundColor(FALSE, cellDefaultColor);

	//printf("Total nos to eliminate are %d\n", total_poss());
		if (total_poss()==0){
			dump_all();
			AfxMessageBox("   ***SOLVED***   ");
			return 0;
		}
	
	do{
		this_loop = 0;
		//dump_all();

		left = total_poss();
		//WaitForButton();

		if (!left)
			break;

		t = 1;
		tt = remove_dup(t);
		if (tt == -1)
			return -1;
			
		this_loop += tt;
		if (tt)
			continue;
		
		tt = eliminate_lonely();
		this_loop += tt;
		if (tt)
			continue;
		
		t = 2;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;
					
		t = 3;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;
		
		t = 4;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;
	
		t = 5;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;

		t = 6;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;

		t = 7;
		tt = remove_dup(t);
		this_loop += tt;
		if (tt)
			continue;

		tt = eliminate_lonely_cross();
		this_loop += tt;

	}while(0);
	dump_all();
	if (!this_loop)
		AfxMessageBox("Sorry, that's the best I can do without guessing\nYou can try 'QuickSolve' button for complete solution");
	
	return this_loop;	
}

unsigned CDisplay::dump_all()
{
#if 1
	//CString str = _T("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031{\\fonttbl{\\f0\\fnil\\fcharset0 Courier New;}}{\\colortbl ;\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green255\\blue0;\\red0\\green0\\blue255;}");
	//CString str = _T("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031{\\fonttbl{\\f0\\fnil\\fcharset0 Arial;}}{\\colortbl ;\\red0\\green0\\blue0;\\red255\\green0\\blue0;\\red0\\green255\\blue0;\\red0\\green0\\blue255;}");
	CString str = _T("{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031{\\fonttbl{\\f0\\fnil\\fcharset0 Courier New;}}{\\colortbl ;\\red140\\green140\\blue140;\\red255\\green0\\blue0;\\red67\\green186\\blue50;\\red0\\green0\\blue255;}");
	CString cellstr, tmpstr, strempty=_T("");
	char buf[100];
	unsigned int j, k, val, bm;

	for (j=0; j<9; j++){
		for (k=0; k<9; k++){
			cellstr = str;
			if ( NoOfPoss(all[j][k]) == 1 && NoOfPoss(RedBits[j][k]) == 0){
				cellstr += "\\fs40 ";
				if (NoOfPoss(BlueBits[j][k]) == 0)
					cellstr += "\\cf3 \\b ";
				else
					cellstr += "\\cf4 \\b ";

				for (val=0,bm=all[j][k]; bm!=0; val++,bm>>=1);
				tmpstr.Format("%d", val);
				cellstr += tmpstr;
				setRTF(pCell[j][k], cellstr);
			} else {
				cellstr += "\\fs19 ";
				for (val=1; val<=9; val++){
					bm = 0x1 << (val-1);
					if (RedBits[j][k] & bm)
						cellstr += "\\cf2 \\b ";
					else if (BlueBits[j][k] & bm)
						cellstr += "\\cf4 \\b ";
					else
						cellstr += "\\cf1 \\b0 ";
					 if ( (RedBits[j][k] & bm) || (all[j][k] & bm) || (BlueBits[j][k] & bm))
						 tmpstr.Format("%d", val);
					 else
						 tmpstr.Format(".");
					 cellstr += tmpstr;
					 if (val==5){
						 cellstr += "\\par ";
					 }
				}
				cellstr += " ";
				setRTF(pCell[j][k], cellstr);
			}
			RedBits[j][k] = BlueBits[j][k] = 0;
		}
	}

	return total_poss();
#else
	return 0;
#endif
}

unsigned CDisplay::DoQuickSolve()
{
	unsigned this_loop, j, k, bm, last, org_all[9][9], left;
	int	tt;

	do{
		this_loop = 0;
		left = total_poss();

		if (!left)
			break;

		tt = remove_dup(1);
		if (tt == -1)
			return 0;
			
		this_loop += tt;
		if (tt)
			continue;
		
		tt = eliminate_lonely();
		this_loop += tt;
		if (tt)
			continue;
		
		tt = remove_dup(2);
		this_loop += tt;
		if (tt)
			continue;
					
		tt = remove_dup(3);
		this_loop += tt;
		if (tt)
			continue;
		
		tt = remove_dup(4);
		this_loop += tt;
		if (tt)
			continue;
	
		tt = eliminate_lonely_cross();
		this_loop += tt;

	}while(this_loop);
	
	if (total_poss()){
		for (j=0; j<9; j++){
			for (k=0; k<9; k++){
				if (NoOfPoss( all[j][k]) > 1){
					memcpy(org_all, all, 9*9*sizeof(unsigned));
					for (bm=0x1; bm<=0x100; bm<<=1){
						if (all[j][k] & bm){
							last = all[j][k];
							all[j][k] = bm;
							if (StopGuess)
								return 0;
							if (total_guesses && !(total_guesses % 300)){
								CString str;
								str.Format("So far I've guessed %d values\nAnd had found %d solution(s)\nDo you want me to look for more?", total_guesses, NoOfSol);
								if (AfxMessageBox(str, MB_YESNO | MB_ICONQUESTION) == IDNO){
									StopGuess = 1;
									return 0;
								}
							}
							total_guesses++;
							if (DoQuickSolve() ) {
								memcpy(all, org_all, 9*9*sizeof(unsigned));
								all[j][k] = last;
								//return 1;
							}else{
								memcpy(all, org_all, 9*9*sizeof(unsigned));
								all[j][k] = last;
							}
								
						}
					}
					return 0;
				}
			}
		}
	}else{
		if (NoOfSol >= 1000){
			CString str;
			str.Format("I've found %d solutions already\nI don't think even YOU have time to view all %d solutions", NoOfSol, NoOfSol);
			AfxMessageBox(str, MB_ICONEXCLAMATION);
			StopGuess = 1;
			return 0;
		}
		solutions[NoOfSol] = (unsigned int *) malloc(sizeof(unsigned)*9*9);
		if (solutions == NULL){
			AfxMessageBox("Not enough memory");
			return 0;
		}
		memcpy(solutions[NoOfSol], all, 9*9*sizeof(unsigned));
		NoOfSol++;
		return 1;
	}

	return 0;
}

void CDisplay::OnQuicksolve() 
{
	// TODO: Add your control notification handler code here
	unsigned i;
	CString str;
	float t;

	QuickSolve = 1;
	StopGuess = 0;
	total_guesses = 0;
	if (NoOfSol)
		for (i=0; i<NoOfSol; i++)
			if (solutions[i])
				free(solutions[i]);

	NoOfSol = 0;
	dur_time.Start();
	if (DoQuickSolve() == 0 && !NoOfSol){
		AfxMessageBox("Invalid puzzle, can not be solved");
	}
	dur_time.Stop();
	/*if (total_guesses > 1000){
		AfxMessageBox("Limiting number of guesses to 200");
	}*/

	QuickSolve = 0;
	if (NoOfSol > 1){
		memcpy(all, solutions[0], sizeof(unsigned)*9*9);
		dump_all();
		MultiSol dlg;

		dlg.NoOfSol = NoOfSol;
		dlg.solutions = solutions;

		dlg.DoModal();

	/*unsigned int **solutions, NoOfSol, CurrentSol;*/
	} else {
		t = dur_time.GetDuration()/(double)1000;
		str.Format("%f ms", t);
		m_Time.SetWindowText(str);
		memcpy(all, solutions[0], sizeof(unsigned)*9*9);
		dump_all();
	}

	
}

void CDisplay::setRTF(CRichEditCtrl *pCell, CString text) 
{

	// This is hard-coded for example purposes. It is likely this would
	// be read from file or another source.
	EDITSTREAM es;
	es.dwCookie = (DWORD)&text; // Pass a pointer to the CString to the callback function
	es.pfnCallback = MEditStreamInCallback; // Specify the pointer to the callback function

	pCell->StreamIn(SF_RTF,es); // Perform the streaming
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?