Minesweeper (Part 5)

Today I present a rough prototype of our Minesweeper project. It incorporates the rendering techniques we’ve been experimenting with over the past few posts, and includes some (partial) game logic. At this point, you can only move around the playfield and uncover cells, but the demo illustrates the basic mechanics of the program.

Demo

You can download the latest demo here. The interface to reach a puzzle is a little strange: Tap the “+” button on the main screen to add a row to the table, then tap that row to bring up a puzzle. (Hopefully, this design will make more sense in a day or two.)

Touches

I took a shortcut to make the game respond to touches: I copied the approach (and, indeed, the code) from one of AAPL’s “ScrollViewSuite” demos. I set the content view inside our UIScrollView to be a TapDetectingView.

You can view the declaration and definition of TapDetectingView on AAPL’s site, or in the complete project.

Game Logic

Most of the “game logic” implemented so far is found in a single Playfield method:

- (void)tapDetectingView:(TapDetectingView*)tdView gotSingleTapAtPoint:(CGPoint)tapPoint
{
	if (![self cellForPoint:&tapPoint]) return;
	NSLog(@"Tap at (%.1f, %.1f)", tapPoint.x, tapPoint.y);

	[puzzle revealCell:tapPoint];

	UIView* tv = [content viewWithTag:(TAG_BASE + puzzle.w*tapPoint.y + tapPoint.x)];
	tv.layer.contents = (id) [[self imageForCell:tapPoint] CGImage];
}

(Note that I take advantage of the 1-to-1 correspondence between cells and tiles to cheaply figure out which parts of the UI need to be redrawn.)

Here are two of the more interesting helper functions:

- (BOOL)cellForPoint:(CGPoint*)point
{
	if (!point) return FALSE;
	
	CGPoint cell = CGPointMake(floorf(point->x/(cellSize.width*scale)),
				   floorf(point->y/(cellSize.height*scale)));
	
	if ([puzzle isLegalCell:cell])
	{
		*point = cell;
		return TRUE;
	}
	else
	{
		return FALSE;
	}
}


- (UIImage*)imageForCell:(CGPoint)pos
{
	if (![puzzle isRevealedCell:pos])
	{
		return [self.contents objectAtIndex:10];
	}
	else if ([puzzle isMinedCell:pos])
	{
		return [self.contents objectAtIndex:9];
	}
	else
	{
		return [self.contents objectAtIndex:[puzzle neighborsOfCell:pos]];
	}
}

I do use some “magic numbers” when referencing the contents array, but, well, “meh”.

Share and Enjoy:
  • Twitter
  • Facebook
  • Digg
  • Reddit
  • HackerNews
  • del.icio.us
  • Google Bookmarks
  • Slashdot
This entry was posted in iPhone, Projects. Bookmark the permalink.

Comments are closed.