⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sudokuwndbase.h

📁 要谈论的不是数独游戏的算法
💻 H
字号:
#ifndef SUDOKU_SUDOKUCTRL_H
#define SUDOKU_SUDOKUCTRL_H

#include <sudoku/logic/SudokuEngine.h>
#include <sudoku/logic/PuzzleModel.h>
#include <sudoku/ui/SudokuWndRenderer.h>

#include <memory>
#include <assert.h>

namespace Sudoku
{

/**
* The <b>SudokuWndBase</b> represents a base class of your sudoku control.
* This clas proivder the methods for filling puzzle and drawing control.
* Your class derived from this class must has a <b>GetClientRect</b> function.
*
* @param T Your class, drived from <b>SudokuWndBase</b>.
*/
template <typename T> class SudokuWndBase
{
	typedef std::auto_ptr<SudokuWndRenderer> PuzzleRendererPtr;

public:
	/**
	* Constructor. Initializes a new instance of <b>SudokuWndBase</b> class.
	*/
	SudokuWndBase();

	PuzzleModel* getPuzzle();

	PuzzleMask getReadonlyMask() const;
	PuzzleMask getInvalidMask() const;

	SudokuWndRenderer* getRenderer();
	void setRenderer(SudokuWndRenderer *renderer);

	ISudokuEngine* getEngine();
	void setEngine(ISudokuEngine *engine);

	int getBlanks();

	HRESULT fill(int level);
	HRESULT solve();
	HRESULT validate();
	void clear();


	void draw(HDC hdc);

	std::pair<int, int> hitTest(int x, int y);

public:
	~SudokuWndBase(void);

private:
	ISudokuEnginePtr	m_engine;
	PuzzleRendererPtr	m_renderer;
	PuzzleModel			*m_puzzle;
	bool				m_readonlyMask[PuzzleModel::N][PuzzleModel::N];
	bool				m_invalidMask[PuzzleModel::N][PuzzleModel::N];
};

template <typename T> inline SudokuWndBase<T>::SudokuWndBase() : m_puzzle(0)
{
	memset(m_readonlyMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);
	memset(m_invalidMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);
}

template <typename T> inline SudokuWndBase<T>::~SudokuWndBase()
{
	CoTaskMemFree(m_puzzle);
}

template <typename T> inline PuzzleModel* SudokuWndBase<T>::getPuzzle()
{
	return m_puzzle;
}

template <typename T> inline PuzzleMask SudokuWndBase<T>::getReadonlyMask() const
{
	return m_readonlyMask;
}

template <typename T> inline PuzzleMask SudokuWndBase<T>::getInvalidMask() const
{
	return m_invalidMask;
}

template <typename T> inline SudokuWndRenderer* SudokuWndBase<T>::getRenderer()
{
	return m_renderer.get();
}

template <typename T> inline void SudokuWndBase<T>::setRenderer(SudokuWndRenderer *renderer)
{
	m_renderer.reset(renderer);
}

template <typename T> inline ISudokuEngine* SudokuWndBase<T>::getEngine()
{
	return m_engine;
}

template <typename T> inline void SudokuWndBase<T>::setEngine(ISudokuEngine *engine)
{
	m_engine = engine;
}

template <typename T> inline int SudokuWndBase<T>::getBlanks()
{
	int cnt = 0;
	for (int i = 0; i < PuzzleModel::N; ++i)
	{
		for (int j = 0; j < PuzzleModel::N; ++j)
		{
			if (!m_readonlyMask[i][j] && m_puzzle->getValue(i, j) == 0)
			{
				++cnt;
			}
		}
	}
	return cnt;
}

template <typename T> inline std::pair<int, int> SudokuWndBase<T>::hitTest(int x, int y)
{
	std::pair<int, int> grid;
	grid.first = y / Sudoku::SudokuWndRenderer::GRID_SIZE;
	grid.second = x / Sudoku::SudokuWndRenderer::GRID_SIZE;

	if (grid.first >= 9)
		grid.first = -1;
	if (grid.second >= 9)
		grid.second = -1;

	return grid;
}

template <typename T> inline HRESULT SudokuWndBase<T>::fill(int level)
{
	PuzzleModel *puzzle;
	HRESULT hr = m_engine->createPuzzle(level, &puzzle);
	if (FAILED(hr))
	{
		return hr;
	}

	if (m_puzzle)
		CoTaskMemFree(m_puzzle);

	m_puzzle = puzzle;

	//
	// initializes the mask of puzzle
	//
	memset(m_readonlyMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);
	for (int i = 0; i < PuzzleModel::N; ++i)
	{
		for (int j = 0; j < PuzzleModel::N; ++j)
		{
			if (m_puzzle->getValue(i, j))
				m_readonlyMask[i][j] = true;
		}
	}

	memset(m_invalidMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);

	//
	// updates the views.
	//
	T *ctrl = static_cast<T*>(this);
	ctrl->update();

	return S_OK;
}

template <typename T> inline HRESULT SudokuWndBase<T>::solve()
{
	if (!m_puzzle)
		return E_FAIL;

	clear();


	HRESULT hr = m_engine->solvePuzzle(*m_puzzle);

	T *ctrl = static_cast<T*>(this);
	ctrl->update();

	return hr;
}

template <typename T> inline HRESULT SudokuWndBase<T>::validate()
{
	if (!m_puzzle)
		return E_FAIL;


	//
	// initializes the output parameter.
	//
	memset(m_invalidMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);

	PuzzleModel result = *m_puzzle;
	result.reset(m_readonlyMask);

	HRESULT hr = m_engine->solvePuzzle(result);
	if (FAILED(hr))
	{
		return hr;
	}

	for (int i = 0; i < PuzzleModel::N; ++i)
	{
		for (int j = 0; j < PuzzleModel::N; ++j)
		{
			if (result.getValue(i, j) != m_puzzle->getValue(i, j))
				m_invalidMask[i][j] = true;
		}
	}

	T *ctrl = static_cast<T*>(this);
	ctrl->update();

	return hr;
}

template <typename T> inline void SudokuWndBase<T>::clear()
{
	if (!m_puzzle)
		return;

	for (int i = 0; i < PuzzleModel::N; ++i)
	{
		for (int j = 0; j < PuzzleModel::N; ++j)
		{
			if (!m_readonlyMask[i][j])
				m_puzzle->setValue(i, j, 0);
		}
	}
	m_puzzle->reset(m_readonlyMask);

	memset(m_invalidMask, 0, sizeof(bool) * PuzzleModel::N * PuzzleModel::N);

	T *ctrl = static_cast<T*>(this);
	ctrl->update();
}

template <typename T> inline void SudokuWndBase<T>::draw(HDC hdc)
{
	if (m_renderer.get())
	{
		m_renderer->draw(hdc);
	}
}

} // end of namespace Sudoku;

#endif // SUDOKU_SUDOKUCTRL_H

⌨️ 快捷键说明

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