home *** CD-ROM | disk | FTP | other *** search
/ The Fatted Calf / The Fatted Calf.iso / Applications / Misc / Queens / Source / QueensController.m < prev    next >
Encoding:
Text File  |  1993-11-09  |  3.3 KB  |  194 lines

  1.  
  2. #import "QueensController.h"
  3.  
  4. @implementation QueensController
  5.  
  6.                                 // set up board
  7.                                 // use selected buttons for white squares
  8. - awakeFromNib
  9.     {
  10.     int    i, j;
  11.     
  12.     for (i=0; i LT 8; i++)
  13.         for ( j=0; j LT 8; j++)
  14.             {
  15.             id        cell = [board cellAt: i : j];
  16.             
  17.             [cell setEnabled: NO];
  18.             if ( (i+j)%1 )
  19.                 [board selectCell: cell];
  20.             }
  21.  
  22.     rows = 0;                    // only 1 row valid
  23.     column[0] = 0;                // only search last 4 due to symmetry
  24.     [self placeQueenAt: 0 : column[0]];
  25.     [board display];
  26.     return( self);
  27.     }
  28.     
  29.                                 
  30.     /*    Action messages            */
  31.     
  32. - motor:sender
  33.     {
  34.     running = YES;
  35.     [self motorStep];
  36.     return( self);
  37.     }
  38.     
  39.  
  40. - pause: sender
  41.     {
  42.     running = NO;
  43.     return( self);
  44.     }
  45.     
  46.  
  47. - step: sender
  48.     {
  49.     running = [self countStep];
  50.     return( self);
  51.     }
  52.  
  53.  
  54.                                 // place another queen
  55. - (BOOL)countStep
  56.     {
  57.     BOOL    placed = [self stepFrom: 0];
  58.  
  59.                                 // update counter    
  60.     [stepsDisplay setIntValue: [stepsDisplay intValue]+1];
  61.     
  62.                                 // if placed on row 7, it is solved
  63.                                 // update solutions and maybe pause
  64.     if ( rows EQ 7 )
  65.         {
  66.         [solutionsDisplay setIntValue: [solutionsDisplay intValue]+1];
  67.         if ( [solutionPause intValue] )
  68.             return( NO);
  69.         }
  70.         
  71.     return( placed);
  72.     }
  73.     
  74.  
  75. - motorStep
  76.     {
  77.                                 // iterate single steps,
  78.                                 // but delay between steps to allow
  79.                                 // pause message
  80.     if ( running )
  81.         {
  82.         running = [self countStep];
  83.  
  84.         [self perform: 
  85.                 @selector( motorStep) with: nil 
  86.                 afterDelay: 20 cancelPrevious: YES
  87.                 ];
  88.         }
  89.  
  90.     return( self);        
  91.     }
  92.     
  93.  
  94.                                 // set the queen icon for the chosen cell
  95. - placeQueenAt: (int)aRow : (int)aColumn
  96.     {
  97.     id        cell = [board cellAt: aRow : aColumn];
  98.     NXRect    cellFrame;
  99.     
  100.     [cell setIcon: "queen"];
  101.     [board getCellFrame: &cellFrame at: aRow : aColumn];
  102.     [board display: &cellFrame : 1];
  103.     return( self);
  104.     }
  105.  
  106.  
  107.                                 // go back to no icon for the cell
  108. - removeQueenFrom: (int)aRow : (int)aColumn
  109.     {
  110.     id        cell = [board cellAt: aRow : aColumn];
  111.     NXRect    cellFrame;
  112.     
  113.     [cell setIcon: ""];
  114.     [board getCellFrame: &cellFrame at: aRow : aColumn];
  115.     [board display: &cellFrame : 1];
  116.     return( self);
  117.     }
  118.  
  119.  
  120.                                 // recursive scan
  121. - (BOOL)stepFrom: (int)aRow
  122.     {
  123.     int        i;
  124.                                 //limit recursion to 8 rows    
  125.     if ( aRow LT 8 )
  126.         {
  127.                                 // if not at end of placed rows
  128.                                 // go immediately to next row
  129.         if ( aRow LE rows )
  130.             {
  131.             if ( [self stepFrom: aRow+1] )
  132.                 return( YES);
  133.                 
  134.                                 // if at empty row, fall through
  135.                                 // to continue scan
  136.             else
  137.                 {
  138.                 rows = aRow;
  139.                 [self removeQueenFrom: aRow : column[ aRow]];
  140.                 column[ aRow] += 1;
  141.                 }
  142.             }
  143.  
  144.                                 // scan remainder of this row        
  145.         for ( i=column[ aRow]; i LT 8; i++ )
  146.             {
  147.                                 // try next queen 
  148.                                 // if no attacks, move to next row
  149.             [self placeQueenAt: aRow : i];
  150.             if ( [self validate: aRow : i] )
  151.                 {
  152.                 column[ aRow] = i;
  153.                 rows = aRow;
  154.                 return( YES);
  155.                 }
  156.  
  157.                                 // remove this queen and continue            
  158.             [self removeQueenFrom: aRow: i];
  159.             }
  160.  
  161.                                 // reset this column and back up
  162.         column[ aRow] = 0;
  163.         }
  164.  
  165.     return( NO);
  166.     }
  167.     
  168.  
  169.                                 // check for attacks...
  170.                                 // another queen in same column
  171.                                 // or on diagonal
  172. - (BOOL)validate: (int)aRow : (int) aColumn
  173.     {
  174.     int        i;
  175.     
  176.     for ( i=0; i LT aRow; i++ )
  177.         {
  178.         int        rowDistance = aRow - i;
  179.         int        columnDistance = aColumn - column[i];
  180.         
  181.         if ( 
  182.                 aColumn EQ column[i]
  183.                 || rowDistance EQ columnDistance
  184.                 || rowDistance EQ -columnDistance
  185.                 )
  186.             return( NO);
  187.         }
  188.     
  189.     return( YES);
  190.     }
  191.     
  192.  
  193. @end
  194.