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.