Click here to Skip to main content
Click here to Skip to main content
 
Add your own
alternative version
Go to top

A Sudoku Teacher Using Boost Libraries

, 7 Jul 2006
A Sudoku teacher using multi_index_container, lambda, and other Boost libraries.
// SudokuEdit.cpp : implementation file
// Adapted from CodeProject work by PJ Arends

#include "stdafx.h"
#include "SudokuEdit.h"
#include "SudokuPuzzle.h"
#include <vector>
#include <sstream>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

#define MES_UNDO        _T("&Show &History")
#define MES_COPY         _T("Show &Answer")
#define MES_CUT         _T("&Cut")
#define MES_PASTE       _T("&Paste")
#define MES_DELETE      _T("&Delete")
#define MES_SELECTALL   _T("Select &All")
#define ME_SELECTALL    WM_USER + 0x7000

BEGIN_MESSAGE_MAP(CSudokuEdit, CEdit)
    ON_WM_CONTEXTMENU()
	ON_WM_CTLCOLOR_REFLECT()
END_MESSAGE_MAP()

CSudokuEdit::CSudokuEdit() :
	m_pPuzzle(NULL)
	, cbAnswer(NULL)
	, cbHint(NULL)
	, cbBlank(NULL)
	, cbImposs(NULL)
	, cfNormal(NULL)
	, cfAnswer(NULL)
	, cfPossibilities(NULL)
	, cfImposs(NULL)
	, crNormalText(RGB(0,0,0))
	, crAnswerText(RGB(0,0,0))
	, crHintText(RGB(0,0,0))
	, crImpossText(RGB(0,0,0))
	, m_pLB(NULL)
	, bChanged(false)
	, m_guess(0)
	, m_iCellNum(0)
	, state(CS_UNINITIALIZED)
	, prevState(CS_UNINITIALIZED)

{
	state = CS_UNINITIALIZED;
}

void CSudokuEdit::OnContextMenu(CWnd* pWnd, CPoint point)
{
    SetFocus();
    CMenu menu;
    menu.CreatePopupMenu();
    BOOL bReadOnly = GetStyle() & ES_READONLY;
    DWORD flags = CanUndo() && !bReadOnly ? 0 : MF_GRAYED;
    menu.InsertMenu(0, MF_BYPOSITION, EM_UNDO,
        MES_UNDO);

    menu.InsertMenu(1, MF_BYPOSITION | MF_SEPARATOR);

	int answer = m_pPuzzle->GetAnswer(m_iCellNum);
	if (answer == 0)
		flags = MF_GRAYED;
	else
		flags = 0;
    menu.InsertMenu(2, MF_BYPOSITION | flags, WM_COPY,
        MES_COPY);

    //flags = (flags == MF_GRAYED || bReadOnly) ? MF_GRAYED : 0;
    //menu.InsertMenu(2, MF_BYPOSITION | flags, WM_CUT,
    //    MES_CUT);
    //menu.InsertMenu(4, MF_BYPOSITION | flags, WM_CLEAR,
    //    MES_DELETE);

    //flags = IsClipboardFormatAvailable(CF_TEXT) &&
    //    !bReadOnly ? 0 : MF_GRAYED;
    //menu.InsertMenu(4, MF_BYPOSITION | flags, WM_PASTE,
    //    MES_PASTE);

    //menu.InsertMenu(6, MF_BYPOSITION | MF_SEPARATOR);

    //int len = GetWindowTextLength();
    //flags = (!len || (LOWORD(sel) == 0 && HIWORD(sel) ==
    //    len)) ? MF_GRAYED : 0;
    //menu.InsertMenu(7, MF_BYPOSITION | flags, ME_SELECTALL,
    //    MES_SELECTALL);

    menu.TrackPopupMenu(TPM_LEFTALIGN | TPM_LEFTBUTTON |
        TPM_RIGHTBUTTON, point.x, point.y, this);
}


BOOL CSudokuEdit::OnCommand(WPARAM wParam, LPARAM lParam)
{
    switch (LOWORD(wParam))
    {
    case EM_UNDO:	// hijacked - show history
		ShowReasons();
		break;
    case WM_COPY:	// hijacked - show answer
		ShowAnswer();
		break;
    case WM_CUT:
    case WM_CLEAR:
    case WM_PASTE:
        return (BOOL)SendMessage(LOWORD(wParam));
    case ME_SELECTALL:
        return (BOOL)SendMessage (EM_SETSEL, 0, -1);
    default:
        return CEdit::OnCommand(wParam, lParam);
    }
	return TRUE;
}

HBRUSH CSudokuEdit::CtlColor(CDC* pDC, UINT nCtlColor) 
{
	HBRUSH hbr;

	if (state == CS_UNINITIALIZED)
	{
		return NULL;
	}

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

	switch (state)
	{
		case CS_NORMAL:
		case CS_GUESS:
			hbr = *cbBlank;
			pDC->SetTextColor(crNormalText);
			pDC->SetBkColor(crNormalText);
			break;

		case CS_HINT:
			hbr = *cbHint;
			pDC->SetTextColor(crHintText);
			pDC->SetBkColor(crHintText);
			break;

		case CS_ANSWER:
			hbr = *cbAnswer;
			pDC->SetTextColor(crAnswerText);
			pDC->SetBkColor(crAnswerText);
			break;

		case CS_IMPOSSIBLE:
			hbr = *cbImposs;
			pDC->SetTextColor(crImpossText);
			pDC->SetBkColor(crImpossText);
			break;
	}

	// Changed text will always be read
	if (bChanged)
	{
		pDC->SetTextColor(RGB(255,0,0));
		pDC->SetBkColor(RGB(255,0,0));
		hbr = *cbChanged;
	}

	return hbr;
}

void CSudokuEdit::SetCellBrushes(CBrush* pbNorm, CBrush* pbAnswer, CBrush* pbPoss, CBrush* pbImposs)
{
	cbBlank = pbNorm;
	cbAnswer = pbAnswer;
	cbHint = pbPoss;
	cbImposs = pbImposs;
	cbChanged = new CBrush(RGB(225, 239, 143));
}


void CSudokuEdit::SetCellFonts(CFont* norm, CFont* answer, CFont* poss, CFont* imposs)
{
	cfNormal = norm;
	cfAnswer = answer;
	cfPossibilities = poss;
	cfImposs = imposs;
};

void CSudokuEdit::SetCellTextColors(COLORREF norm, COLORREF answer, COLORREF poss, COLORREF imposs)
{
	crNormalText = norm;
	crAnswerText = answer;
	crHintText = poss;
	crImpossText = imposs;
}

void CSudokuEdit::RefreshCell(bool hintsOn, bool showAnswers)
{
	std::string sPoss;
	char currText[16];
	std::stringstream ss;

	int answer = m_pPuzzle->GetPossibilitiesString(m_iCellNum, sPoss);

	if (showAnswers && (answer != 0))
	{
		state = CS_ANSWER;
		ss << answer;
		SetReadOnly(TRUE);
		SetFont(cfAnswer);
		SetWindowText(ss.str().c_str());
		return;
	}

	if (hintsOn && (state != CS_HINT) && (state != CS_ANSWER))
	{
		prevState = state;
		state = CS_HINT;
	}
	else if (!hintsOn && (state == CS_HINT))
	{
		state = prevState;
	}

	GetWindowText(currText, 16);
	int guess = atoi(currText);


	SetReadOnly(FALSE);

	switch (state)
	{
		case CS_ANSWER:
			ss << answer;
			SetReadOnly(TRUE);
			SetFont(cfAnswer);
			SetWindowText(ss.str().c_str());
			break;
		case CS_GUESS:
			ss << m_guess;
			SetReadOnly(FALSE);
			SetFont(cfNormal);
			SetWindowText(ss.str().c_str());
			break;
		case CS_HINT:
			SetReadOnly(TRUE);
			SetFont(cfPossibilities);
			SetWindowText(sPoss.c_str());
			break;
		case CS_NORMAL:
			SetFont(cfNormal);
			SetWindowText(ss.str().c_str());
			break;
		case CS_IMPOSSIBLE:
			SetFont(cfImposs);
			break;
		default:
			break;
	}
return;
	if (state == CS_ANSWER)
	{
		std::stringstream ss;
		ss << answer;

	}
	else if ((guess == 0) && (answer != 0))
	{
		std::stringstream ss;
		ss << answer;

		state = CS_ANSWER;
		//SetReadOnly(TRUE);
		SetFont(cfNormal);
		SetWindowText(ss.str().c_str());
	}
	else
	{
		if (hintsOn)
		{
			m_guess = guess;
			state = CS_HINT;
			SetReadOnly(TRUE);
			SetFont(cfPossibilities);
			SetWindowText(sPoss.c_str());
		}
		else
		{

			SetReadOnly(FALSE);
			if (state == CS_IMPOSSIBLE)
			{
				SetFont(cfImposs);
			}
			else
			{
				state = CS_NORMAL;
				SetFont(cfNormal);
				if (m_guess == 0)
					SetWindowText("");
				else
				{
					std::stringstream ss;
					ss << m_guess;
					SetWindowText(ss.str().c_str());
				}
			}
		}
	}
}

void CSudokuEdit::ShowReasons()
{
	if (m_pLB)
	{
		m_pLB->ResetContent();
		std::vector<std::string> sReasons;
		std::vector<std::string>::iterator reasonsIter;

		m_pPuzzle->GetReasons(m_iCellNum, sReasons);
		for (reasonsIter = sReasons.begin(); reasonsIter != sReasons.end(); ++reasonsIter)
		{
			m_pLB->AddString(reasonsIter->c_str());
		}
	}
}

void CSudokuEdit::ShowAnswer()
{
	int answer = m_pPuzzle->GetAnswer(m_iCellNum);
	if (answer != 0)
	{
		std::stringstream ss;
		ss << answer;

		state = CS_ANSWER;
		//SetReadOnly(TRUE);
		SetFont(cfAnswer);
		SetWindowText(ss.str().c_str());
	}
}

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

Share

About the Author

Scott A. Ross
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.

| Advertise | Privacy | Mobile
Web03 | 2.8.140921.1 | Last Updated 7 Jul 2006
Article Copyright 2006 by Scott A. Ross
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid