Jeu De Taquin

created and published by Ziff Communications in 1989-04-05, running on OS/2
type: puzzle
genre: N-puzzle
perspective: bird's-eye fixed camera
player options: single player
languages: eng

Technical specs

display: raster

Editor note

/*---------------------------------------------------------
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) ;
}

# 2013-04-04 15:18:47

Tag

traditional

Contributors (4)

AndreaD
zerothis
dandyboh
uvlbot-1

Post an anonymous comment / review about this game.

Rate and review

LIKE
PLAYED
FINISHED
OWN
PLAYING
WANT
View the full gallery