home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c082_144 / 2.ddi / TVDEMOS.ZIP / PUZZLE.CPP < prev    next >
Encoding:
C/C++ Source or Header  |  1992-06-10  |  7.0 KB  |  334 lines

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