Click here to Skip to main content
15,884,353 members
Articles / Desktop Programming / MFC

A Sudoku Teacher Using Boost Libraries

Rate me:
Please Sign up or sign in to vote.
4.73/5 (27 votes)
7 Jul 20067 min read 68.1K   1.9K   60  
A Sudoku teacher using multi_index_container, lambda, and other Boost libraries.
// STUBLDlg.cpp : implementation file
//

#include "stdafx.h"
#include "STUBL.h"
#include "STUBLDlg.h"
#include "SudokuPuzzle.h"
#include <sstream>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// CAboutDlg dialog used for App About

class CAboutDlg : public CDialog
{
public:
	CAboutDlg();

// Dialog Data
	enum { IDD = IDD_ABOUTBOX };

	protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support

// Implementation
protected:
	DECLARE_MESSAGE_MAP()
};

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}

void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CSTUBLDlg dialog




CSTUBLDlg::CSTUBLDlg(CWnd* pParent /*=NULL*/)
	: CDialog(CSTUBLDlg::IDD, pParent)
{
	m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}

void CSTUBLDlg::DoDataExchange(CDataExchange* pDX)
{
	DDX_Control(pDX, IDC_BUTTON_SHOWHINTS, m_buttonHints);
	DDX_Control(pDX, IDC_LIST_REASONS, m_lbReasons);
	CDialog::DoDataExchange(pDX);
}

BEGIN_MESSAGE_MAP(CSTUBLDlg, CDialog)
	ON_WM_SYSCOMMAND()
	ON_WM_PAINT()
	ON_WM_QUERYDRAGICON()
	ON_WM_CTLCOLOR()
	ON_WM_DROPFILES()
    ON_CONTROL_RANGE(EN_CHANGE, 4000, 4091, OnSquareChanged)
	//}}AFX_MSG_MAP
	ON_COMMAND(ID_FILE_MYOPEN, &CSTUBLDlg::OnFileOpen)
	ON_COMMAND(ID_FILE_SAVEAS, &CSTUBLDlg::OnFileSaveAs)
	ON_COMMAND(ID_FILE_TYPEINPUZZLE, &CSTUBLDlg::OnFileTypeInPuzzle)
	ON_COMMAND(ID_FILE_MYCLOSE, &CSTUBLDlg::OnFileClose)
	ON_COMMAND(ID_PUZZLE_CLEAR, &CSTUBLDlg::OnPuzzleClear)
	ON_COMMAND(ID_PUZZLE_RESET, &CSTUBLDlg::OnPuzzleReset)
	ON_COMMAND(ID_HELP_ABOUTSTUBL, &CSTUBLDlg::OnHelpAboutStubl)
    ON_BN_CLICKED(IDC_BUTTON_SOLVE, &CSTUBLDlg::OnBnClickedButtonSolve)
	ON_BN_CLICKED(IDC_BUTTON_SHOWHINTS, &CSTUBLDlg::OnBnClickedButtonShowhints)
	ON_BN_CLICKED(IDC_BUTTON_HISTORY, &CSTUBLDlg::OnBnClickedButtonHistory)
	ON_BN_CLICKED(IDC_BUTTON_STEP, &CSTUBLDlg::OnBnClickedButtonStep)
	ON_BN_CLICKED(IDC_BUTTON_STEP_UNTIL_ANSWERFOUND, &CSTUBLDlg::OnBnClickedButtonStepUntilAnswerfound)
	ON_BN_CLICKED(IDC_BUTTON_SHOWANSWERS, &CSTUBLDlg::OnBnClickedButtonShowanswers)
END_MESSAGE_MAP()


// CSTUBLDlg message handlers

BOOL CSTUBLDlg::OnInitDialog()
{
	CDialog::OnInitDialog();

	// Add "About..." menu item to system menu.

	// IDM_ABOUTBOX must be in the system command range.
	ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);
	ASSERT(IDM_ABOUTBOX < 0xF000);

	CMenu* pSysMenu = GetSystemMenu(FALSE);
	if (pSysMenu != NULL)
	{
		CString strAboutMenu;
		strAboutMenu.LoadString(IDS_ABOUTBOX);
		if (!strAboutMenu.IsEmpty())
		{
			pSysMenu->AppendMenu(MF_SEPARATOR);
			pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
		}
	}

	// Set the icon for this dialog.  The framework does this automatically
	//  when the application's main window is not a dialog
	SetIcon(m_hIcon, TRUE);			// Set big icon
	SetIcon(m_hIcon, FALSE);		// Set small icon

    pPuzzle = new Sudoku();

	cbAnswer = new CBrush(RGB(0xE6,0xE8,0xFA));
	cbHint = new CBrush(RGB(0xAF, 0xEE, 0xEE));
	cbBlank = new CBrush(RGB(255, 255, 255));
	cbImposs = new CBrush(RGB(0x8e, 0x23, 0x23));

	cdDlgBgColor = new CBrush(RGB(0xEB, 0xC7, 0x9E));

    const int xdim = 36;
    const int ydim = 36;

    cf = new CFont();
    cf->CreateFont(
        xdim,
        0,
        0,
        0,
        FW_NORMAL,
        FALSE, 
        FALSE,
        0, 
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_SWISS,
        "Arial");

    cfAnswer = new CFont();
    cfAnswer->CreateFont(
        xdim,
        0,
        0,
        0,
        FW_BOLD,
        FALSE, 
        FALSE,
        0, 
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_SWISS,
        "Arial");

    cfHints = new CFont();
    cfHints->CreateFont(
        14,
        0,
        0,
        0,
        FW_NORMAL,
        FALSE, 
        FALSE,
        0, 
        ANSI_CHARSET,
        OUT_DEFAULT_PRECIS,
        CLIP_DEFAULT_PRECIS,
        DEFAULT_QUALITY,
        DEFAULT_PITCH | FF_SWISS,
        "Arial");



    CSudokuEdit *tmpEdit;
    int id = 4000;

    CRect rStart(10, 10, 10+xdim, 10+ydim);

    CRect rPos = rStart;

    for (int row = 0; row < 9; ++row)
    {
        rPos.left = rStart.left;
        rPos.right = rStart.right;

        for (int col = 0; col < 9; ++col)
        {
            tmpEdit = new CSudokuEdit();
			DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_TABSTOP | ES_CENTER | ES_MULTILINE | ES_NUMBER;
			if ((row == 0) && (col == 0))
				dwStyle |= WS_GROUP;
            tmpEdit->Create(dwStyle, rPos, this, ++id);
			tmpEdit->SetCellBrushes(cbBlank, cbAnswer, cbHint, cbImposs);
			tmpEdit->SetCellFonts(cf, cfAnswer, cfHints, cf);
			tmpEdit->SetCellTextColors(RGB(0,0,0), RGB(0x8E, 0x23, 0x23), RGB(0x21, 0x5E, 0x21), RGB(0x00, 0xff, 0x7f));

            tmpEdit->SetFont(cf);
			tmpEdit->LimitText(1);
			tmpEdit->SetPuzzlePtr(pPuzzle);
			tmpEdit->SetCellNum(row*9 + col);
			tmpEdit->SetCellState(CS_NORMAL);

			tmpEdit->SetLB(&m_lbReasons);
            Boxes[row][col] = tmpEdit;

            rPos.left += (xdim + 2);
            rPos.right += (xdim + 2);
            if ((col == 2) || (col == 5))
            {
                rPos.left += 4;
                rPos.right += 4;
            }
        }
        rPos.bottom += (ydim + 2);
        rPos.top += (ydim + 2);
        if ((row == 2) || (row == 5))
        {
            rPos.bottom += 4;
            rPos.top += 4;
        }
    }

	SetHints(false);

	for (int i=0; i<81; ++i)
		m_puzzleDef[i] = 0;

	GetDlgItem(IDC_BUTTON_HISTORY)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_SHOWHINTS)->EnableWindow(FALSE);
	GetDlgItem(IDC_LIST_REASONS)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_STEP)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_SOLVE)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_STEP_UNTIL_ANSWERFOUND)->EnableWindow(FALSE);
	GetDlgItem(IDC_BUTTON_SHOWANSWERS)->EnableWindow(FALSE);

	m_playState = SPS_UNINIT;	// no puzzle entered yet

	return TRUE;  // return TRUE  unless you set the focus to a control
}

void CSTUBLDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
	if ((nID & 0xFFF0) == IDM_ABOUTBOX)
	{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
	}
	else
	{
		CDialog::OnSysCommand(nID, lParam);
	}
}

// If you add a minimize button to your dialog, you will need the code below
//  to draw the icon.  For MFC applications using the document/view model,
//  this is automatically done for you by the framework.

void CSTUBLDlg::OnPaint()
{
	if (IsIconic())
	{
		CPaintDC dc(this); // device context for painting

		SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);

		// Center icon in client rectangle
		int cxIcon = GetSystemMetrics(SM_CXICON);
		int cyIcon = GetSystemMetrics(SM_CYICON);
		CRect rect;
		GetClientRect(&rect);
		int x = (rect.Width() - cxIcon + 1) / 2;
		int y = (rect.Height() - cyIcon + 1) / 2;

		// Draw the icon
		dc.DrawIcon(x, y, m_hIcon);
	}
	else
	{
		CDialog::OnPaint();
	}
}

// The system calls this function to obtain the cursor to display while the user drags
//  the minimized window.
HCURSOR CSTUBLDlg::OnQueryDragIcon()
{
	return static_cast<HCURSOR>(m_hIcon);
}

void CSTUBLDlg::OnBnClickedButtonSolve()
{
	if (pPuzzle->SolvePuzzle())
		MessageBox("Puzzle Solved");
	else
		MessageBox("Unable to solve puzzle!");

	OnBnClickedButtonShowanswers();
}


void CSTUBLDlg::Restore(char *fName)
{

	OnPuzzleClear();

    CFile file;
    char cBuf[256];

    if (file.Open(fName, CFile::modeRead))
    {
        int fSize = file.Read(cBuf, 256);
        file.Close();

		int iCell = 0;
		int index = 0;

        char answerBuf[2];
        answerBuf[1] = '\0';

		while ((index < fSize) && (iCell != 81))
        {
			int answer;
			bool bValidChar = true;

			switch (cBuf[index])
			{
				case '0':
				case '.':
					answer = 0;
		            answerBuf[0] = ' ';
					break;

				case '1':
				case '2':
				case '3':
				case '4':
				case '5':
				case '6':
				case '7':
				case '8':
				case '9':
					answer = cBuf[index] - '0';
		            answerBuf[0] = cBuf[index];
					break;

				default:
					bValidChar = false;
					break;
			}

			if (bValidChar)
			{
				m_puzzleDef[iCell] = answer;
				Boxes[iCell/9][iCell%9]->SetWindowTextA(answerBuf);
				if (answer != 0)
				{
					pPuzzle->SetAnswer(iCell, answer, std::string("Read from File"));
					Boxes[iCell/9][iCell%9]->SetCellState(CS_ANSWER);
				}

				Boxes[iCell/9][iCell%9]->RefreshCell(false, true);
				++iCell;
			}
			++index;
        }
    }

	GetDlgItem(IDC_BUTTON_HISTORY)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_SHOWHINTS)->EnableWindow(TRUE);
	GetDlgItem(IDC_LIST_REASONS)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_STEP)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_SOLVE)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_STEP_UNTIL_ANSWERFOUND)->EnableWindow(TRUE);
	GetDlgItem(IDC_BUTTON_SHOWANSWERS)->EnableWindow(TRUE);

	m_playState = SPS_PLAYING;

	PerformInitialCheck();

	//if (pPuzzle->SolvePuzzle())
	//	MessageBox("Puzzle Solved");
	//else
	//	MessageBox("Unable to solve puzzle!");
}


bool CSTUBLDlg::GetFileName(bool save, CString& cs)
{
    char szFilters[]="Sudoku Files (*.sudoku)|*.sudoku|All Files (*.*)|*.*||";

    CFileDialog *fileDlg;

    if (save)
    {
        fileDlg = new CFileDialog(FALSE, "Sudoku", "*.Sudoku", OFN_OVERWRITEPROMPT | 
            OFN_PATHMUSTEXIST, szFilters, this);
    }
    else
    {
        fileDlg = new CFileDialog(TRUE, "Sudoku", "*.Sudoku",
            OFN_FILEMUSTEXIST| OFN_HIDEREADONLY, szFilters, this);
    }
   
    // Display the file dialog. When user clicks OK, fileDlg.DoModal() 
    // returns IDOK.
    if( fileDlg->DoModal ()==IDOK )
    {
        cs = fileDlg->GetPathName();
        return true;
    }
   
    return false;
};

void CSTUBLDlg::OnSquareChanged( UINT nID )
{
    int square = nID - 4001;

    CSudokuEdit* tmpEdit = Boxes[square/9][square%9];

	if (m_playState == SPS_UNINIT)
	{
		MessageBox("Please enter a puzzle in one of three ways:\n\r"
			"1.  By selecting File->Type In Puzzle\n\r"
			"2.  By selecting File->Open\n\r"
			"3.  By dragging and dropping a sudoku file");
		tmpEdit->SetWindowTextA("");
		return;
	}

	tmpEdit->SetChanged(false);

	if (tmpEdit->GetCellState() == CS_HINT)
	{
	}
	else
	{
		CString csNum;
		tmpEdit->GetWindowText(csNum);
		int iVal = atoi(csNum.GetBuffer());

		csNum.ReleaseBuffer();

		if (m_playState == SPS_ENTERING_PUZZLE)
			m_puzzleDef[square] = iVal;

		if (iVal == 0)
		{
			//pPuzzle->ClearAnswer(square);
			tmpEdit->SetCellState(CS_NORMAL);
			tmpEdit->SetGuess(0);
		}
		else
		{
			if (pPuzzle->IsDigitPossible(square, iVal))
			{
				if (m_playState == SPS_ENTERING_PUZZLE)
				{
					tmpEdit->SetCellState(CS_GUESS);
					tmpEdit->SetGuess(iVal);
					//pPuzzle->SetAnswer(square, iVal, "Puzzle Input");
					//tmpEdit->SetCellState(CS_ANSWER);
				}
				else
				{
					int realAnswer = pPuzzle->GetAnswer(square);
					if ((realAnswer != 0) && (realAnswer == iVal))
					{
						tmpEdit->SetCellState(CS_ANSWER);
					}
					else
					{
						tmpEdit->SetCellState(CS_GUESS);
						tmpEdit->SetGuess(iVal);
					}
				}
			}
			else
				tmpEdit->SetCellState(CS_IMPOSSIBLE);

			//if (pPuzzle->SetAnswer(square, iVal, std::string("Entered by user")))
			//	tmpEdit->SetCellState(CS_GUESS);
			//else
			//	tmpEdit->SetCellState(CS_IMPOSSIBLE);
			tmpEdit->RefreshCell(false);
		}
	}
}


HBRUSH CSTUBLDlg::OnCtlColor(CDC* pDC, CWnd* pWnd, UINT nCtlColor)
{
	
	// Call the base class implementation first! Otherwise, it may
	// undo what we're trying to accomplish here.
	HBRUSH hbr = CDialog::OnCtlColor(pDC, pWnd, nCtlColor);

	if (nCtlColor == CTLCOLOR_DLG)
	{
		// Set the text color to red
		pDC->SetTextColor(RGB(255, 0, 0));

		// Set the background mode for text to transparent 
		// so background will show thru.
		pDC->SetBkMode(TRANSPARENT);

		// Return handle to our CBrush object
		hbr = *cdDlgBgColor;
	}

	return hbr;
}

void CSTUBLDlg::SetHints(bool hintsOn)
{
	bShowHints = hintsOn;
	if (bShowHints)
		m_buttonHints.SetWindowTextA("HIDE POSSIBILITIES");
	else
		m_buttonHints.SetWindowTextA("SHOW POSSIBILITIES");
}


void CSTUBLDlg::OnBnClickedButtonShowhints()
{
	SetHints(bShowHints == false);

	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->RefreshCell(bShowHints);
}

void CSTUBLDlg::OnDropFiles(HDROP hDropInfo)
{
	char fName[1024];

	DragQueryFile(hDropInfo, 0, fName, 1024);

	Restore(fName);
}

void CSTUBLDlg::OnBnClickedButtonHistory()
{
	m_lbReasons.ResetContent();

	std::vector<std::string> history;
	std::vector<std::string>::iterator historyIter;

	pPuzzle->GetHistory(history);

	for (historyIter = history.begin(); historyIter != history.end(); ++historyIter)
		m_lbReasons.AddString(historyIter->c_str());
}

void CSTUBLDlg::OnBnClickedButtonStep()
{
	std::vector<int> vChangedCells;
	std::vector<int>::iterator vChangedIter;

	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->SetChanged(false);

	pPuzzle->TakeStep(vChangedCells);

	for (vChangedIter = vChangedCells.begin(); vChangedIter != vChangedCells.end(); vChangedIter++)
	{
		Boxes[(*vChangedIter)/9][(*vChangedIter)%9]->SetChanged(true);
	}
	//if (!pPuzzle->TakeStep())
	//{
	//	MessageBox("Puzzle could not be solved!  Try the Desperate or Really Desperate buttons.");
	//}
	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->RefreshCell(bShowHints, true);
	OnBnClickedButtonHistory();
}



void CSTUBLDlg::OnFileOpen()
{
    CString cs;

	OnPuzzleClear();

    if (GetFileName(false, cs))
    {
		Restore(cs.GetBuffer());
    }
}

void CSTUBLDlg::OnFileSaveAs()
{
    char buf[8];
    CString cs;

    char cBuf[96];

    CFile file;

    int counter=0;
    if (GetFileName(true, cs))
    {
        if (file.Open(cs.GetBuffer(), CFile::modeCreate | CFile::modeWrite))
        {
            for (int row=0; row<9; ++row)
            {
                for (int col=0; col<9; ++col)
                {
                    (Boxes[row][col])->GetWindowText(buf, 8);
                    if (buf[0] == '\0')
                        cBuf[counter] = '0';
                    else
                        cBuf[counter] = buf[0];
                counter++;
                }
            }
            file.Write(cBuf, 81);
            file.Close();
        }
    }
}

void CSTUBLDlg::OnFileTypeInPuzzle()
{
	if (m_playState == SPS_ENTERING_PUZZLE)
	{
		m_playState = SPS_PLAYING;

		// Now change all the guesses to answers
		for (int i=0; i<81; ++i)
		{
			CSudokuEdit* tmpEdit = Boxes[i/9][i%9];
			int answer = tmpEdit->GetGuess();
			if (answer != 0)
			{
				pPuzzle->SetAnswer(i, answer, "Puzzle Input By User");
				tmpEdit->SetCellState(CS_ANSWER);
			}
			else
				tmpEdit->SetCellState(CS_NORMAL);
		}

		//if (pPuzzle->SolvePuzzle())
		//	MessageBox("Puzzle Solved");
		//else
		//	MessageBox("Unable to solve puzzle!");

		GetDlgItem(IDC_BUTTON_HISTORY)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_SHOWHINTS)->EnableWindow(TRUE);
		GetDlgItem(IDC_LIST_REASONS)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_STEP)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_STEP_UNTIL_ANSWERFOUND)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_SOLVE)->EnableWindow(TRUE);
		GetDlgItem(IDC_BUTTON_SHOWANSWERS)->EnableWindow(TRUE);

		PerformInitialCheck();
	}
	else
	{
		MessageBox("Enter digits into cells.  Select this menu item again to indicate "
			"you have completed your input.");
		OnPuzzleClear();
		m_playState = SPS_ENTERING_PUZZLE;

		GetDlgItem(IDC_BUTTON_HISTORY)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON_SHOWHINTS)->EnableWindow(FALSE);
		GetDlgItem(IDC_LIST_REASONS)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON_STEP)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON_STEP_UNTIL_ANSWERFOUND)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON_SOLVE)->EnableWindow(FALSE);
		GetDlgItem(IDC_BUTTON_SHOWANSWERS)->EnableWindow(FALSE);
	}
}

void CSTUBLDlg::OnFileClose()
{
	OnOK();}

void CSTUBLDlg::OnPuzzleClear()
{
    if (pPuzzle)
        delete pPuzzle;

	for (int i=0; i<81; ++i)
		m_puzzleDef[i] = 0;

    pPuzzle = new Sudoku();
	SetHints(false);

	for (int cell=0; cell<81; ++cell)
	{
		Boxes[cell/9][cell%9]->SetWindowTextA("");
		Boxes[cell/9][cell%9]->SetPuzzlePtr(pPuzzle);
		Boxes[cell/9][cell%9]->SetCellState(CS_NORMAL);
		Boxes[cell/9][cell%9]->RefreshCell(false);
	}
}

void CSTUBLDlg::OnPuzzleReset()
{
    if (pPuzzle)
        delete pPuzzle;

    pPuzzle = new Sudoku();
	SetHints(false);
	std::stringstream ss;
	for (int cell=0; cell<81; ++cell)
	{
		ss.str("");
		ss << m_puzzleDef[cell];
		Boxes[cell/9][cell%9]->SetWindowTextA(ss.str().c_str());
		pPuzzle->SetAnswer(cell, m_puzzleDef[cell], std::string("User Reset"));
		Boxes[cell/9][cell%9]->SetPuzzlePtr(pPuzzle);
		if (m_puzzleDef[cell] == 0)
			Boxes[cell/9][cell%9]->SetCellState(CS_NORMAL);
		else
			Boxes[cell/9][cell%9]->SetCellState(CS_NORMAL);
		Boxes[cell/9][cell%9]->RefreshCell(false, true);
	}
}

void CSTUBLDlg::OnHelpAboutStubl()
{
		CAboutDlg dlgAbout;
		dlgAbout.DoModal();
}

void CSTUBLDlg::OnBnClickedButtonStepUntilAnswerfound()
{
	std::vector<int> vChangedCells;
	std::vector<int>::iterator vChangedIter;

	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->SetChanged(false);

	pPuzzle->TakeStep(vChangedCells, true);

	for (vChangedIter = vChangedCells.begin(); vChangedIter != vChangedCells.end(); vChangedIter++)
	{
		if (pPuzzle->GetAnswer(*vChangedIter) != 0)
			Boxes[(*vChangedIter)/9][(*vChangedIter)%9]->SetChanged(true);
	}
	//if (!pPuzzle->TakeStep())
	//{
	//	MessageBox("Puzzle could not be solved!  Try the Desperate or Really Desperate buttons.");
	//}
	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->RefreshCell(bShowHints, false);
	//OnBnClickedButtonHistory();
}

void CSTUBLDlg::PerformInitialCheck()
{
	std::vector<int> vChangedCells;
	std::vector<int>::iterator vChangedIter;

	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->SetChanged(false);

	pPuzzle->RunAlgsForNewPuzzle(vChangedCells);

	for (vChangedIter = vChangedCells.begin(); vChangedIter != vChangedCells.end(); vChangedIter++)
	{
		if (pPuzzle->GetAnswer(*vChangedIter) != 0)
			Boxes[(*vChangedIter)/9][(*vChangedIter)%9]->SetChanged(true);
	}

	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->RefreshCell(bShowHints, false);

}

void CSTUBLDlg::OnBnClickedButtonShowanswers()
{
	SetHints(false);
	for (int cell=0; cell<81; ++cell)
		Boxes[cell/9][cell%9]->RefreshCell(false, true);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
I live in Minnesota with my wife and son, having moved here from Montana. I enjoy creating software which benefits people, and I am fortunate to have a job where I am able to do that.
I enjoy reading, hunting and fishing, any sport with a racquet or paddle, and rooting for the New England Patriots.
In addition to my full-time job, I founded Rohawk, LLC which creates software for Christian churches.

Comments and Discussions