Skip to content

Commit

Permalink
Changed method prototypes of ones that return a short * to take the o…
Browse files Browse the repository at this point in the history
…utput as an argument. This allows us to free() them when we're done, to fix memory leaks.
  • Loading branch information
noitsjocelyn committed Nov 1, 2013
1 parent 0c2faaa commit 2df7f1c
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 89 deletions.
1 change: 1 addition & 0 deletions PuzzleTutor/Puzzle.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@

- (id)init;
- (id)initWithShortArray:(short *)shortArray;
- (id)initWithNumberArray:(NSArray *)array;
- (id)initWithString:(NSString *)stringRepresentation;

- (short)getPuzzleValueAtIndex:(short)index;
Expand Down
15 changes: 15 additions & 0 deletions PuzzleTutor/Puzzle.m
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,21 @@ - (id)initWithShortArray:(short *)shortArray
return self;
}

/* Method to initialize the Puzzle with an NSArray of 81 NSNumbers.
*/
- (id)initWithNumberArray:(NSArray *)array
{
self = [self init];
short *shortArray = calloc(81, sizeof(short));
for (NSUInteger i = 0; i < 81; ++i)
{
shortArray[i] = [(NSNumber *)[array objectAtIndex:i] shortValue];
}
[self putInShortArray:shortArray];
free(shortArray);
return self;
}

/* Method to initialize the Puzzle with an NSString of length 81.
*/
- (id)initWithString:(NSString *)stringRepresentation
Expand Down
8 changes: 5 additions & 3 deletions PuzzleTutor/PuzzleMaker.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,11 @@
short workingPuzzle[81];
}

- (short *)buildEasyPuzzle;
- (short *)buildMediumPuzzle;
//- (short *)buildEasyPuzzle;
//- (short *)buildMediumPuzzle;
- (void)givePuzzle:(short *)thePuzzle;
- (short *)getWorkingPuzzle;
- (short *)getWorkingPuzzle:(short *)outputArray;
- (short *)buildEasyPuzzle:(short *)outputArray;
- (short *)buildMediumPuzzle:(short *)outputArray;

@end
152 changes: 85 additions & 67 deletions PuzzleTutor/PuzzleMaker.m
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,6 @@ - (id)init
/* The givePuzzle function. When given a short array representation of a puzzle,
* it sets the givenPuzzle member to the given puzzle.
*/
- (short *)getWorkingPuzzle
{
return workingPuzzle;
}

- (void)givePuzzle:(short *)thePuzzle
{
for (short i = 0; i < 81; ++i)
Expand All @@ -30,6 +25,88 @@ - (void)givePuzzle:(short *)thePuzzle
}
}

- (short *)getWorkingPuzzle:(short *)outputArray
{
for (short i = 0; i < 81; ++i)
{
outputArray[i] = workingPuzzle[i];
}
return outputArray;
}

- (short *)buildEasyPuzzle:(short *)outputArray
{
[self buildEasyPuzzle];
return [self getWorkingPuzzle:outputArray];
}

- (short *)buildMediumPuzzle:(short *)outputArray
{
[self buildMediumPuzzle];
return [self getWorkingPuzzle:outputArray];
}

/* The buildEasyPuzzle function. It uses count to track how many locations have
* been filled, either by deduciton or by displaying the value. Inside of a
* loop, it first looks to deduce a location's value by the
* findSquareWithOneAvaiableValue algorithm. If that fails, it generates random
* numbers between 0 and 40 until it finds one such that that location and 80
* minus that location are both unfilled. It then makes those squares' values
* part of the initial puzzle displayed to the user.
*/
//- (short *)buildEasyPuzzle
- (void)buildEasyPuzzle
{
short count = 0;
while (count < 81)
{
short *results = [basePuzzle findSquareWithOneAvailableValue];
if (results[0] != 0)
{
[basePuzzle putInValue:(results[2] * 9 + results[3])];
count += 1;
}
else
{
int r = arc4random() % 41;
int r2 = 80 - r;
BOOL alreadyCounted = NO;
BOOL alreadyCounted2 = NO;
if ([basePuzzle getPuzzleValueAtIndex: r] != 0)
{
alreadyCounted = YES;
}
[basePuzzle putInValue:(givenPuzzle[r] + r * 9)];
if (workingPuzzle[r] != givenPuzzle[r])
{
workingPuzzle[r] = givenPuzzle[r];
if (alreadyCounted == NO)
{
count += 1;
}
}
if (r != 40)
{
if ([basePuzzle getPuzzleValueAtIndex: r2] != 0)
{
alreadyCounted2 = YES;
}
[basePuzzle putInValue:(givenPuzzle[r2] + r2 * 9)];
if (workingPuzzle[r2] != givenPuzzle[r2])
{
workingPuzzle[r2] = givenPuzzle[r2];
if (alreadyCounted == NO)
{
count += 1;
}
}
}
}
free(results);
}
// return workingPuzzle;
}

/* The buildMediumPuzzle function. It uses count to track how many locations
* have been filled, either by deduciton or by displaying the value. Inside of
* a loop, it first looks to deduce a location's value by the
Expand All @@ -40,7 +117,8 @@ - (void)givePuzzle:(short *)thePuzzle
* unfilled. It then makes those squares' values part of the initial puzzle
* displayed to the user.
*/
- (short *)buildMediumPuzzle
//- (short *)buildMediumPuzzle
- (void)buildMediumPuzzle
{
short count = 0;
while (count < 81)
Expand Down Expand Up @@ -98,67 +176,7 @@ - (short *)buildMediumPuzzle
}
free(results);
}
return workingPuzzle;
}

/* The buildEasyPuzzle function. It uses count to track how many locations have
* been filled, either by deduciton or by displaying the value. Inside of a
* loop, it first looks to deduce a location's value by the
* findSquareWithOneAvaiableValue algorithm. If that fails, it generates random
* numbers between 0 and 40 until it finds one such that that location and 80
* minus that location are both unfilled. It then makes those squares' values
* part of the initial puzzle displayed to the user.
*/
- (short *) buildEasyPuzzle
{
short count = 0;
while (count < 81)
{
short *results = [basePuzzle findSquareWithOneAvailableValue];
if (results[0] != 0)
{
[basePuzzle putInValue:(results[2] * 9 + results[3])];
count += 1;
}
else
{
int r = arc4random() % 41;
int r2 = 80 - r;
BOOL alreadyCounted = NO;
BOOL alreadyCounted2 = NO;
if ([basePuzzle getPuzzleValueAtIndex: r] != 0)
{
alreadyCounted = YES;
}
[basePuzzle putInValue:(givenPuzzle[r] + r * 9)];
if (workingPuzzle[r] != givenPuzzle[r])
{
workingPuzzle[r] = givenPuzzle[r];
if (alreadyCounted == NO)
{
count += 1;
}
}
if (r != 40)
{
if ([basePuzzle getPuzzleValueAtIndex: r2] != 0)
{
alreadyCounted2 = YES;
}
[basePuzzle putInValue:(givenPuzzle[r2] + r2 * 9)];
if (workingPuzzle[r2] != givenPuzzle[r2])
{
workingPuzzle[r2] = givenPuzzle[r2];
if (alreadyCounted == NO)
{
count += 1;
}
}
}
}
free(results);
}
return workingPuzzle;
// return workingPuzzle;
}

@end
23 changes: 15 additions & 8 deletions Sudoku Teacher/Sudoku Teacher/PPSudokuGameViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -182,35 +182,42 @@ - (void)generateAndDisplayBoard:(id)sender
// Generate the full puzzle board
SudokuBoard *aBoard = nil;
// The generate method returns nil if there is a failure, so loop it
#ifdef DEBUG
NSUInteger attempts = 0;
#endif
while (!aBoard)
{
#ifdef DEBUG
++attempts;
NSLog(@"Generating puzzle, try %d...", attempts);
#endif
aBoard = [SudokuBoardGenerator generate];
}
#ifdef DEBUG
NSLog(@"Took %d %@ to generate full puzzle.", attempts, attempts == 1 ? @"try" : @"tries");
NSLog(@"Took %d %@ to generate.", attempts, attempts == 1 ? @"try" : @"tries");
#endif
// Generate the puzzle
PuzzleMaker *aMaker = [[PuzzleMaker alloc] init];
[aMaker givePuzzle:[aBoard boardAsShortArray]];
short *puzzleArray;
short *fullPuzzleArray = calloc(81, sizeof(short));
fullPuzzleArray = [aBoard boardAsShortArray:fullPuzzleArray];
[aMaker givePuzzle:fullPuzzleArray];
free(fullPuzzleArray);
// Make our Puzzle data
short *puzzleArray = calloc(81, sizeof(short));
if (self.difficulty == 0)
{
puzzleArray = [aMaker buildEasyPuzzle];
puzzleArray = [aMaker buildEasyPuzzle:puzzleArray];
}
else
{
puzzleArray = [aMaker buildMediumPuzzle];
puzzleArray = [aMaker buildMediumPuzzle:puzzleArray];
}
// Make our Puzzle data
Puzzle *newPuzzleData = [[Puzzle alloc] initWithShortArray:puzzleArray];
// Setup the board
[self setupFromPuzzleData:newPuzzleData];
aBoard = Nil;
aMaker = Nil;
// I think this needs to be freed, but I'm getting warnings when I do, so leaving it for now
//free(puzzleArray);
free(puzzleArray);

// Animate removing the processing view
[UIView animateWithDuration:0.4
Expand Down
2 changes: 1 addition & 1 deletion SudokuGenerator/SudokuBoard.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,6 @@

+ (id) sudokuBoard;
- (SudokuBoardSector *) sectorWithSectorId: (NSUInteger) sectorId;
- (short *) boardAsShortArray;
- (short *) boardAsShortArray: (short *) outputArray;

@end
19 changes: 9 additions & 10 deletions SudokuGenerator/SudokuBoard.m
Original file line number Diff line number Diff line change
Expand Up @@ -139,25 +139,24 @@ - (NSString *) description {
return desc;
}

- (short *) boardAsShortArray {
short *output = calloc(81, sizeof(short));
- (short *) boardAsShortArray: (short *) outputArray {
for (NSUInteger s = 0; s < 9; ++s) {
SudokuBoardSector *sector = [_sectors objectAtIndex:s];
SudokuBoardSector *sector = [_sectors objectAtIndex: s];
for (NSUInteger x = 0; x < 3; ++x) {
for (NSUInteger y = 0; y < 3; ++y) {
// Note: sectors are positioned as follows:
// 0 1 2
// 3 4 5
// 6 7 8
short num = (short)[sector numberAtX:x y:y];
short xOffset = 3 * (s % 3);
short locX = xOffset + x;
short yOffset = 0;
short num = (short)[sector numberAtX: x y: y];
NSUInteger xOffset = 3 * (s % 3);
NSUInteger locX = xOffset + x;
NSUInteger yOffset = 0;
if (s >= 3 && s < 6) yOffset = 3;
if (s >= 6 && s < 9) yOffset = 6;
short locY = yOffset + y;
NSUInteger locY = yOffset + y;
NSUInteger loc = 9 * locX + locY;
output[loc] = num;
outputArray[loc] = num;
}
}
#if __has_feature(objc_arc)
Expand All @@ -166,7 +165,7 @@ - (short *) boardAsShortArray {
[sector autorelease];
#endif
}
return output;
return outputArray;
}

@end

0 comments on commit 2df7f1c

Please sign in to comment.