IOS/Xcode工具

一:主要功能

在拼图小游戏开发过程中,实现的主要的功能。

  1. 压缩图片:需要给传递过来的任意图片,根据手机模拟器中View大小,重新设置图片的尺寸,即压缩图片运用UIGraphicsBeginImageContext进行实现。
  2. 切割图片separateImage:将尺寸设置好的图片,进行切割成3*3 或者4*4,获取整个View的尺寸大小和图片的尺寸大小,进行大小比较,当图片的大小超过容器View的时候,将图片进行大小的缩放。然后根据切割的块,来计算出每个图块的宽高。运用两层For循环,将完整的图片按照每块设置的大小进行切割,并将0-0位置设置为空白位置 。将每块图片View的信息放到数组中。存放的信息有:当前拼图的下标,以及拼图起始没有打乱顺序的下标,用来最后判断游戏是否胜利的标记。
  3. 打乱图片顺序:产生两个NSINteger随机数,来作为存放图片View的数组的下标,从而获取图片信息,然后将两张图片进行位置对换,并改变当前拼图的下标。然后用逆序数的奇偶性来判断游戏是否能正常复位(有时候随机打乱的图片,并不能够恢复原来的位置即无解,则就需要运用逆序数的奇偶性进行判断),并判断拼图是否完全的打乱。如果两个条件有一方符合,将再次遍历打乱图片,产生两个随机数…否则游戏开始。
  4. 拼图移动:由于每个图块都有在合适的位置进行移动的实现方法,所以如果我们点击的图片,能与空白位进行移动,那么就交换这两张图块。
  5. 游戏完成:遍历的从存放每个图块视图的数组中取出每块图片View,并判断每块图片的当前下标,是否与最终特定的下标位置相等,如果每个图块都完全对照,则表示图片拼凑完成,则游戏胜利,弹出对话框。

二:效果图

  • 开始:

  • 拼图开始(点击菜单可以返回):

  • 拼图进阶:

  • 成功:

三:代码

If you are interested, study the code.

  1. 拼图视图PuzzleImageView.m
  2. 拼图视图PuzzleImageView.h
  3. 拼图视图控制器PuzzleViewController.m
  4. 拼图视图控制器PuzzleViewController.h
  5. 菜单视图控制器MenuViewController.m
  6. 菜单视图控制器MenuViewControlle.h

1:拼图视图PuzzleImageView.m

//PuzzleImageView.m#import <Foundation/Foundation.h>
#import "PuzzleImageView.h"
@implementation PuzzleImageView- (id)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {}return self;
}- (id) initWithImage:(UIImage *)image
{if (self = [super initWithImage:image]) {[self setUserInteractionEnabled:YES];//交互设置[self setMultipleTouchEnabled:YES];//多指触控self.layer.borderWidth = 1;//注意边框为1,来判断拼图是否能移动}return self;
}-(BOOL)canMoveToPoint:(CGPoint)pos
{//判断拼图是否能够移动,注意Origin的取值。CGPoint point = self.frame.origin;CGSize size = self.frame.size;//可用Log输出日志对其中取值进行查看//左右移动的拼图if (abs(abs(point.x - pos.x) - size.width) <1 && (point.y == pos.y)){return YES;}//上下移动拼图else if(abs(abs(point.y - pos.y) - size.height) <1 && (point.x == pos.x)){return YES;}else{return NO;}
}-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{//代理if(self.delegate && [self.delegate respondsToSelector:@selector(puzzleImageViewShouldMove:)]){[self.delegate puzzleImageViewShouldMove:self];}
}
@end

2: 拼图视图PuzzleImageView.h

//PuzzleImageView.h#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
@class PuzzleImageView;@protocol PuzzleDelegate <NSObject>@optional
-(void) puzzleImageViewShouldMove:(PuzzleImageView *)imageview;@end@interface PuzzleImageView : UIImageView@property (assign, nonatomic) id <PuzzleDelegate> delegate;@property (assign, nonatomic) NSInteger resultIndex;
@property (assign, nonatomic) NSInteger nowIndex;-(BOOL)canMoveToPoint:(CGPoint)pos;
@end

3:拼图视图控制器PuzzleViewController.m

//PuzzleViewController.m#import "PuzzleViewController.h"
#import <Foundation/Foundation.h>
@interface PuzzleViewController ()@end@implementation PuzzleViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];if (self) {// Custom initialization}return self;
}- (void)viewDidLoad
{[super viewDidLoad];//初始化数据[self initData];//初始化图片[self initPuzzleImage];
}
- (void)viewWillAppear:(BOOL)animated
{[super viewWillAppear:animated];
}
- (void)didReceiveMemoryWarning
{[super didReceiveMemoryWarning];
}// 初始化必要数据
-(void) initData
{self.title = @"拼图";self.string_ImageName = @"IMG.JPG";
}// 初始化图片
-(void) initPuzzleImage
{[self resetPuzzleImageWithImage:[UIImage imageNamed:self.string_ImageName]];
}
// 重置图片
-(void) resetPuzzleImageWithImage:(UIImage *)image
{CGFloat scale = image.size.height / image.size.width;//重新设置图片尺寸(压缩图片)UIImage *resultImage = [self image:image ByScalingToSize:CGSizeMake(380, 380*scale)];self.isStart = NO;//切割图片self.array_ImageView = [self separateImage:resultImage ByX:self.lvl andY:self.lvl];//打乱图片顺序[self puzzleTheImage];if(self.view_PuzzleBoard){[self.view_PuzzleBoard removeFromSuperview];}//加载图片视图(tip:可以通过修改坐标值,以及更改背景颜色,来观察,绘制位置)self.view_PuzzleBoard = [self createPuzzleBoardViewWithFrame:CGRectMake(0, 0, 380, [UIScreen mainScreen].bounds.size.height)];//将拼图视图添加到View中[self.view addSubview:self.view_PuzzleBoard];
}//重新设置图片尺寸
- (UIImage *)image:(UIImage *)sourceImage ByScalingToSize:(CGSize)targetSize
{UIImage *newImage = nil;    CGRect rect = CGRectMake(0.0, 0.0, targetSize.width, targetSize.height);//压缩图片过程UIGraphicsBeginImageContext(rect.size);[sourceImage drawInRect:rect];newImage = UIGraphicsGetImageFromCurrentImageContext();UIGraphicsEndImageContext();if(newImage == nil)NSLog(@"could not scale image");return newImage ;
}// 分解图片
-(NSMutableArray *) separateImage:(UIImage *)image ByX:(int)x andY:(int)y
{// 数据监测if (x < 1 || y < 1 || ![image isKindOfClass:[UIImage class]]){return Nil;}CGFloat sWidth = self.view.frame.size.width;CGFloat sHeight = self.view.frame.size.height;CGFloat iWidth = image.size.width;CGFloat iHeight = image.size.height;// 图片大小适配(防止图片超过屏幕尺寸)if (iHeight > sHeight || iWidth > sWidth){CGFloat scala = MIN(sHeight/iHeight, sWidth/iWidth);iWidth = iWidth * scala;iHeight = iHeight * scala;}NSMutableArray *array = [NSMutableArray array];float resultX = iWidth * 1.0 / y;float resultY = iHeight * 1.0 / x;for (int i = 0; i < x; i++){for (int j = 0; j < y; j++){CGRect rect = CGRectMake(resultX*j, resultY*i, resultX, resultY);CGImageRef imageRef = CGImageCreateWithImageInRect([image CGImage],rect);UIImage* elementImage = [UIImage imageWithCGImage:imageRef];// 空白位if (i == 0 && j == 0){elementImage = nil;}PuzzleImageView *puzzleImageView=[[PuzzleImageView alloc] initWithImage:elementImage];puzzleImageView.resultIndex = i * x + j;puzzleImageView.nowIndex = i * x + j;puzzleImageView.delegate = self;puzzleImageView.frame = CGRectMake( 10+resultX * j,  150+resultY * i, resultX, resultY);[array addObject:puzzleImageView];}}return array;
}
//创建拼图所需的背景图,可将注释放开结合坐标更改,观察具体使用
-(UIView *) createPuzzleBoardViewWithFrame:(CGRect)rect
{UIView *view = [[UIView alloc]initWithFrame:rect];//view.backgroundColor = [UIColor grayColor];//遍历for (PuzzleImageView *pzView in self.array_ImageView){[view addSubview: pzView];}return view;
}// 打乱顺序
-(void)puzzleTheImage
{// 保持0位不动,否则奇偶性检查无效(需要提前对逆序数有所学习认识)//随机产生两个1~8之间的数字NSInteger aIndex = arc4random()%(self.array_ImageView.count - 1) + 1;PuzzleImageView *aView = [self.array_ImageView objectAtIndex:aIndex];NSInteger bIndex = arc4random()%(self.array_ImageView.count - 1) + 1;PuzzleImageView *bView = [self.array_ImageView objectAtIndex:bIndex];//交换随机产生的两个图片的 NowIndex[self exchangePuzzleFrameWithZero:aView And:bView withAnimation:NO];// 检查打乱是否完成,否则递归if (![self makePuzzleCanBeSolved] || ![self makePuzzleFinished]){[self puzzleTheImage];}else{// 游戏正式开始self.isStart = YES;}
}
// 检查无解
-(BOOL) makePuzzleCanBeSolved
{// 奇偶性总值NSInteger sum = 0;// 循环遍历(两层for循环计算的是逆序数值,知道逆序数的怎么计算的,就可以相应理解)for (NSInteger i = 0; i < self.array_ImageView.count; i++){PuzzleImageView *aView = [self.array_ImageView objectAtIndex:i];printf("--%d",aView.nowIndex);for (NSInteger j = i + 1; j < self.array_ImageView.count; j++){PuzzleImageView *bView = [self.array_ImageView objectAtIndex:j];// printf("b-- %d ",bView.nowIndex);// 逆序数检查if (aView.nowIndex > bView.nowIndex){sum ++;}}}// 根据逆序数奇偶性判断是否有解if ((sum % 2) == 0){return YES;}else{printf("无解\n");return NO;}
}
// 全部无序
-(BOOL) makePuzzleFinished
{BOOL flag = YES;//每个拼图进行一一比对for (PuzzleImageView *pzView in self.array_ImageView){if (pzView.resultIndex != 0 && pzView.resultIndex == pzView.nowIndex){printf("未全打乱\n");flag = NO;break;}}return flag;
}//拼图移动
-(void) puzzleImageViewShouldMove:(PuzzleImageView *)imageview
{PuzzleImageView *zeroPZ = [self.array_ImageView objectAtIndex:0];// 是否允许移动if ([imageview canMoveToPoint:zeroPZ.frame.origin]) {//交换[self exchangePuzzleFrameWithZero:zeroPZ And:imageview withAnimation:YES];}
}// 交换两个拼图视图
-(void)exchangePuzzleFrameWithZero:(PuzzleImageView *)zeroView And:(PuzzleImageView *)bView withAnimation:(BOOL)animation
{CGRect aRect = zeroView.frame;NSInteger aIndex = zeroView.nowIndex;[zeroView setFrame:bView.frame];[zeroView setNowIndex:bView.nowIndex];[bView setNowIndex:aIndex];if (animation) {[UIView animateWithDuration:0.4 delay:0.0 options:UIViewAnimationOptionCurveEaseInOut animations:^{[bView setFrame:aRect];} completion:Nil];}else{[bView setFrame:aRect];}if (self.isStart && [self gameComplete]){UIAlertView *alert = [[UIAlertView alloc]initWithTitle:@"恭喜" message:@"游戏完成!" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:Nil, nil];[alert show];}
}
// 完成退出
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{[self.navigationController popViewControllerAnimated:YES];
}
// 判断游戏完成
-(BOOL) gameComplete
{BOOL flag = YES;for (PuzzleImageView *pzView in self.array_ImageView){if (pzView.resultIndex != pzView.nowIndex){flag = NO;break;}}return flag;
}
@end

4:拼图视图控制器PuzzleViewController.h

//PuzzleViewController.h#import <UIKit/UIKit.h>
#import "PuzzleImageView.h"
#import <Foundation/Foundation.h>@interface PuzzleViewController : UIViewController <PuzzleDelegate, UIActionSheetDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate>@property (strong, nonatomic) NSMutableArray *array_ImageView;@property (strong, nonatomic) NSString *string_ImageName;@property (assign, nonatomic) BOOL isStart;@property (assign, nonatomic) NSInteger lvl;@property (strong, nonatomic) UIView *view_PuzzleBoard;@end

5: 菜单视图控制器MenuViewController.m

//  ViewController.m#import <Foundation/Foundation.h>#import "MenuViewController.h"
#import "PuzzleViewController.h"@interface MenuViewController ()@end@implementation MenuViewController- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];if (self) {}return self;
}- (void)viewDidLoad
{[super viewDidLoad];[self initData];
}- (void)didReceiveMemoryWarning
{[super didReceiveMemoryWarning];
}
//视图控制器更改,不同视图的跳转(点击Button时候跳转拼图页面)传入的是拼图阶。
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{UIViewController *vc = segue.destinationViewController;if ([vc isKindOfClass:[PuzzleViewController class]]){((PuzzleViewController *)vc).lvl = self.lvl;}
}// 初始化必要数据
-(void)initData
{self.title = @"菜单";self.lvl = 3;
}
//滑块值的更改处理
- (IBAction)sliderValueChange:(id)sender
{UISlider *slider = sender;if (slider.value < 4){self.lvl = 3;[slider setValue:3.0];self.label_lvl.text = @"简单";}else if (slider.value < 5){self.lvl = 4;[slider setValue:4.0];self.label_lvl.text = @"中等";}else if (slider.value > 4){self.lvl = 5;[slider setValue:5.0];self.label_lvl.text = @"困难";}
}
@end

6:菜单视图控制器MenuViewControlle.h

//MenuViewControlle.h#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>@interface MenuViewController : UIViewController@property (assign, nonatomic) NSInteger lvl;@property (strong, nonatomic) IBOutlet UILabel *label_lvl;- (IBAction)sliderValueChange:(id)sender;@end

四:主要函数解析

  1. -(void) initData:主要的功能是初始化拼图标题,以及指定图片名称。
  2. ByScalingToSize:(CGSize)targetSize:压缩图片,重新设置图片尺寸。
  3. -(NSMutableArray *) separateImage:根据不同的等级来对图片进行切割。(对切割好的图片设置好 两个下标Tag(nowIndex, resultIndex))用来最后判断拼图是否成功复位。
  4. -(void)puzzleTheImage: 打乱图块顺序
  5. -(BOOL) makePuzzleCanBeSolved:逆序数检查图片是否能复位即有解。
  6. -(BOOL) makePuzzleFinished:判断每个图块是否全部打乱,也是用来判断游戏是否复位成功的判断函数的实现。
  7. -(void)exchangePuzzleFrameWithZero:交换两个图块。并实时判断游戏是否成功结束。
  8. -(void) puzzleImageViewShouldMove:判断图块是否能与空白位进行移动。若可以则移动。

简单的介绍逆序数

  1. 拼图复位判断:循环遍历每个图块,看每个图片的当前下标nowIndex,是否与最初分块的下标值(resultIndex)相等,如果完全一致,表示拼图成功复位。
  2. 逆序数奇偶性判断有无解:对源状态A与目标状态B进行规范化,使得两矩阵的元素0(important)的位置相同;记为新的源状态A’与目标状态B’;

     1. 若A'与B'的逆序对的奇偶性相同(即A'与B1的逆序对的奇偶性相同),则A'必定可能转化为B',即A可以转化到B(从这一条性质知道,乱序的拼图是否能够有解); 2. 若A'与B'的逆序对的奇偶性不同(即A'与B2的逆序对的奇偶性相同),则A'必定不可能转化为B',即A不可以转化到B;
    

根据逆序数想关推论,以3*3为例,矩阵为

0 1 2 逆序数为0 是偶数
3 4 5 所以最后随机乱序的拼图 也应该是偶矩阵排列
6 7 8 逆序数的计算有线性代数知识点可知

逆序数计算的例子:
0 4 5
7 8 3
2 1 6
以 0 4 5 7 8 3 2 1 6 一一看起
4:比4小的值有 3 2 1 (三个)
5:比5小的值有 3 2 1 (三个)
7:比7小的值有 3 2 1 6 (四个)
8:比8小的值有 3 2 1 6 (四个)
2:比2小的值有 1(一个)
1:比1小的值有 (0个)
6:比6小的值显然..
三个+三个+四个+四个+一个= 15 判断一下 奇数。 与最出的偶数矩阵奇偶性不同。故乱序的拼图如果是这个矩阵,则无解。

代码仍需要在不断的学习中完善,带着怀疑的态度来思考(⊙_⊙)?。

360云盘代码(点击前先复制访问密码) 访问密码 1394

代码

基于IOS平台的游戏之小拼图相关推荐

  1. 基于IOS平台的游戏之打地鼠

    一. 题目描述 1.1游戏介绍 打地鼠是一款休闲游戏,游戏的规则也特别的简单,玩家只需要敲打一只只从地洞里冒出头的地鼠即可,游戏要求在限定的时间内,敲打的地鼠越多,分数越高,游戏画面比较清新,地鼠造型 ...

  2. java android 五子棋游戏_基于Android平台五子棋游戏最终版.doc

    基于Android平台五子棋游戏最终版 毕业设计(论文)任务书 毕业设计(论文)题目: 基于android平台的五子棋游戏的设计与实现 毕业设计(论文)要求及原始数据(资料): 1.综述国内基于and ...

  3. WEBRTC系列之基于IOS平台编译(一)

    Webrtc 系列文章: WEBRTC系列之基于IOS平台编译(一) WEBRTC系列之 AGC 算法原理初识(二) WEBRTC系列之 AGC 算法原理初识(三) WEBRTC系列之基于IOS平台编 ...

  4. 基于android平台的手机游戏的设计与实现,基于Android平台手机游戏社区的设计与实现...

    摘要: 在移动终端性能的不断提高和移动互联网的不断普及,SNS社区以及不再只停留在电脑上,逐渐的走进了手机里,与以往的社区相比,手机社区有更好的实时性,以及能够更方便的提供LBS服务功能.目前每个社区 ...

  5. 使用SDK快速接入各大平台快游戏 微信小游戏 QQ小游戏使用方法-附源码下载地址

    使用SDK快速接入各平台快游戏 微信小游戏 QQ小游戏 使用方法 引入SDK文件 // 该方式引入可以直接使用qgsdk<script src="qg-sdk.min.1.0.4.js ...

  6. 小米手机nfc能连电脑吗_基于ios平台小米手环5 NFC版体验报告

    2020年6月11日,小米手环5如期问世.作为2代和3代小米手环的用户,对新款小米手环还是十分期待的.从安卓转到ios,全功能NFC的缺失着实给生活带来些许不便.随着ios逐步开放城市公交卡的功能,我 ...

  7. iOS平台经典游戏《合金弹头X》上架 售价25元

    日本SNK Playmore株式会社正打算将<合金弹头>系列都移植到iOS平台上去.去年7月,他们首先在iOS平台上推出了<合金弹头3>.由于某些特殊的原因,他们在移植< ...

  8. 基于iOS平台配置免费离线语音识别功能-OpenEars

    用了半天时间弄明白了在iOS上如何配置语音识别功能,然后用半天时间写了一个demo,公司坑爹的是不用科大飞讯的语音识别,而使用的是OpenEars,用google查了一下最新的介绍文章是2013年的, ...

  9. 基于android平台unity3d游戏设计与实现,Unity3D微信小游戏平台的设计与实现毕业设计(论文)开题报告及工作计划书...

    四.主要参考文献 (8-10篇) [1]  朱玉.基于Unity3D漫游系统的设计与研究[J].信息安全与技术,2014,12:78-81 [2]  蒋元,蔡胜军,何绍勇,祁玮.基于Unity3D的虚 ...

最新文章

  1. 万航单位换算器 V1.0 绿色版
  2. linux文件的操作原理简介 以及 实现linux cp命令的代码
  3. 在Global Object Services (GOS) 中加入自定义项目
  4. Linux学习:gcc 编译其他常用参数
  5. 我在阿里招前端,我该怎么帮你?
  6. python网络安全工具箱界面_Python开发案例:设计启动工具箱,显示图形界面的方式...
  7. CSS3中的3D变换与简易立方体的制作
  8. 年夜饭之 -- 红烧黄鳝
  9. 电脑开机提示计算机无法启动不了,电脑无法启动并出现“System Halted”如何解决?...
  10. 解决方案-vector初始化后存放Mat,出现Mat矩阵数据同变问题
  11. 使用 MonoGame* 开发游戏
  12. 问题五十六:怎么用ray tracing画参数方程表示的曲面(3)—— b-spline surface
  13. 23.6. Functions
  14. ISIS 7 Professional运行报错解决方案
  15. 2021 年最佳开源软件榜单
  16. WFQ/CBWFQ/LLQ介绍
  17. 吉大网络教育护理学专升本病例分析
  18. Linux驱动——mmc bus浅析(五)
  19. 面试题——登录、支付功能测试点总结
  20. 盒子模型(CSS重点)

热门文章

  1. 忘记win10系统账户的登陆密码以及密保问题无法进入桌面时应该怎么拯救自己的电脑
  2. C# winform 登录 实现自动登录 和记住密码功能
  3. 你是不是特别想做好一个游戏主播?今天胖哥帮你开启一个新的大门
  4. xlrd方法excel
  5. CSDN,毕业生有话说!在如此疯狂的年代如何寻找自己的方向?迈向社会的第一步
  6. Android 11安装apk异常java.lang.SecurityException: Permission Denial:
  7. 类与结构体性能对比测试——以封装网络心跳包为例
  8. 软件测试基础知识-测试用例设计方法
  9. vncsever-centosdebian
  10. 张江地铁站OFFICE:最新职位:自动化测试、Linux_ QA Engineer、云计算技术开发、系统管理员、黑盒QA测试、多媒体QA测试...