home *** CD-ROM | disk | FTP | other *** search
- /*---------------------------------------------------------
- TAQUIN.C -- Jeu de Taquin for OS/2 Presentation Manager
- (c) 1989, Ziff Communications Co.
- PC Magazine * Charles Petzold, January 1989
- ---------------------------------------------------------*/
-
- #define INCL_WIN // include 'Win' functions in OS/2 headers
- #define INCL_GPI // include 'Gpi' functions in OS/2 headers
- #include <os2.h>
- #include <stdlib.h>
- #include "taquin.h"
-
- #define NUMROWS 4 // greater than or equal to 2
- #define NUMCOLS 4 // greater than or equal to 3
- #define SCRAMBLEREP 100 // make larger if using more than 16 square
- #define SQUARESIZE 67 // in 1/100th inch
-
- MRESULT EXPENTRY ClientWndProc (HWND, USHORT, MPARAM, MPARAM) ;
- MRESULT EXPENTRY AboutDlgProc (HWND, USHORT, MPARAM, MPARAM) ;
-
- int main (void)
- {
- static CHAR szClientClass[] = "Taquin" ;
- static ULONG flFrameFlags = FCF_SYSMENU | FCF_TITLEBAR |
- FCF_BORDER | FCF_MINBUTTON |
- FCF_MENU | FCF_ICON |
- FCF_TASKLIST ;
- HAB hab ;
- HMQ hmq ;
- HWND hwndFrame, hwndClient ;
- QMSG qmsg ;
- // Initialize and create standard window
-
- hab = WinInitialize (0) ;
- hmq = WinCreateMsgQueue (hab, 0) ;
- WinRegisterClass (hab, szClientClass, ClientWndProc, 0L, 0) ;
- hwndFrame = WinCreateStdWindow (HWND_DESKTOP, WS_VISIBLE,
- &flFrameFlags, szClientClass, NULL,
- 0L, NULL, ID_RESOURCE, &hwndClient) ;
-
- // Get messages from queue and dispatch them
-
- while (WinGetMsg (hab, &qmsg, NULL, 0, 0))
- WinDispatchMsg (hab, &qmsg) ;
-
- // Clean up and terminate
-
- WinDestroyWindow (hwndFrame) ;
- WinDestroyMsgQueue (hmq) ;
- WinTerminate (hab) ;
- return 0 ;
- }
-
- MRESULT EXPENTRY ClientWndProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
- {
- static SHORT asPuzzle[NUMROWS][NUMCOLS],
- sBlankRow, sBlankCol, cxSquare, cySquare ;
- CHAR szNum[5] ;
- HPS hps ;
- HWND hwndFrame ;
- POINTL ptl ;
- RECTL rcl, rclInvalid, rclIntersect ;
- SHORT sRow, sCol, sMouseRow, sMouseCol, i ;
- SIZEL sizl ;
-
- switch (msg)
- {
- case WM_CREATE:
- // Calculate square size in pixels
-
- hps = WinGetPS (hwnd) ;
- sizl.cx = sizl.cy = 0 ;
- GpiSetPS (hps, &sizl, PU_LOENGLISH) ;
- ptl.x = SQUARESIZE ;
- ptl.y = SQUARESIZE ;
- GpiConvert (hps, CVTC_PAGE, CVTC_DEVICE, 1L, &ptl) ;
- WinReleasePS (hps) ;
-
- cxSquare = (SHORT) ptl.x ;
- cySquare = (SHORT) ptl.y ;
-
- // Calculate client window size and position
-
- rcl.xLeft = (WinQuerySysValue (HWND_DESKTOP, SV_CXSCREEN) -
- NUMCOLS * cxSquare) / 2 ;
- rcl.yBottom = (WinQuerySysValue (HWND_DESKTOP, SV_CYSCREEN) -
- NUMROWS * cySquare) / 2 ;
- rcl.xRight = rcl.xLeft + NUMCOLS * cxSquare ;
- rcl.yTop = rcl.yBottom + NUMROWS * cySquare ;
-
- // Set frame window position and size
-
- hwndFrame = WinQueryWindow (hwnd, QW_PARENT, FALSE) ;
- WinCalcFrameRect (hwndFrame, &rcl, FALSE) ;
- WinSetWindowPos (hwndFrame, NULL,
- (SHORT) rcl.xLeft, (SHORT) rcl.yBottom,
- (SHORT) (rcl.xRight - rcl.xLeft),
- (SHORT) (rcl.yTop - rcl.yBottom),
- SWP_MOVE | SWP_SIZE | SWP_ACTIVATE) ;
-
- // Initialize the asPuzzle array
-
- WinSendMsg (hwnd, WM_COMMAND, MPFROMSHORT (IDM_NORMAL), NULL) ;
- return 0 ;
-
- case WM_PAINT:
- hps = WinBeginPaint (hwnd, NULL, &rclInvalid) ;
-
- // Draw the squares
-
- for (sRow = NUMROWS - 1 ; sRow >= 0 ; sRow--)
- for (sCol = 0 ; sCol < NUMCOLS ; sCol++)
- {
- rcl.xLeft = cxSquare * sCol ;
- rcl.yBottom = cySquare * sRow ;
- rcl.xRight = rcl.xLeft + cxSquare ;
- rcl.yTop = rcl.yBottom + cySquare ;
-
- if (!WinIntersectRect (NULL, &rclIntersect,
- &rcl, &rclInvalid))
- continue ;
-
- if (sRow == sBlankRow && sCol == sBlankCol)
- WinFillRect (hps, &rcl, CLR_BLACK) ;
- else
- {
- WinDrawBorder (hps, &rcl, 5, 5,
- CLR_PALEGRAY, CLR_DARKGRAY,
- DB_STANDARD | DB_INTERIOR) ;
- WinDrawBorder (hps, &rcl, 2, 2,
- CLR_BLACK, 0L, DB_STANDARD) ;
- WinDrawText (hps, -1,
- itoa (asPuzzle[sRow][sCol], szNum, 10),
- &rcl, CLR_WHITE, CLR_DARKGRAY,
- DT_CENTER | DT_VCENTER) ;
- }
- }
- WinEndPaint (hps) ;
- return 0 ;
-
- case WM_BUTTON1DOWN:
- sMouseCol = MOUSEMSG(&msg)->x / cxSquare ;
- sMouseRow = MOUSEMSG(&msg)->y / cySquare ;
-
- // Check if mouse was in valid area
-
- if ( sMouseRow < 0 || sMouseCol < 0 ||
- sMouseRow >= NUMROWS || sMouseCol >= NUMCOLS ||
- (sMouseRow != sBlankRow && sMouseCol != sBlankCol) ||
- (sMouseRow == sBlankRow && sMouseCol == sBlankCol))
- break ;
-
- // Move a row right or left
-
- if (sMouseRow == sBlankRow)
- {
- if (sMouseCol < sBlankCol)
- for (sCol = sBlankCol ; sCol > sMouseCol ; sCol--)
- asPuzzle[sBlankRow][sCol] =
- asPuzzle[sBlankRow][sCol - 1] ;
- else
- for (sCol = sBlankCol ; sCol < sMouseCol ; sCol++)
- asPuzzle[sBlankRow][sCol] =
- asPuzzle[sBlankRow][sCol + 1] ;
- }
- // Move a column up or down
- else
- {
- if (sMouseRow < sBlankRow)
- for (sRow = sBlankRow ; sRow > sMouseRow ; sRow--)
- asPuzzle[sRow][sBlankCol] =
- asPuzzle[sRow - 1][sBlankCol] ;
- else
- for (sRow = sBlankRow ; sRow < sMouseRow ; sRow++)
- asPuzzle[sRow][sBlankCol] =
- asPuzzle[sRow + 1][sBlankCol] ;
- }
- // Calculate invalid rectangle
-
- rcl.xLeft = cxSquare * min (sMouseCol, sBlankCol) ;
- rcl.yBottom = cySquare * min (sMouseRow, sBlankRow) ;
- rcl.xRight = cxSquare * (max (sMouseCol, sBlankCol) + 1) ;
- rcl.yTop = cySquare * (max (sMouseRow, sBlankRow) + 1) ;
-
- // Set new array and blank values
-
- sBlankRow = sMouseRow ;
- sBlankCol = sMouseCol ;
- asPuzzle[sBlankRow][sBlankCol] = 0 ;
-
- // Invalidate rectangle
-
- WinInvalidateRect (hwnd, &rcl, FALSE) ;
- break ;
-
- case WM_CHAR:
- if (!(CHARMSG(&msg)->fs & KC_VIRTUALKEY) ||
- CHARMSG(&msg)->fs & KC_KEYUP)
- return 0 ;
-
- // Mimic a WM_BUTTON1DOWN message
-
- sMouseCol = sBlankCol ;
- sMouseRow = sBlankRow ;
-
- switch (CHARMSG(&msg)->vkey)
- {
- case VK_LEFT: sMouseCol++ ; break ;
- case VK_RIGHT: sMouseCol-- ; break ;
- case VK_UP: sMouseRow-- ; break ;
- case VK_DOWN: sMouseRow++ ; break ;
- default: return 0 ;
- }
- WinSendMsg (hwnd, WM_BUTTON1DOWN,
- MPFROM2SHORT (sMouseCol * cxSquare,
- sMouseRow * cySquare), NULL) ;
- return 0 ;
-
- case WM_COMMAND:
- switch (COMMANDMSG(&msg)->cmd)
- {
- // Initialize asPuzzle array
-
- case IDM_NORMAL:
- case IDM_INVERT:
- for (sRow = 0 ; sRow < NUMROWS ; sRow++)
- for (sCol = 0 ; sCol < NUMCOLS ; sCol++)
- asPuzzle[sRow][sCol] = sCol + 1 +
- NUMCOLS * (NUMROWS - sRow - 1) ;
-
- if (COMMANDMSG(&msg)->cmd == IDM_INVERT)
- {
- asPuzzle[0][NUMCOLS-2] = NUMCOLS * NUMROWS - 2 ;
- asPuzzle[0][NUMCOLS-3] = NUMCOLS * NUMROWS - 1 ;
- }
- asPuzzle[sBlankRow = 0][sBlankCol = NUMCOLS - 1] = 0 ;
- WinInvalidateRect (hwnd, NULL, FALSE) ;
- return 0 ;
-
- // Randomly scramble the squares
-
- case IDM_SCRAMBLE:
- WinSetPointer (HWND_DESKTOP, WinQuerySysPointer (
- HWND_DESKTOP, SPTR_WAIT, FALSE)) ;
-
- srand ((int) WinGetCurrentTime (NULL)) ;
-
- for (i = 0 ; i < SCRAMBLEREP ; i++)
- {
- WinSendMsg (hwnd, WM_BUTTON1DOWN,
- MPFROM2SHORT (rand() % NUMCOLS * cxSquare,
- sBlankRow * cySquare), NULL) ;
- WinUpdateWindow (hwnd) ;
-
- WinSendMsg (hwnd, WM_BUTTON1DOWN,
- MPFROM2SHORT (sBlankCol * cxSquare,
- rand() % NUMROWS * cySquare), NULL) ;
- WinUpdateWindow (hwnd) ;
- }
- WinSetPointer (HWND_DESKTOP, WinQuerySysPointer (
- HWND_DESKTOP, SPTR_ARROW, FALSE));
- return 0 ;
-
- // Display dialog box
-
- case IDM_ABOUT:
- WinDlgBox (HWND_DESKTOP, hwnd, AboutDlgProc,
- NULL, IDD_ABOUT, NULL) ;
- return 0 ;
- }
- break ;
- }
- return WinDefWindowProc (hwnd, msg, mp1, mp2) ;
- }
-
- MRESULT EXPENTRY AboutDlgProc (HWND hwnd, USHORT msg, MPARAM mp1, MPARAM mp2)
- {
- switch (msg)
- {
- case WM_COMMAND:
- switch (COMMANDMSG(&msg)->cmd)
- {
- case DID_OK:
- case DID_CANCEL:
- WinDismissDlg (hwnd, TRUE) ;
- return 0 ;
- }
- break ;
- }
- return WinDefDlgProc (hwnd, msg, mp1, mp2) ;
- }
-