Home > Articles > Programming > C/C++

  • Print
  • + Share This
This chapter is from the book

Implementing the Replacement Functions

The last step is to implement the actual games logic within the main request handler class. One nice feature added to the editing of SRFs is the ability to right-click a replacement tag and have the replacement function automatically added for you within the request handler class. Therefore, right-click the UserGuessedCorrectly tag and select Add Tag Handler from the context menu. Continue this same process and add tag handlers for GetNumGuesses and GetLastError.

Before you implement the replacement functions, you'll need a few member variables to keep track of state within your application. Using the Class Viewer, right-click the CNumberGuessHandler class within the NumberGuess project and select Add, Add Variable from the context menu. Set the member access level to private, set the variable type to int, and give it the variable name m_iMagicNumber. This is the number the user will try to guess. Repeat the process and add another private integer with the name m_iNumGuesses. Finally, add one more variable with the same access level, set the type to TCHAR?, and give it the name m_szLastError.

The first replacement function you are going to implement is the function responsible for determining whether the user has guessed the number correctly: the UserGuessedCorrectly function.

First, you need to get the value the user entered from the input box. This value will be passed in as a form variable. Anytime you need to get details about the request from the client, you can use the member variable m_HttpRequest, which is a CHttpRequest object. This variable is created in a base class from which you are deriving. To get the value of form variables, you simply create a local variable of type CHttpRequestParams and assign it the result of a call to the CHttpRequest member function GetFormVars. This will give you a collection of all the form controls and their associated values. To get at the input box control's value, you can use the GetField member function provided by your local CHttpRequestParams variable, passing it the name of the form variable you are requesting. Take caution: The function can return a NULL value if the form value doesn't exist. This happens the first time the page is loaded because the form hasn't been submitted yet. You can, however, use this to your advantage.

You need a good place to generate the random number that the user is trying to guess. The function ValidateAndExchange may be a tempting place to put this code, but the comment that says to add initialization code is a little misleading. The ValidateAndExchange function is called each time your SRF is loaded. This means that it is loaded each time the user clicks the Submit button. If you place your random number–generation code there, a random number is generated each and every time the user tries to guess. In other words, the user's chances of guessing the number correctly would be virtually zero. Therefore, the UserGuessedCorrectly function should check the return value of the GetField function call. If the value is not NULL, it should check to see whether it is between the required range of 1 to 100 and, if not, set the last error member variable to a proper value and return HTTP_S_FALSE. If the number is within the range, you should check to see whether it is lower, higher, or exactly the same as your randomly generated magic number. If it is the same, HTTP_SUCCESS should be returned so that the conditional in the SRF evaluates to True and the congratulations statement is rendered. Your code should look similar to Listing 14.3.

Listing 14.3 Implementation of UserGuessedCorrectly Tag Replacement Function

 1: [ tag_name(name = "UserGuessedCorrectly") ]
 2: HTTP_CODE OnUserGuessedCorrectly(void)
 3: {
 4:  // Get form fields collection from the request
 5:  const CHttpRequestParams& theFields = m_HttpRequest.GetFormVars();
 6:
 7:  if( theFields.Lookup( "UserGuess") != NULL )
 8:  {
 9:    int iGuess = _ttoi( theFields.Lookup( "UserGuess" ));
10:
11:    if( iGuess < 1 || iGuess > 100 )
12:    {
13:      _tcscpy( m_szLastError, "You must enter a number 
14:       between 1 and 100." );
15:      return HTTP_S_FALSE;
16:    }
17:
18:    // increment number of steps
19:    m_iNumGuesses++;
20:
21:    if( iGuess < m_iMagicNumber )
22:    {
23:      _tcscpy( m_szLastError, "Your guess is too low." );
24:      return HTTP_S_FALSE;
25:    }
26:
27:    if( iGuess > m_iMagicNumber )
28:    {
29:      _tcscpy( m_szLastError, "Your guess is too high." );
30:      return HTTP_S_FALSE;
31:    }
32:
33:    // user guessed correctly
34:    return HTTP_SUCCESS;
35:  }
36:  else
37:  {
38:    // user has started a new game
39:    srand( (unsigned)time( NULL ) );
40:    m_iMagicNumber = (rand()%100)+1;
41:    
42:    // reset number of guesses
43:    m_iNumGuesses = 0;
44:
45:    return HTTP_S_FALSE;
46:  }
47: }

Now it's time to finish implementing the two remaining replacement functions: OnGetLastError and OnGetNumGuesses. OnGetLastError is responsible for rendering the last error message the user has encountered. In order to send content down the response stream to render on the client's browser, you use the m_HttpResponse member variable, which is an instance of CHttpResponse. Rendering content on the client uses a stream-based method of rendering. Therefore, you use the stream operator << for any data you want to render. In this case, you should check to make sure m_szLastError is not empty. If it's not, you need to render it to the m_HttpResponse stream, as shown in Listing 14.4. Finally, the last function, OnGetNumGuesses, should render the value of the variable m_iNumGuesses, which is also shown in Listing 14.4.

Listing 14.4 Rendering Content Using the HTTP Response Stream

 1: [ tag_name(name = "GetLastError") ]
 2: HTTP_CODE OnGetLastError(void)
 3: {
 4:  if( _tcscmp( m_szLastError, _T("") ) )
 5:  m_HttpResponse << "<FONT color=#ff0000>* </FONT>" << m_szLastError;
 6:
 7:  return HTTP_SUCCESS;
 8: }
 9:
10: [ tag_name(name = "GetNumGuesses") ]
11: HTTP_CODE OnGetNumGuesses(void)
12: {
13:  m_HttpResponse << m_iNumGuesses;
14:  return HTTP_SUCCESS;
15:}
  • + Share This
  • 🔖 Save To Your Account