#pragma once
class CRandomNumber
{
public:
CRandomNumber(long lSeed = 0);
~CRandomNumber(void) {};
long GetRandom(long lLower = 0, long lUpper = 0x7FFFFFFE);
private:
long m_lSeed;
float rand(long *idum);
//Following are static members of the func in the original
//here made to class members to preserve values between calls
//but allows multiple instances of the class to be independant of one another
//(should that be required)
long iy;
long iv[32]; //array size MUST be the same as value of NTAB
};
#include "StdAfx.h"
#include "RandomNumber.h"
#define IA (16807)
#define IM (2147483647)
#define AM ((float)1.0/(float)IM)
#define IQ (127773)
#define IR (2836)
#define NTAB (32)
#define NDIV (1+(IM-1)/NTAB)
#define EPS ((float)1.2e-7)
#define RNMX ((float)(1.0-EPS))
CRandomNumber::CRandomNumber(long lSeed)
: m_lSeed(lSeed > 0 ? -lSeed : lSeed)
, iy(0)
{
//Check that the 'iv' array is the same size as NTAB - it should be so
ASSERT(sizeof(iv) == NTAB * sizeof(long));
if(m_lSeed == 0)
{
//generate a seed, use the day of year and time of day as a base value
COleDateTime dte = COleDateTime::GetCurrentTime();
m_lSeed = -(dte.GetDayOfYear() * 24 * 60 * 60 + dte.GetHour() * 60 * 60 + dte.GetMinute() * 60 + dte.GetSecond());
}
rand(&m_lSeed);
}
//Assume no overflows of the entered values, and that lLower is in fact less than lUpper
long CRandomNumber::GetRandom(long lLower, long lUpper)
{
if(lLower == lUpper)
return lLower;
float fRes = rand(&m_lSeed);
//lUpper would never be returned if this value was not incremented
lUpper++;
return (long)((float)(lUpper - lLower) * fRes) + lLower;
}
float CRandomNumber::rand(long *idum)
{
int j;
long k;
float temp;
if(idum <= 0 || !iy) //initialise
{
if(-(*idum) < 1) //idum should not be zero, if it is then set to 1 as an initial value
*idum = 1;
else
*idum = -(*idum); //make positive
for(j = NTAB+7; j >= 0; j--)
{
k = (*idum)/IQ;
*idum = IA * (*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
if(j < NTAB)
iv[j] = *idum;
}
iy = iv[0];
}
//Starts here when not initialising
k = (*idum) / IQ;
//computes idum=(IA*idum) % IM without overflows by Schrage's method
*idum = IA * (*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
j = iy / NDIV; //range 0..NTAB-1
//Get previous value then replace the array with the new value
iy = iv[j];
iv[j] = *idum;
temp = AM * iy;
//In case temp is over the max value set it to the max value
if(temp > RNMX)
temp = RNMX;
//the result is returned
return temp;
}
/*
The following is the source code from the literature:
Numerical recipies in C, second edition
W.H.Press, S.A.Teukolsky, W.T.Vetterling, B.P.Flannery
chapter 7, ran1 method for random number generation
#define IA 16807
#define IM 2147483647
#define AM ((float)1.0/IM)
#define IQ 127773
#define IR 2836
#define NTAB 32
#define NDIV (1+(IM-1)/NTAB)
#define EPS (float)1.2e-7
#define RNMX (float)(1.0-EPS)
float RAND(long *idum)
{
int j;
long k;
static long iy=0;
static long iv[NTAB];
float temp;
if(idum <= 0 || !iy) //initialise
{
if(-(*idum) < 1) //idum should not be zero, if it is then set to 1 as an initial value
*idum = 1;
else
*idum = -(*idum); //make positive
for(j = NTAB+7; j >= 0; j--)
{
k = (*idum)/IQ;
*idum = IA * (*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
if(j < NTAB)
iv[j] = *idum;
}
iy = iv[0];
}
//Starts here when not initialising
k = (*idum) / IQ;
//computes idum=(IA*idum) % IM without overflows by Schrage's method
*idum = IA * (*idum - k*IQ) - IR*k;
if(*idum < 0)
*idum += IM;
j = iy / NDIV; //range 0..NTAB-1
//Get previous value then replace the array with the new value
iy = iv[j];
iv[j] = *idum;
temp = AM * iy;
//In case temp is over the max value set it to the max value
if(temp > RNMX)
temp = RNMX;
//the result is returned
return temp;
}
*/
#include "afxdao.h"
#pragma warning(disable : 4995)
private:
CDaoDatabase* m_pDB;
CSudokuDoc::CSudokuDoc()
{
//Create the pointer to the database
m_pDB = new CDaoDatabase();
//Get the path to the database and open it
//Note, a common fault is to rely on finding the current directory and ASSUMING that is where the
//application.exe is located. Unfortunately as part of a startup of an exe one can specify the directory
//to start in so that assumption may work for you in testing, but a user can easily make it fail.
//You get the fallout (--> the app doesn't work is the feedback to your boss? )
char szPath[MAX_PATH + 1]; //plus space for 0 string terminator
GetModuleFileName(NULL, szPath, MAX_PATH); //NULL = use this module (the app)
//Now remove the name of the exe from the returned string - find the final '\' char in the string
char* pch = strrchr(szPath, '\\');
*pch = 0; //insert a 0 to act as a string terminator
strcat_s(szPath, MAX_PATH, "\\Sudoku.mdb"); //append the name of the mdb
//open the database
m_pDB->Open(szPath);
}
#pragma warning(disable : 4995)
CSudokuDoc::~CSudokuDoc()
{
if(m_pDB != NULL)
{
m_pDB->Close();
delete m_pDB;
m_pDB = NULL;
}
}
CRandomNumber rn;
CDaoRecordset RS(m_pDB);
RS.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT ID, GameDetail FROM Games");
RS.MoveLast();
long lCount = RS.GetRecordCount();
RS.MoveFirst();
//move to random record (eg. 5 records then VALID moves are 0, 1, 2, 3, 4 -- so we need lCount-1)
RS.Move(rn.GetRandom(0, lCount - 1));
COleVariant var = RS.GetFieldValue("GameDetail");
//It is a string in the table, now convert it to a string we can use
CString szGame(var.pbVal);
//Now for the info to display in the status bar
var = RS.GetFieldValue("ID");
m_szInfo.Format("ID: %ld", var.lVal);
RS.Close();
strcpy_s(m_arGame, sizeof(m_arGame), szGame);
UpdateAllViews(NULL, eLoadGame, NULL);
#include "SudokuDoc.h"
#include "RandomNumber.h"
void CSudokuDoc::OnUpdateEditLock(CCmdUI *pCmdUI)
{
char* pCell = m_arGame;
while(*pCell != 0)
{
if(*pCell != '0')
{
pCmdUI->Enable(false);
return;
}
pCell++;
}
pCmdUI->Enable(true);
}
void CSudokuDoc::OnEditLock()
{
//tell the view to store the 'game' into the document
UpdateAllViews(NULL, eSaveGame, NULL);
//Now update the database
CDaoRecordset RS(m_pDB);
RS.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Games WHERE (ID=0)");
RS.AddNew();
RS.SetFieldValue("GameDetail", m_arGame);
RS.Update();
RS.Close();
}
void CSudokuDoc::OnEditLock()
{
CString s;
s.LoadString(IDS_QRY_SAVE_TO_DB);
if(AfxMessageBox(s, MB_YESNO | MB_ICONQUESTION) != IDYES)
return;
try
{
RS.Update();
}
catch(CDaoException* pe)
{
if(pe->m_pErrorInfo->m_lErrorCode != 3022)
{
AfxMessageBox(pe->m_pErrorInfo->m_strDescription, MB_ICONEXCLAMATION);
}
pe->Delete();
}
COleVariant var = RS.GetFieldValue("ID");
COleVariant varBkmark = RS.GetLastModifiedBookmark();
RS.SetBookmark(varBkmark);
COleVariant var = RS.GetFieldValue("ID");
m_szInfo.Format("ID: %ld", var.lVal);
POSITION pos = GetFirstViewPosition();
static_cast<CMainFrame*>(GetNextView(pos)->GetParentFrame())->DisplayStatusInfo(GetInfo());
void CSudokuDoc::OnEditLock()
{
CString s;
s.LoadString(IDS_QRY_SAVE_TO_DB);
if(AfxMessageBox(s, MB_YESNO | MB_ICONQUESTION) != IDYES)
return;
//tell the view to store the 'game' into the document
UpdateAllViews(NULL, eSaveGame, NULL);
//Now update the database
CDaoRecordset RS(m_pDB);
RS.Open(AFX_DAO_USE_DEFAULT_TYPE, "SELECT * FROM Games WHERE (ID=0)");
RS.AddNew();
RS.SetFieldValue("GameDetail", m_arGame);
try
{
RS.Update();
COleVariant varBkmark = RS.GetLastModifiedBookmark();
RS.SetBookmark(varBkmark);
COleVariant var = RS.GetFieldValue("ID");
m_szInfo.Format("ID: %ld", var.lVal);
POSITION pos = GetFirstViewPosition();
static_cast<CMainFrame*>(GetNextView(pos)->GetParentFrame())->DisplayStatusInfo(GetInfo());
}
catch(CDaoException* pe)
{
if(pe->m_pErrorInfo->m_lErrorCode != 3022)
{
AfxMessageBox(pe->m_pErrorInfo->m_strDescription, MB_ICONEXCLAMATION);
}
pe->Delete();
}
RS.Close();
}
void CSudokuDoc::OnUpdateEditDeletegame(CCmdUI *pCmdUI)
{
// Only required if we have loaded a game from the Database
pCmdUI->Enable(m_szInfo.Left(2).CompareNoCase("ID") == 0);
}
void CSudokuDoc::OnEditDeletegame()
{
CString s(m_szInfo.Mid(4));
CString szSQL;
szSQL.Format("DELETE * FROM Games WHERE (ID=%s)", s);
m_pDB->Execute(szSQL);
AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(ID_FILE_PLAYRANDOM, 0), NULL);
}
Have a question about something in this article? You can receive help directly from the article author. Sign up for a free trial to get started.
Comments (0)