透過 UIPickerView 製作吃角子老虎遊戲

螢幕快照 2011-11-18 下午1.25.59
多虧了 Apple 所提供的 UIPickerView 類別,再加上 Interface Builder 的幫助,可以很容易就製作出吃角子老虎的遊戲。




在這遊戲中,會透過 Picker View 設計三個 Column ,每個 Column 中各會放有六個圖像。另外是一個按鈕元件來啟動遊戲、一個標籤元件來顯示玩家是否獲得勝利的文字。
當使用者按下按鈕後,這個簡易的吃角子老虎遊戲將會啟動,同時按鈕會暫時消失,以免使用者拼命按、一直按...當遊戲結果顯示後,按鈕才會再度出現。
整個製作過程將如下所述。

先打開一個新的 view-based 專案、命名之後,新增檔案選擇 UIViewController 的 subclass,這邊我將其命名為 customPickerViewController,創建時選擇 with XIB,可以順便把xib 新建出來。


螢幕快照 2011-11-18 下午1.15.44



先把 customPickerViewController.h 拿出來改,程式碼如下:


#import <UIKit/UIKit.h>

@interface CustomPickViewControllerViewController : UIViewController <UIPickerViewDataSource, UIPickerViewDelegate>
{
    UIPickerView *picker;
    UILabel *winLabel;
    
    NSArray *column1;
    NSArray *column2;
    NSArray *column3;
    
    UIButton *button;
    UILabel *label;
}

@property (nonatomic, retain) IBOutlet UILabel *label;
@property (nonatomic, retain) IBOutlet UIButton *button;
@property (nonatomic, retain) IBOutlet UIPickerView *picker;
@property (nonatomic, retain) IBOutlet UILabel *winLabel;
@property (nonatomic, retain) NSArray *column1;
@property (nonatomic, retain) NSArray *column2;
@property (nonatomic, retain) NSArray *column3;

-(IBAction) spin;

@end



.h 標頭檔完成後,打開 customPickerViewController.xib 檔,開始製作介面。我們需要的是一個 Pick View, 一個Button, 以及一個 Label 元件,然後將按鈕改個名字、Label 原本顯示的文字去掉,因為之後會以程式碼設定將顯示於其上的文字。最後將各個元件與標頭檔中所創建的 IBOutlet, IBAction 做連結,好了後應該是如下圖的狀態:


螢幕快照 2011-11-21 下午1.51.27



再來我們需要將一些小圖片加入專案之中,注意圖片大小不要太大、使用 .png 檔,如果自己沒有的話,在 Google 中搜尋『icon』,可以找到許多免費的資源。挑好自己喜歡的圖片後,將其加入專案。


螢幕快照 2011-11-18 下午1.25.36



最後一個步驟,就是撰寫 customPickerViewController.m 的程式碼,再次感謝 Apple ,使我們並不需要寫太多的程式碼也可以完成這遊戲。
#import "CustomPickViewControllerViewController.h"

@implementation CustomPickViewControllerViewController

@synthesize picker, winLabel, column1, column2, column3;
@synthesize button, label;

-(void) showButton
{
    label.hidden = NO;
    button.hidden = NO;
}

-(void)playerWin
{
    winLabel.text = @"WIN!";
    
    [self performSelector:@selector(showButton) withObject:nil afterDelay:0.5];
}

-(IBAction)spin
{
    BOOL win = NO;
    int numInRow = 1;
    int lastVal = -1;
    
    for (int i=0; i < 3; i++) {
        int newValue = random()% [self.column1 count];
        
        if (newValue == lastVal)
            numInRow ++;
        else numInRow = 1;
        
        lastVal = newValue;
        
        [picker selectRow:newValue inComponent:i animated:YES];
        [picker reloadComponent:i];
        
        if (numInRow >=2) 
            win = YES;
    }
    
    button.hidden = YES;
    label.hidden = YES;
    
    if (win) {
        [self performSelector:@selector(playerWin) withObject:nil afterDelay:0.5];
    }
    
    else 
        [self performSelector:@selector(showButton) withObject:nil afterDelay:0.5];
    
    winLabel.text = @"LOSE....";
}

- (void)dealloc
{
    [picker release];
    [winLabel release];
    [column1 release];
    [column2 release];
    [column3 release];
    
    [super dealloc];
}

- (void)didReceiveMemoryWarning
{
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];
    
    // Release any cached data, images, etc that aren't in use.
}

#pragma mark - View lifecycle


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad
{
    UIImage *icon1 = [UIImage imageNamed:@"32.png"];
    UIImage *icon2 = [UIImage imageNamed:@"33.png"];
    UIImage *icon3 = [UIImage imageNamed:@"34.png"];
    UIImage *icon4 = [UIImage imageNamed:@"35.png"];
    UIImage *icon5 = [UIImage imageNamed:@"36.png"];
    UIImage *icon6 = [UIImage imageNamed:@"37.png"];
    
    for (int i=1; i<=3; i++) {
        UIImageView *iconView1 = [[UIImageView alloc] initWithImage:icon1];
        UIImageView *iconView2 = [[UIImageView alloc] initWithImage:icon2];
        UIImageView *iconView3 = [[UIImageView alloc] initWithImage:icon3];
        UIImageView *iconView4 = [[UIImageView alloc] initWithImage:icon4];
        UIImageView *iconView5 = [[UIImageView alloc] initWithImage:icon5];
        UIImageView *iconView6 = [[UIImageView alloc] initWithImage:icon6];
        
        NSArray *array = [[NSArray alloc] initWithObjects:iconView1, iconView2, iconView3, iconView4, iconView5, iconView6, nil];
        
        NSString *fieldName = [[NSString alloc] initWithFormat:@"column%d", i];
        [self setValue:array forKey:fieldName];
        [fieldName release];
        [array release];
        
        [iconView1 release];
        [iconView2 release];
        [iconView3 release];
        [iconView4 release];
        [iconView5 release];
        [iconView6 release];
    }
    
    srandom(time(NULL));
    
    [super viewDidLoad];
}


- (void)viewDidUnload
{
    self.picker = nil;
    self.winLabel = nil;
    self.column1 = nil;
    self.column2 = nil;
    self.column3 = nil;
    
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark picker data source methods
-(NSInteger) numberOfComponentsInPickerView:(UIPickerView *)pickerView
{
    return 3;
}

-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component
{
    return [self.column1 count];
}

#pragma mark picker delegate methods
-(UIView *) pickerView:(UIPickerView *)pickerView viewForRow:(NSInteger)row forComponent:(NSInteger)component reusingView:(UIView *)view
{
    NSString *arrayName = [[NSString alloc] initWithFormat:@"column%d", component+1];
    
    NSArray *array = [self valueForKey:arrayName];
    [arrayName release];
    return [array objectAtIndex:row];
}

@end

當上述步驟都完成後,可以開始執行了!如果一切無誤的話,按下畫面中的按鈕,三個轉輪就會啟動,並停在隨機一個圖案上;因為用了六個不同的圖片,所以設定只要有兩個一樣的圖片,就會使用者獲勝,否則即為失敗。


螢幕快照 2011-11-18 下午1.26.07

螢幕快照 2011-11-18 下午1.26.20