This is QueensController.m in view mode; [Download] [Up]
#import "QueensController.h" @implementation QueensController // set up board // use selected buttons for white squares - awakeFromNib { int i, j; for (i=0; i LT 8; i++) for ( j=0; j LT 8; j++) { id cell = [board cellAt: i : j]; [cell setEnabled: NO]; if ( (i+j)%1 ) [board selectCell: cell]; } rows = 0; // only 1 row valid column[0] = 0; // only search last 4 due to symmetry [self placeQueenAt: 0 : column[0]]; [board display]; return( self); } /* Action messages */ - motor:sender { running = YES; [self motorStep]; return( self); } - pause: sender { running = NO; return( self); } - step: sender { running = [self countStep]; return( self); } // place another queen - (BOOL)countStep { BOOL placed = [self stepFrom: 0]; // update counter [stepsDisplay setIntValue: [stepsDisplay intValue]+1]; // if placed on row 7, it is solved // update solutions and maybe pause if ( rows EQ 7 ) { [solutionsDisplay setIntValue: [solutionsDisplay intValue]+1]; if ( [solutionPause intValue] ) return( NO); } return( placed); } - motorStep { // iterate single steps, // but delay between steps to allow // pause message if ( running ) { running = [self countStep]; [self perform: @selector( motorStep) with: nil afterDelay: 20 cancelPrevious: YES ]; } return( self); } // set the queen icon for the chosen cell - placeQueenAt: (int)aRow : (int)aColumn { id cell = [board cellAt: aRow : aColumn]; NXRect cellFrame; [cell setIcon: "queen"]; [board getCellFrame: &cellFrame at: aRow : aColumn]; [board display: &cellFrame : 1]; return( self); } // go back to no icon for the cell - removeQueenFrom: (int)aRow : (int)aColumn { id cell = [board cellAt: aRow : aColumn]; NXRect cellFrame; [cell setIcon: ""]; [board getCellFrame: &cellFrame at: aRow : aColumn]; [board display: &cellFrame : 1]; return( self); } // recursive scan - (BOOL)stepFrom: (int)aRow { int i; //limit recursion to 8 rows if ( aRow LT 8 ) { // if not at end of placed rows // go immediately to next row if ( aRow LE rows ) { if ( [self stepFrom: aRow+1] ) return( YES); // if at empty row, fall through // to continue scan else { rows = aRow; [self removeQueenFrom: aRow : column[ aRow]]; column[ aRow] += 1; } } // scan remainder of this row for ( i=column[ aRow]; i LT 8; i++ ) { // try next queen // if no attacks, move to next row [self placeQueenAt: aRow : i]; if ( [self validate: aRow : i] ) { column[ aRow] = i; rows = aRow; return( YES); } // remove this queen and continue [self removeQueenFrom: aRow: i]; } // reset this column and back up column[ aRow] = 0; } return( NO); } // check for attacks... // another queen in same column // or on diagonal - (BOOL)validate: (int)aRow : (int) aColumn { int i; for ( i=0; i LT aRow; i++ ) { int rowDistance = aRow - i; int columnDistance = aColumn - column[i]; if ( aColumn EQ column[i] || rowDistance EQ columnDistance || rowDistance EQ -columnDistance ) return( NO); } return( YES); } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.