home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tv20cpp.zip / demos / puzzle.cpp < prev    next >
C/C++ Source or Header  |  1999-05-24  |  7KB  |  360 lines

  1. /*---------------------------------------------------------*/
  2. /*                                                         */
  3. /*   Turbo Vision Puzzle Demo                              */
  4. /*                                                         */
  5. /*---------------------------------------------------------*/
  6. /*
  7.  *      Turbo Vision - Version 2.0
  8.  *
  9.  *      Copyright (c) 1994 by Borland International
  10.  *      All Rights Reserved.
  11.  *
  12.  */
  13. /*
  14.  * Modified by Sergio Sigala <ssigala@globalnet.it>
  15.  */
  16.  
  17. #define Uses_TRect
  18. #define Uses_TEvent
  19. #define Uses_TKeys
  20. #define Uses_TDrawBuffer
  21. #define Uses_TStreamableClass
  22. #define Uses_TStreamable
  23. #define Uses_TView
  24. #define Uses_TWindow
  25. #include <tvision/tv.h>
  26. __link( RView )
  27. __link( RWindow )
  28.  
  29. #include <string.h>
  30. #include <stdio.h>    /* SS: for sprintf(...) */
  31. #include <stdlib.h>
  32. #include <ctype.h>
  33. #include <strstream.h>
  34. #include <iomanip.h>
  35. #include <sys/time.h>
  36. //#include <unistd.h>
  37.  
  38. #include "puzzle.h"
  39.  
  40.  
  41. #define cpPuzzlePalette "\x06\x07"
  42.  
  43.  
  44. //
  45. // TPuzzleView functions & static variables
  46. //
  47.  
  48. const char * const TPuzzleView::name = "TPuzzleView";
  49.  
  50.  
  51. void TPuzzleView::write( opstream& os )
  52. {
  53.     TView::write( os );
  54.     os.writeBytes(board, sizeof(board));
  55.     os << moves << solved;
  56. }
  57.  
  58.  
  59. void *TPuzzleView::read( ipstream& is )
  60. {
  61.     TView::read( is );
  62.     is.readBytes(board, sizeof(board));
  63.     is >> moves >> solved;
  64.     return this;
  65. }
  66.  
  67.  
  68. TStreamable *TPuzzleView::build()
  69. {
  70.     return new TPuzzleView( streamableInit );
  71. }
  72.  
  73.  
  74. TStreamableClass RPuzzleView( TPuzzleView::name,
  75.                               TPuzzleView::build,
  76.                               __DELTA(TPuzzleView)
  77.                             );
  78.  
  79.  
  80. static char boardStart[16] =
  81.     { 'A', 'B', 'C', 'D',
  82.       'E', 'F', 'G', 'H',
  83.       'I', 'J', 'K', 'L',
  84.       'M', 'N', 'O', ' '
  85.     };
  86.  
  87. static char map[15] =
  88.     { 0, 1, 0, 1,
  89.       1, 0, 1, 0,
  90.       0, 1, 0, 1,
  91.       1, 0, 1
  92.     };
  93.  
  94.  
  95. TPuzzleView::TPuzzleView(TRect& r) : TView(r)
  96. {
  97.     srand(time(NULL));
  98.     options |= ofSelectable;
  99.     memset( board, ' ', sizeof(board) );
  100.  
  101.     for(int i = 0; i <= 3; i++)
  102.         for(int j = 0; j <= 3; j++)
  103.             board[i][j] = boardStart[i*4+j];
  104.  
  105.     scramble();
  106. }
  107.  
  108.  
  109. void TPuzzleView::draw()
  110. {
  111.     char tmp[8];
  112.     char color[2], colorBack;
  113.     TDrawBuffer buf;
  114.  
  115.     color[0] = color[1] = colorBack = getColor(1);
  116.     if (!solved)
  117.         color[1] = getColor(2);
  118.  
  119.     /* SS: little change */
  120.     short i;
  121.     for(i = 0; i <= 3; i++)
  122.     //for(short i = 0; i <= 3; i++)
  123.         {
  124.         buf.moveChar(0, ' ', colorBack, 18);
  125.         if(i == 1)
  126.             buf.moveStr(13, "Move", colorBack);
  127.         if(i == 2)
  128.     {
  129.         sprintf(tmp, "%d",  moves);
  130.         buf.moveStr(14, tmp, colorBack);
  131.     }
  132.         for(short j = 0; j <= 3; j++)
  133.             {
  134.             strcpy(tmp, "   ");
  135.             tmp[1] = board[i][j];
  136.             if(board[i][j] == ' ')
  137.                 buf.moveStr( (short)(j*3), tmp, color[0]);
  138.             else
  139.                 buf.moveStr( (short)(j*3), tmp, color[map[board[i][j]-'A']]);
  140.             }
  141.         writeLine(0, i, 18, 1, buf);
  142.         }
  143. }
  144.  
  145.  
  146. TPalette& TPuzzleView::getPalette() const
  147. {
  148.     static TPalette palette( cpPuzzlePalette, sizeof(cpPuzzlePalette)-1 );
  149.     return palette;
  150. }
  151.  
  152.  
  153. void TPuzzleView::handleEvent(TEvent& event)
  154. {
  155.     TView::handleEvent(event);
  156.  
  157.     if (solved && (event.what & (evKeyboard | evMouse) ) )
  158.         {
  159.         scramble();
  160.         clearEvent(event);
  161.         }
  162.  
  163.     if(event.what == evMouseDown)
  164.         {
  165.         moveTile(event.mouse.where);
  166.         clearEvent(event);
  167.         winCheck();
  168.         }
  169.     else if(event.what == evKeyDown)
  170.         {
  171.         moveKey(event.keyDown.keyCode);
  172.         clearEvent(event);
  173.         winCheck();
  174.         }
  175. }
  176.  
  177. void TPuzzleView::moveKey(int key)
  178. {
  179.     /* SS: little change */
  180.     int i;
  181.     for(i = 0; i <= 15; i++)
  182. //    for(int i = 0; i <= 15; i++)
  183.         if(board[i/4][i%4] == ' ')
  184.             break;
  185.  
  186.     int x = i % 4;
  187.     int y = i / 4;
  188.  
  189.     switch(key)
  190.         {
  191.         case kbDown:
  192.             if (y > 0)
  193.                 {
  194.                 board[y][x] = board[y-1][x];
  195.                 board[y-1][x] = ' ';
  196.                 if(moves < 1000)
  197.                     moves++;
  198.                 }
  199.             break;
  200.  
  201.         case kbUp:
  202.             if (y < 3)
  203.                 {
  204.                 board[y][x] = board[y+1][x];
  205.                 board[y+1][x] = ' ';
  206.                 if(moves < 1000)
  207.                     moves++;
  208.                 }
  209.             break;
  210.  
  211.         case kbRight:
  212.             if (x > 0)
  213.                 {
  214.                 board[y][x] = board[y][x-1];
  215.                 board[y][x-1] = ' ';
  216.                 if(moves < 1000)
  217.                     moves++;
  218.                 }
  219.             break;
  220.  
  221.         case kbLeft:
  222.             if (x < 3)
  223.                 {
  224.                 board[y][x] = board[y][x+1];
  225.                 board[y][x+1] = ' ';
  226.                 if(moves < 1000)
  227.                     moves++;
  228.                 }
  229.             break;
  230.         }
  231.     drawView();
  232. }
  233.  
  234. void TPuzzleView::moveTile(TPoint p)
  235. {
  236.     p = makeLocal(p);
  237.  
  238.     /* SS: little change */
  239.     int i;
  240.     for(i = 0; i <= 15; i++)
  241. //    for(int i = 0; i <= 15; i++)
  242.         if(board[i/4][i%4] == ' ')
  243.             break;
  244.     int x = p.x / 3;
  245.     int y = p.y;
  246.  
  247.     switch( (y*4 + x - i) )
  248.         {
  249.         case -4:                            //  Piece moves down
  250.             moveKey(kbDown);
  251.             break;
  252.  
  253.         case -1:                            //  Piece moves right
  254.             moveKey(kbRight);
  255.             break;
  256.  
  257.         case 1:                             //  Piece moves left
  258.             moveKey(kbLeft);
  259.             break;
  260.  
  261.         case 4:                             //  Piece moves up
  262.             moveKey(kbUp);
  263.             break;
  264.  
  265.         }
  266.     drawView();
  267. }
  268.  
  269. void TPuzzleView::scramble()
  270. {
  271.     moves = 0;
  272.     solved = 0;
  273.     do
  274.         {
  275.         switch( (rand() >> 4) % 4)
  276.             {
  277.             case 0:
  278.                 moveKey(kbUp);
  279.                 break;
  280.  
  281.             case 1:
  282.                 moveKey(kbDown);
  283.                 break;
  284.  
  285.             case 2:
  286.                 moveKey(kbRight);
  287.                 break;
  288.  
  289.             case 3:
  290.                 moveKey(kbLeft);
  291.                 break;
  292.             }
  293.         } while (moves++ <= 500);
  294.  
  295.     moves = 0;
  296.     drawView();
  297. }
  298.  
  299.  
  300. static char *solution = "ABCDEFGHIJKLMNO ";
  301.  
  302. void TPuzzleView::winCheck()
  303. {
  304.     /* SS: little change */
  305.     int i;
  306.     for(i = 0; i <= 15; i++)
  307. //    for(int i = 0; i <= 15; i++)
  308.         if(board[i/4][i%4] != solution[i])
  309.             break;
  310.  
  311.     if(i == 16)
  312.         solved = 1;
  313.     drawView();
  314. }
  315.  
  316.  
  317. //
  318. // TPuzzleWindow functions
  319. //
  320.  
  321. const char * const TPuzzleWindow::name = "TPuzzleWindow";
  322.  
  323.  
  324. void TPuzzleWindow::write( opstream& os )
  325. {
  326.     TWindow::write( os );
  327. }
  328.  
  329.  
  330. void *TPuzzleWindow::read( ipstream& is )
  331. {
  332.     TWindow::read( is );
  333.     return this;
  334. }
  335.  
  336.  
  337. TStreamable *TPuzzleWindow::build()
  338. {
  339.     return new TPuzzleWindow( streamableInit );
  340. }
  341.  
  342.  
  343. TStreamableClass RPuzzleWindow( TPuzzleWindow::name,
  344.                                 TPuzzleWindow::build,
  345.                                 __DELTA(TPuzzleWindow)
  346.                               );
  347.  
  348.  
  349. TPuzzleWindow::TPuzzleWindow() :
  350.     TWindow( TRect(1, 1, 21, 7), "Puzzle", wnNoNumber),
  351.     TWindowInit( &TPuzzleWindow::initFrame )
  352. {
  353.     flags &= ~(wfZoom | wfGrow);
  354.     growMode = 0;
  355.  
  356.     TRect r = getExtent();
  357.     r.grow(-1, -1);
  358.     insert( new TPuzzleView(r) );
  359. }
  360.