home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / graphics / audio / mcipuzzl / puzzle.c < prev    next >
C/C++ Source or Header  |  1997-10-05  |  5KB  |  153 lines

  1. /**************************************************************************
  2.  *
  3.  *  THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY
  4.  *  KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  5.  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR
  6.  *  PURPOSE.
  7.  *
  8.  *  Copyright (C) 1992 - 1997 Microsoft Corporation.  All Rights Reserved.
  9.  *
  10.  **************************************************************************/
  11.  
  12. #define  STRICT
  13. #include <windows.h>
  14. #include <mmsystem.h>
  15. #include <stdlib.h>
  16. #include "puzzle.h"
  17.  
  18. #define MEM_COPY( hpd, hps, size ) memcpy( hpd, hps, size )
  19. #define DATA_PTR BYTE *
  20.  
  21. #define WIDTHBYTES(i)     ((unsigned)((i+31)&(~31))/8)  /* ULONG aligned ! */
  22. #define DIBWIDTHBYTES(bi) (DWORD)WIDTHBYTES((int)(bi).biWidth * (int)(bi).biBitCount)
  23.  
  24. //
  25. // Initialize the puzzle, and optionally simulate 1000 clicks on the puzzle
  26. //
  27. void InitPuzzle(
  28. LPPUZZLE p,
  29. BOOL fScramble)
  30. {
  31.         int i,j;
  32.  
  33.         // Set the puzzle to a "solved" state
  34.         for (i = 0; i < PSIZE; i++)
  35.                 for (j = 0; j < PSIZE; j++)
  36.                         p->a[i][j] = i + j * PSIZE;
  37.  
  38.         // Put the "hole" in the lower right corner.
  39.         p->a[PSIZE-1][PSIZE-1] = -1;
  40.         p->hx = PSIZE - 1;
  41.         p->hy = PSIZE - 1;
  42.  
  43.         if(fScramble) {
  44.                 // Make things really be random
  45.                 srand((unsigned int) timeGetTime());
  46.  
  47.                 for (i = 0; i < 1000; i++) {
  48.                         // Click on a random square
  49.                         int r = rand() % PSIZE;
  50.                         int s = rand() % PSIZE;
  51.                         ClickPuzzle(p, r, s);
  52.                 }
  53.         }
  54. }
  55.  
  56. //
  57. // Given a puzzle, and x & y in puzzle coordinates, move squares around
  58. // or not as appropriate, given how such puzzles work.
  59. //
  60. void ClickPuzzle(
  61. LPPUZZLE p,
  62. int x,
  63. int y)
  64. {
  65.         int i;
  66.  
  67.         if (x < 0 || x >= PSIZE)
  68.                 return;
  69.  
  70.         if (y < 0 || y >= PSIZE)
  71.                 return;
  72.  
  73.         if (x == p->hx) {
  74.                 if (y < p->hy) {
  75.                         for (i = p->hy; i > y; i--)
  76.                                 p->a[x][i] = p->a[x][i-1];
  77.                 } else if (y > p->hy) {
  78.                         for (i = p->hy; i < y; i++)
  79.                                 p->a[x][i] = p->a[x][i+1];
  80.                 }
  81.                 p->hy = y;
  82.                 p->a[x][y] = -1;
  83.         } else if (y == p->hy) {
  84.                 if (x < p->hx) {
  85.                         for (i = p->hx; i > x; i--)
  86.                                 p->a[i][y] = p->a[i-1][y];
  87.                 } else if (x > p->hx) {
  88.                         for (i = p->hx; i < x; i++)
  89.                                 p->a[i][y] = p->a[i+1][y];
  90.                 }
  91.                 p->hx = x;
  92.                 p->a[x][y] = -1;
  93.         }
  94.  
  95.         // We could potentially see if the puzzle was solved here.
  96.         // If we do that, the prototype should change to
  97.         // BOOL ClickPuzzle(LPPUZZLE p, int x, int y, BOOL fCheckSolved)
  98.         // where we would pass TRUE for fCheckSolved if the call was
  99.         // a result of the user really clicking, and not a call from
  100.         // InitPuzzle() or something....
  101. }
  102.  
  103.  
  104. //
  105. // Given a puzzle, map the input picture to the output picture with squares
  106. // rearranged.
  107. //
  108. // Works on any RGB DIB.  Doesn't work on bitmaps, probably, so could be a
  109. // problem with Todd's new DrawDib.
  110. //
  111. void MixPicture(
  112. LPPUZZLE p,
  113. LPBITMAPINFOHEADER lpbi,
  114. LPBYTE lpIn,
  115. LPBYTE lpOut)
  116. {
  117.         int i,j;
  118.         int y;
  119.         char achHack[1024] = {0};
  120.         int dx = ((int) lpbi->biWidth / PSIZE) * ((int) lpbi->biBitCount / 8);
  121.         int dy = (int) lpbi->biHeight / PSIZE;
  122.         LONG lRowBytes = DIBWIDTHBYTES(*lpbi);
  123.         DATA_PTR lpI;
  124.         DATA_PTR lpO;
  125.  
  126.         for (i = 0; i < PSIZE; i++) {
  127.                 for (j = 0; j < PSIZE; j++) {
  128.                         // Get pointer to square we're copying into
  129.                         lpO = (DATA_PTR) lpOut + (PSIZE - 1 - j) * dy * lRowBytes + dx * i;
  130.  
  131.                         if (p->a[i][j] >= 0) {
  132.                                 // Get pointer to square we're copying from
  133.                                 lpI = (DATA_PTR) lpIn +
  134.                                                 (PSIZE - 1 - (p->a[i][j] / PSIZE)) * dy * lRowBytes +
  135.                                                 dx * (p->a[i][j] % PSIZE);
  136.  
  137.                                 // do the copy
  138.                                 for (y = 0; y < dy; y++) {
  139.                                         MEM_COPY(lpO, lpI, dx);
  140.                                         lpO += lRowBytes;
  141.                                         lpI += lRowBytes;
  142.                                 }
  143.                         } else {
  144.                                 // clear the square to zeroes
  145.                                 for (y = 0; y < dy; y++) {
  146.                                         MEM_COPY(lpO, achHack, dx);
  147.                                         lpO += lRowBytes;
  148.                                 }
  149.                         }
  150.                 }
  151.         }
  152. }
  153.