OC版贪吃蛇
昨天写了一个js版贪吃蛇,今天突然想写一个OC版的,来对比一下两种语言的区别
oc版功能,适配所有尺寸iphone,可暂停,可设置地图和蛇的比例,可加速
对比一下会发现js版的相对OC版的会简单一些,有想看js版的可以看我上一篇随笔
程序中没用到任何素材,效果图如下:
github源码地址:https://github.com/masterChunlinHan/snake_OC

下面开始,跟js版一样,为了方便学习,所有代码都写在一个controller中,所以头文件中什么也不用写
#import <UIKit/UIKit.h> @interface ViewController : UIViewController @end
1,首先看需要定义的宏,和需要的全局变量,各个变量的含义都已经写在注释中
#import "ViewController.h"
#define SCREENWIDTH [UIScreen mainScreen].bounds.size.width//屏幕的高度
#define SCREENHEIGHT [UIScreen mainScreen].bounds.size.height//屏幕宽度
#define LINECOUNT 30 //地图上可显示的行数,这里规定地图是正方形,所以只需要一个数
#define BOXWIDTH SCREENHEIGHT/LINECOUNT //每格的宽度,既是食物的宽度也是每节蛇身的宽度 @interface ViewController ()
@property(nonatomic,strong)UIView *map;//地图只有一个,定义成全局的
@property(nonatomic,strong)UIView *food;//食物也只有一个
@property(nonatomic,assign)NSInteger foodx;//食物的x坐标,以格子的宽度为单位
@property(nonatomic,assign)NSInteger foody;//食物的y坐标
@property(nonatomic,strong)NSMutableArray *body;//蛇的身体是变化的,所以用一个可变数组来存
@property(nonatomic,strong)NSTimer *timer;//定时器
@property(nonatomic,assign)NSInteger directionCode;//定义一个数字来代表方向0,1,2,3分别代表上下左右
@property(nonatomic,assign)float time;//定时器的时间间隔,默认为0.5秒走一步
@end
2,一些初始化工作
@implementation ViewController
//初始化定时器的间隔
-(float)time{
if(!_time){
_time=0.5;
}
return _time;
}
//viewDidLoad中创建一些不会变的控件,这些控件始终只有一份,不需要创建第二次
- (void)viewDidLoad {
[super viewDidLoad];
//创建地图
[self createMap];
//添加重置按钮,默认进入程序不会立刻开始游戏,需要点击这个按钮才开始
[self createReloadButton];
//添加开始暂停按钮
[self createControlButtons];
//添加方向键
[self createDirectionButtons]; }
3,创建地图
-(void)createMap{
//先判断地图是否已经存在,如果存在就不再创建
if(!self.map){
self.map = [[UIView alloc]initWithFrame:CGRectMake(,, SCREENHEIGHT, SCREENHEIGHT)];
[self.view addSubview:self.map];
UIColor *lightColor = [UIColor colorWithRed:/255.0 green:/255.0 blue:/255.0 alpha:];
self.map.backgroundColor =lightColor;
self.map.center = self.view.center;
}
}
4,创建食物
//创建食物,每次刷新时都会调用这个方法
-(void)createFood{
//先判断食物是否已经存在,如果存在就不再创建
if(!self.food){
self.food = [[UIView alloc]initWithFrame:CGRectMake(,, BOXWIDTH, BOXWIDTH)];
UIColor *foodColor = [UIColor redColor];
self.food.backgroundColor = foodColor;
[self.map addSubview:self.food];
}
//每次刷新食物的坐标都是一个随机值
self.foodx = arc4random()%LINECOUNT;
self.foody = arc4random()%LINECOUNT;
self.food.frame = CGRectMake(self.foodx*BOXWIDTH, self.foody*BOXWIDTH, BOXWIDTH, BOXWIDTH); }
5,创建蛇
//创建蛇,每次刷新时先让蛇的身体坐标发生改变,再调用这个方法,让蛇重新显示
-(void)createSnake{
//先判断食物是否已经存在,如果存在就不再创建
if(!self.body){
//初始化蛇前进的方向为向右
self.directionCode = ;
//初始化蛇的身体,开始时只有一个头,两节身体,头为红色,身体为蓝色
self.body = [NSMutableArray arrayWithArray:@[
@{@"bodyx":@"",@"bodyy":@"",@"color":[UIColor redColor]},
@{@"bodyx":@"",@"bodyy":@"",@"color":[UIColor blueColor]},
@{@"bodyx":@"",@"bodyy":@"",@"color":[UIColor blueColor]}
]];
}
for (int i=; i<self.body.count; i++) {
NSMutableDictionary *mDic = [NSMutableDictionary dictionaryWithDictionary:self.body[i]];
UIView *body = mDic[@"body"];
if(!body){
body = [[UIView alloc]initWithFrame:CGRectMake(, , BOXWIDTH, BOXWIDTH)];
[self.map addSubview:body];
[mDic setObject:body forKey:@"body"];
} float bodyx =BOXWIDTH*[mDic[@"bodyx"] intValue];
float bodyy =BOXWIDTH*[mDic[@"bodyy"] intValue];
body.frame = CGRectMake(bodyx, bodyy, BOXWIDTH, BOXWIDTH);
body.backgroundColor = mDic[@"color"];
self.body[i] = mDic;
}
}
6,蛇移动的方法
//蛇移动,每次刷新时会在这个方法里改变蛇的坐标,并计算与食物的碰撞和自身的碰撞
-(void)snakeMove{ //设置蛇身
for(NSInteger i=self.body.count-;i>;i--){
NSMutableDictionary *mDic = [NSMutableDictionary dictionaryWithDictionary:self.body[i]];
NSString *bodyx = self.body[i-][@"bodyx"];
NSString *bodyy = self.body[i-][@"bodyy"];
[mDic setObject:bodyx forKey:@"bodyx"];
[mDic setObject:bodyy forKey:@"bodyy"];
self.body[i] = mDic;
}
//设置蛇头
NSMutableDictionary *mDic = [NSMutableDictionary dictionaryWithDictionary:self.body[]];
NSString *headx=mDic[@"bodyx"] ;
NSString *heady=mDic[@"bodyy"];
if(self.directionCode==){//上
heady = [NSString stringWithFormat:@"%d",[heady intValue]-];
}else if (self.directionCode==){//下
heady = [NSString stringWithFormat:@"%d",[heady intValue]+];
}else if (self.directionCode==){//左
headx = [NSString stringWithFormat:@"%d",[headx intValue]-];
}else if (self.directionCode==){//右
headx = [NSString stringWithFormat:@"%d",[headx intValue]+];
}
[mDic setObject:headx forKey:@"bodyx"];
[mDic setObject:heady forKey:@"bodyy"];
self.body[] = mDic;
//判断是否吃到食物
if([headx integerValue]==self.foodx&&[heady integerValue]==self.foody){
[self.body addObject:@{@"bodyx":@"-1",@"bodyy":@"",@"color":[UIColor blueColor]}];
if(self.time>0.25){
self.time-=0.05;
[self start];
// [self createTimer];
} [self createFood];
}
//判断是否撞到边界
if([headx integerValue]<||[headx integerValue]>LINECOUNT-||[heady intValue]<||[heady intValue]>LINECOUNT-){
// [self reload];
[self stop];
[self gameOver]; return; }
//判断是否撞到自己 [self createSnake];
}
7,创建计时器,因为创建计时器的工作和暂停之后继续游戏的方法功能一样,所以直接调用继续游戏的方法
//创建定时器
-(void)createTimer{
[self start];
}
继续游戏
//继续,这里创建定时器之前先销毁旧的计时器可以保证始终只有一个计时器在工作
-(void)start{
//如果不先销毁定时器,不断点击继续按钮会创建很多个定时器,会出现蛇跑很快的bug,
[self.timer invalidate];
self.timer = [NSTimer timerWithTimeInterval:self.time repeats:YES block:^(NSTimer * _Nonnull timer) {
[self snakeMove];
}];
[[NSRunLoop currentRunLoop]addTimer:self.timer forMode:NSDefaultRunLoopMode];
}
8,暂停游戏,只要将计时器销毁就行了
//暂停
-(void)stop{
[self.timer invalidate]; }
9,设置重置按钮方法,每一次执行(包括第一次)都会清空地图再创建蛇、食物、并重置计时器,所以第一次点击相当于开始游戏
//reload方法,执行之后一切重置,移除地图上的所有东西,并重新创建
-(void)reload{
self.body = nil;
for(UIView *subview in self.map.subviews){
if(subview!=self.food){
[subview removeFromSuperview];
}
}
[self createFood];
[self createSnake];
[self createTimer];
}
//创建重置按钮
-(void)createReloadButton{
UIButton *reloadBtn = [[UIButton alloc]initWithFrame:CGRectMake(, , (SCREENWIDTH-SCREENHEIGHT)/, SCREENHEIGHT/)];
[self.view addSubview:reloadBtn];
[reloadBtn setTitle:@"重置/开始" forState:UIControlStateNormal];
reloadBtn.backgroundColor = [UIColor orangeColor];
[reloadBtn addTarget:self action:@selector(reload) forControlEvents:UIControlEventTouchUpInside];
}
10,创建各种按键,在地图创建好之后就可以调用,因为有些按钮要相对于地图的位置来放置
//下面是创建各种按钮,就不多说了
//上下左右按键
-(void)createDirectionButtons{
// float btnW = (SCREENWIDTH-SCREENHEIGHT)/2;
//左边的方向键view
UIView *leftDirectionView = [[UIView alloc]initWithFrame:CGRectMake(, SCREENHEIGHT/, (SCREENWIDTH-SCREENHEIGHT)/, *SCREENHEIGHT/)];
[self.view addSubview:leftDirectionView];
//右边的方向键view
UIView *rightDirectionView = [[UIView alloc]initWithFrame:CGRectMake(CGRectGetMaxX(self.map.frame), SCREENHEIGHT/, (SCREENWIDTH-SCREENHEIGHT)/, *SCREENHEIGHT/)];
[self.view addSubview:rightDirectionView]; float btnH = *SCREENHEIGHT/;
for (int i=; i<; i++) {
NSString *title;
float x;
float y;
float w;
UIColor *backColor;
switch (i) {
case :
x = ;
y = ;
w = (SCREENWIDTH-SCREENHEIGHT)/;
title = @"上";
backColor = [UIColor redColor];
break;
case :
x = ;
y = *btnH;
w = (SCREENWIDTH-SCREENHEIGHT)/;
title = @"下";
backColor = [UIColor greenColor];
break;
case :
x = ;
y = btnH;
w = (SCREENWIDTH-SCREENHEIGHT)/;
title = @"左";
backColor = [UIColor grayColor];
break;
default:
x= (SCREENWIDTH-SCREENHEIGHT)/;
y=btnH;
w = (SCREENWIDTH-SCREENHEIGHT)/;
title=@"右";
backColor = [UIColor orangeColor];
break;
}
//左边的按钮
UIButton*btnLeft = [[UIButton alloc]initWithFrame:CGRectMake(x, y, w, btnH)];
btnLeft.tag = i;
[btnLeft setBackgroundColor:backColor];
[btnLeft setTitle:title forState:UIControlStateNormal];
[btnLeft addTarget:self action:@selector(directionChanged:) forControlEvents:UIControlEventTouchUpInside];
//右边的按钮
UIButton*btnRight = [[UIButton alloc]initWithFrame:CGRectMake(x, y, w, btnH)];
btnRight.tag = i;
[btnRight setBackgroundColor:backColor];
[btnRight setTitle:title forState:UIControlStateNormal];
[btnRight addTarget:self action:@selector(directionChanged:) forControlEvents:UIControlEventTouchUpInside]; [leftDirectionView addSubview:btnLeft];
[rightDirectionView addSubview:btnRight];
// [self.view addSubview:btn];
}
}
//点击方向按钮后让代表方向的全局变量改变,这样在蛇移动的方法中才能获取到
-(void)directionChanged:(UIButton*)btn{
self.directionCode = btn.tag;
// NSLog(@"%zd",btn.tag);
}
@end
OC版贪吃蛇的更多相关文章
- TOJ 3973 Maze Again && TOJ 3128 简单版贪吃蛇
TOJ3973传送门:http://acm.tzc.edu.cn/acmhome/problemdetail.do?&method=showdetail&id=3973 时间限制(普通 ...
- 如何用python制作贪吃蛇以及AI版贪吃蛇
用python制作普通贪吃蛇 哈喽,大家不知道是上午好还是中午好还是下午好还是晚上好! 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很 ...
- js版贪吃蛇
之前没有写博客的习惯,这是我的第一个博客,有些的不好的地方,希望大家多多提意见 js版的贪吃蛇相对比较简单,废话不多说直接上代码,有需要注意的地方我会标红,github源码地址https://gith ...
- JavaScript 实现简易版贪吃蛇(Day_13)
时光永远在变迁,你始终要丢下过去. 使用语言 JavaScript 概述 运用JavaScript 实现简易版<贪吃蛇>. Html 页面 1 <!DOCTYPE htm ...
- Javascript基础示例:用JS写简易版贪吃蛇(面向对象)
废话不多说,代码如下: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> & ...
- JavaScript版—贪吃蛇小组件
最近在学习JavaScript,利用2周的时间看完了<JavaScript高级编程>,了解了Js是一门面向原型编程的语言,没有像C#语言中的class,也没有私有.公有.保护等访问限制的级 ...
- Winfrom 极简版贪吃蛇源码
该源码是我在百度知识库借助前辈的的经验,加上自己的一点小改动写的一个非常简陋的贪吃蛇小程序.如果你们有更好的改动方案,欢迎评论. 进入主题吧! 1.创建一个桌面应运程序,拖一个定时器控件.这样,程序界 ...
- 用GUI实现java版贪吃蛇小游戏
项目结构 新建一个JFrame窗口,作为程序入口 public class GameStart{ public static void main(String[] args) { JFrame jFr ...
- c语言版贪吃蛇小游戏
编译环境:windows 7 64位 编译工具:codeblocks 13.12 备注:未使用graphics.h 声明:个人原创,未经允许,禁止转载!!! 数据结构:双向链表 1.程序未使用grap ...
随机推荐
- 如何将md文件转换成带目录的html文件
配置环境node 去官网下一个node安装包,下一步下一步: 由于现在的node都自带npm,直接 npm install i5ting_toc 这样安装好了i5ting_toc这个包, 进入你实现准 ...
- acm->stl
容器 queue 队列 定义 queue的定义需要两个参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque类型 基本方法 push(x) 入队,将x接到队列的末端 ...
- java数组排序(冒泡、直排)反转
package lianxi; public class maopao { public static void main(String[] args){ int[] i=new int[]{45,6 ...
- [C++ Calculator 项目] 文件读入与可视化实现
Calculator V1.1 注:这是C++计算器项目第三.四部分-文件读写与可视化 [基于原代码重构而得] 源文件已上传至Github 文件读写 可视化 文件读写: Ⅰ.在原基础代码上增加了-f参 ...
- Hybris商品图片导入与压缩有关的配置
1. 在电脑上安装 ImageMagick 软件(windows平台还需要安装VC++),下载路径:http://www.imagemagick.org/script/download.php#w ...
- Actor模型原理
1.Actor模型 在使用Java进行并发编程时需要特别的关注锁和内存原子性等一系列线程问题,而Actor模型内部的状态由它自己维护即它内部数据只能由它自己修改(通过消息传递来进行状态修改),所以使用 ...
- Nginx文档-初学者指南
原文档: http://nginx.org/en/docs/beginners_guide.html 译者:Oopsguy 本指南旨在介绍nginx基本内容和一些在Nginx上可以完成的简单任务.这里 ...
- (转)IBM MQ 创建以及常见问题集锦
背景:这篇文章还是很全面的,但是很杂乱 后面慢慢整理吧! 1 MQ 消息队列+发送队列+消息通道 接收通道名称与发送端的发送通道名称要一致,修改通道信息后要执行 start channle(chlna ...
- (转)Synchronized(对象锁)和Static Synchronized(类锁)的区别
场景:面试的时候经常用得到! 1 综述 Synchronized和Static Synchronized区别 一个是实例锁(锁在某一个实例对象上,如果该类是单例,那么该锁也具有全局锁的概念),一个是全 ...
- Java以及PHP安装环境
开学前想把web的知识系统掌握一下,跟着极客学院学html5. 安装了intellij idead.xampp.jdk.eclipse for php. 下面列举一些安装过程中会出现的问题,以及解决. ...