2019独角兽企业重金招聘Python工程师标准>>>

iOS简易蓝牙对战五子棋游戏设计思路之二——核心棋盘逻辑与胜负判定算法

一、引言

上一篇博客我们介绍了在开发一款蓝牙对战五子棋游戏中核心的蓝牙通讯框架的设计与编写,本篇博客将来完成独立的棋盘逻辑与胜负判定算法。上篇博客地址如下:

五子棋游戏中和核心通讯类设计:http://my.oschina.net/u/2340880/blog/644432。

二、棋盘中独立棋格的设计

我们知道,五子棋游戏的棋盘是由横纵交叉的两组平行线组成,每一个横纵线的交点即是棋盘上可以落子的点。因此,在设计棋盘前,我们可以先来设计创建棋盘上每一个独立的落子点,这里称之为棋格,在iOS中,可以使用UIButton类来进行棋格的设计。

创建一个类,命名为TipButton作为棋格类,实现其头文件如下:

TipButton.h

#import <UIKit/UIKit.h>
@interface TipButton : UIButton
//标记此瓦片是否已经落子 0 空 1 己方落子 2 敌方落子
@property(nonatomic,assign)int hasChess;
//落子 BOOL类型的参数 决定是己方还是敌方
-(void)dropChess:(BOOL)isMine;
//设置白子或者黑子
@property(nonatomic,assign)BOOL isWhite;
//瓦片编号
@property(nonatomic,assign)int index;
@end

实现.m文件如下:

#import "TipButton.h"
@implementation TipButton
- (instancetype)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {[self creatView];}return self;
}
-(void)creatView{//创建横竖两条线UIView * line1 = [[UIView alloc]initWithFrame:CGRectMake(self.frame.size.width/2-0.25, 0, 0.5, self.frame.size.height)];line1.backgroundColor = [UIColor grayColor];[self addSubview:line1];UIView * line2 = [[UIView alloc]initWithFrame:CGRectMake(0, self.frame.size.height/2-0.25, self.frame.size.width, 0.5)];line2.backgroundColor = [UIColor grayColor];[self addSubview:line2];
}-(void)dropChess:(BOOL)isMine{UIView * view = [[UIView alloc]initWithFrame:CGRectMake(self.frame.size.width/2-5, self.frame.size.height/2-5, 10, 10)];view.layer.masksToBounds = YES;view.layer.cornerRadius = 5;UIColor * myColor;UIColor * otherColor;if (_isWhite) {myColor = [UIColor whiteColor];otherColor = [UIColor blackColor];}else{myColor = [UIColor blackColor];otherColor = [UIColor whiteColor];}if (isMine) {view.backgroundColor = myColor;self.hasChess = 1;}else{view.backgroundColor = otherColor;self.hasChess = 2;}[self addSubview:view];}
@end

三、游戏棋盘的设计

创建一个继承于UIView的类,作为五子棋游戏的棋盘,命名为GameView实现如下:

GameView.h

#import <UIKit/UIKit.h>
#import "TipButton.h"
#import "BlueToothTool.h"
//用于处理用户下子后的逻辑
@protocol GameViewDelegate<NSObject>
-(void)gameViewClick:(NSString *)index;
@end
@interface GameView : UIView<UIAlertViewDelegate>
//存放所有棋格
@property(nonatomic,strong)NSMutableArray<TipButton *> * tipArray;
@property(nonatomic,weak)id<GameViewDelegate>delegate;
//进行下子
-(void)setTipIndex:(int)index;
@end

GameView.m

#import "GameView.h"
@implementation GameView
- (instancetype)initWithFrame:(CGRect)frame
{self = [super initWithFrame:frame];if (self) {_tipArray = [[NSMutableArray alloc]init];[self creatView];}return self;
}
//创建表格视图 横16 竖20
-(void)creatView{self.layer.borderColor = [UIColor colorWithRed:222/255.0 green:222/255.0 blue:222/255.0 alpha:1].CGColor;self.layer.borderWidth = 0.5;CGFloat width = self.frame.size.width/12;CGFloat height = self.frame.size.height/20;//排列布局for (int i=0; i<240; i++) {TipButton * btn = [[TipButton alloc]initWithFrame:CGRectMake(width*(i%12), height*(i/12), width, height)];[btn addTarget:self action:@selector(click:) forControlEvents:UIControlEventTouchUpInside];btn.isWhite = NO;btn.index=i;[self addSubview:btn];[_tipArray addObject:btn];}
}
-(void)click:(TipButton *)btn{if (btn.hasChess==0) {//下子[btn dropChess:YES];//进行胜负判定[self cheak];[self.delegate gameViewClick:[NSString stringWithFormat:@"%d",btn.index]];}
}
//进行胜负判定
-(void)cheak{//判定己方是否胜利if ([self cheakMine]) {UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"您胜利啦" message:@"" delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil];[alert show];}//判断对方是否胜利if ([self cheakOther]) {UIAlertView * alert = [[UIAlertView alloc]initWithTitle:@"您失败了" message:@"" delegate:self cancelButtonTitle:@"好的" otherButtonTitles:nil, nil];[alert show];}
}
-(void)setTipIndex:(int)index{//下子for (TipButton * btn in _tipArray) {if (btn.index==index) {[btn dropChess:NO];[self cheak];}}
}
-(BOOL)cheakOther{//遍历所有棋子for (int i=0; i<_tipArray.count; i++) {TipButton * tip = _tipArray[i];//获取是否是己方棋子if (tip.hasChess==2) {//进行五子判定逻辑//横向if ( [self cheak1HasMineOrOther:NO index:i]) {return YES;}//左上到右下的对角线if ( [self cheak2HasMineOrOther:NO index:i]) {return YES;}//纵向if ( [self cheak3HasMineOrOther:NO index:i]) {return YES;}//右上到左下的对角线if ( [self cheak4HasMineOrOther:NO index:i]) {return YES;}}}return NO;}-(BOOL)cheakMine{//遍历所有棋子for (int i=0; i<_tipArray.count; i++) {TipButton * tip = _tipArray[i];//获取是否是己方棋子if (tip.hasChess==1) {//进行五子判定逻辑//横向if ( [self cheak1HasMineOrOther:YES index:i]) {return YES;}//左上到右下的对角线if ( [self cheak2HasMineOrOther:YES index:i]) {return YES;}//纵向if ( [self cheak3HasMineOrOther:YES index:i]) {return YES;}//右上到左下的对角线if ( [self cheak4HasMineOrOther:YES index:i]) {return YES;}}}return NO;
}-(BOOL)cheak1HasMineOrOther:(BOOL)mine index:(int)index{int mineOrOther = 0;if (mine) {mineOrOther = 1;}else{mineOrOther = 2;}int count=1;//左侧右侧同时进行可以增加效率//左侧count = count +[self algorithmic1:index param:mineOrOther num:4];//右侧count = count +[self algorithmic2:index param:mineOrOther num:4];if (count>=5) {return YES;}else{return NO;}
}-(BOOL)cheak2HasMineOrOther:(BOOL)mine index:(int)index{int mineOrOther = 0;if (mine) {mineOrOther = 1;}else{mineOrOther = 2;}int count=1;//左上右下同时进行可以增加效率//左上count = count +[self algorithmic3:index param:mineOrOther num:4];//右下count = count +[self algorithmic4:index param:mineOrOther num:4];if (count>=5) {return YES;}else{return NO;}
}-(BOOL)cheak3HasMineOrOther:(BOOL)mine index:(int)index{int mineOrOther = 0;if (mine) {mineOrOther = 1;}else{mineOrOther = 2;}int count=1;//纵向//向上count = count +[self algorithmic5:index param:mineOrOther num:4];//向下count = count +[self algorithmic6:index param:mineOrOther num:4];if (count>=5) {return YES;}else{return NO;}
}
-(BOOL)cheak4HasMineOrOther:(BOOL)mine index:(int)index{int mineOrOther = 0;if (mine) {mineOrOther = 1;}else{mineOrOther = 2;}int count=1;//纵向//向上count = count +[self algorithmic7:index param:mineOrOther num:4];//向下count = count +[self algorithmic8:index param:mineOrOther num:4];NSLog(@"%d",count);if (count>=5) {return YES;}else{return NO;}
}/*左侧递归进行查找 index 棋子编号 param 对比值 num 递归次数*/
-(int)algorithmic1:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//左侧有子if (index-tem>=0) {//左侧无换行if(((index-tem)%12)!=11){if (_tipArray[index-tem].hasChess==param) {return  [self algorithmic1:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}
/*右侧递归进行查找 index 棋子编号 param 对比值 num 递归次数*/
-(int)algorithmic2:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//右侧有子if (index+tem<240) {//右侧无换行if(((index+tem)%12)!=11){if (_tipArray[index+tem].hasChess==param) {return  [self algorithmic2:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}/*左上递归进行查找 index 棋子编号 param 对比值 num 递归次数*/
-(int)algorithmic3:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//左上有子if ((index-(tem*12)-tem)>=0) {//右侧无换行if(((index-(tem*12)-tem)%12)!=11){if (_tipArray[(index-(tem*12)-tem)].hasChess==param) {return  [self algorithmic3:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}-(int)algorithmic4:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//左上有子if ((index+(tem*12)+tem)<240) {//右侧无换行if(((index+(tem*12)+tem)%12)!=0){if (_tipArray[(index+(tem*12)+tem)].hasChess==param) {return  [self algorithmic4:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}-(int)algorithmic5:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//上有子if ((index-(tem*12))>=0) {if (_tipArray[(index-(tem*12))].hasChess==param) {return  [self algorithmic5:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}-(int)algorithmic6:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//上有子if ((index+(tem*12))<240) {if (_tipArray[(index+(tem*12))].hasChess==param) {return  [self algorithmic6:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}
-(int)algorithmic7:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//左上有子if ((index-(tem*12)+tem)>=0) {//右侧无换行if(((index-(tem*12)+tem)%12)!=0){if (_tipArray[(index-(tem*12)+tem)].hasChess==param) {return  [self algorithmic7:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}-(int)algorithmic8:(int)index param:(int)param num:(int)num{if (num>0) {int tem = 4-(num-1);//左上有子if ((index+(tem*12)-tem)<240) {//右侧无换行if(((index+(tem*12)-tem)%12)!=11){if (_tipArray[(index+(tem*12)-tem)].hasChess==param) {return  [self algorithmic8:index param:param num:num-1];}else{return 4-num;}}else{return 4-num;}}else{return 4-num;}}else{//递归了四次return 4-num;}
}
-(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{[[BlueToothTool sharedManager]disConnect];[(UIViewController *)[self.superview nextResponder] dismissViewControllerAnimated:YES completion:nil];
}
@end

关于胜负判定的算法逻辑,这里采用了向各个方向进行递归查找的方式,这里有一点需要主要,在4个方向进行递归查找时,理论上每个方向只需要单面递归即可,但是代码中采用了双面递归在进行累加的方式,这样的设计可以遍历更少的棋子判定出胜负情况。

四、整合通讯与游戏逻辑

创建一个继承于UIViewController的类作为游戏视图控制器,实现如下:

GameViewController.m

#import "GameViewController.h"
#import "GameView.h"
#import "BlueToothTool.h"
@interface GameViewController ()<BlueToothToolDelegate,GameViewDelegate>
{UIView * _bgView;UILabel * _tipLabel;GameView * _view;
}
@end@implementation GameViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor brownColor];//创建游戏视图_view = [[GameView alloc]initWithFrame:CGRectMake(20, 40, (self.view.frame.size.width-40), (self.view.frame.size.width-40)/12*20)];_view.delegate=self;[self.view addSubview:_view];//创建背景视图_bgView = [[UIView alloc]initWithFrame:self.view.frame];_bgView.backgroundColor = [UIColor colorWithRed:1 green:1 blue:1 alpha:0.1];UIButton * btn = [UIButton buttonWithType:UIButtonTypeSystem];btn.frame = CGRectMake(self.view.frame.size.width/2-50, 150, 100, 30);UIButton * btn2 = [UIButton buttonWithType:UIButtonTypeSystem];btn2.frame = CGRectMake(self.view.frame.size.width/2-50, 250, 100, 30);[btn setTitle:@"创建游戏" forState:UIControlStateNormal];[btn2 setTitle:@"扫描附近游戏" forState:UIControlStateNormal];btn.backgroundColor = [UIColor orangeColor];btn2.backgroundColor = [UIColor orangeColor];[btn addTarget:self action:@selector(creatGame) forControlEvents:UIControlEventTouchUpInside];[btn2 addTarget:self action:@selector(searchGame) forControlEvents:UIControlEventTouchUpInside];[_bgView addSubview:btn];[_bgView addSubview:btn2];[self.view addSubview:_bgView];//设置蓝牙通讯类代理[BlueToothTool sharedManager].delegate=self;//创建提示标签_tipLabel = [[UILabel alloc]initWithFrame:CGRectMake(0, 0, self.view.frame.size.width,40)];[self.view addSubview:_tipLabel];_tipLabel.textAlignment = NSTextAlignmentCenter;
}
-(void)creatGame{[[BlueToothTool sharedManager]setUpGame:@"" block:^(BOOL first) {[_bgView removeFromSuperview];if (first) {_tipLabel.text = @"请您下子";//进行发送下子信息}else{_tipLabel.text = @"请等待对方下子";self.view.userInteractionEnabled = NO;[self gameViewClick:@"-1"];}}];
}
-(void)searchGame{[[BlueToothTool sharedManager]searchGame];
}
- (void)didReceiveMemoryWarning {[super didReceiveMemoryWarning];// Dispose of any resources that can be recreated.
}
-(void)getData:(NSString *)data{if (_bgView.superview) {[_bgView removeFromSuperview];}if ([data integerValue]==-1) {_tipLabel.text = @"请您下子";self.view.userInteractionEnabled = YES;return;}_tipLabel.text = @"请您下子";[_view setTipIndex:[data intValue]];self.view.userInteractionEnabled = YES;
}-(void)gameViewClick:(NSString *)index{_tipLabel.text = @"请等待对方下子";[[BlueToothTool sharedManager]writeData:index];self.view.userInteractionEnabled = NO;
}
@end

游戏运行的主要界面如下图所示:

附录:游戏的源码已经放在git上,时间比较仓促,只用了一下午来写,其中还有许多细节与bug没有进行调整,有需要的可以作为参考:

git地址:https://github.com/ZYHshao/BlueGame。

专注技术,热爱生活,交流技术,也做朋友。

——珲少 QQ群:203317592

转载于:https://my.oschina.net/u/2340880/blog/644438

iOS简易蓝牙对战五子棋游戏设计思路之二——核心棋盘逻辑与胜负判定算法相关推荐

  1. iOS简易蓝牙对战五子棋游戏设计思路之一——核心蓝牙通讯类的设计

    iOS简易蓝牙对战五子棋游戏设计思路之一--核心蓝牙通讯类的设计 一.引言 本系列博客将系统的介绍一款蓝牙对战五子棋的开发思路与过程,其中的核心部分有两个,一部分是蓝牙通讯中对战双方信息交互框架的设计 ...

  2. 特别提醒蓝牙语音智能药盒的设计思路(二)TTS技术应用篇,附手机小程序界面

    全文3000字,阅读时间约8分钟,建议收藏后慢慢看 目录 引言 蓝牙TTS智能药盒方案系统图 智能药盒是什么 智能药盒为什么需要语音提醒 语音提醒功能为什么要用TTS技术 TTS语音提醒的应用场景 1 ...

  3. android五子棋设计模板,基于android的五子棋游戏设计

    内容介绍 原文档由会员 hfnmb 发布 基于Android的五子棋游戏设计 软件工程 [摘 要]本论文主要阐述以面向对象的程序开发语言eclipse为开发工具, 基于智能手机Android之上设计一 ...

  4. ​基于STM32F407的五子棋游戏设计​

    本博客为资源:基于STM32F407的五子棋游戏设计内的说明文档. 目录 一.设计目标 三.设计方案 1.游戏模式 2.游戏过程 3.游戏设计 四.硬件配置 1.TFT-LCD液晶屏模块 (1)工作原 ...

  5. 基于安卓Android的五子棋游戏设计与实现

    下载地址 本论文主要阐述以面向对象的程序开发语言,Eclipse为开发工具, 基于智能手机Android系统之上设计的一个五子棋游戏.五子棋起源于中国古代的传统黑白棋种之一,它不仅能增强思维能力提高智 ...

  6. 五子棋游戏设计VHDL语言

    本设计实现五子棋游戏设计,使用VHDL语言 quartusII 或者 vivado均可 通过VGA显示实时的棋盘,双方可以通过按键来控制黑棋和白棋的位置,实现五子棋游戏的功能. 开始和胜利的界面如下: ...

  7. 【181018】VC++ 网络对战五子棋游戏(服务端+用户端)

    VC++ 网络对战五子棋游戏(服务端+客户端),编译后先开启服务器端,服务端管理着各个用户之间的数据传递,用户端是多个的.就像游戏大厅一样.用户登录了后服务端将向用户端发送当前所有在线玩家列表数据.由 ...

  8. C++毕业设计——基于C+++EasyX+剪枝算法的能人机对弈的五子棋游戏设计与实现(毕业论文+程序源码)——五子棋游戏

    基于C+++EasyX+剪枝算法的能人机对弈的五子棋游戏设计与实现(毕业论文+程序源码) 大家好,今天给大家介绍基于C+++EasyX+剪枝算法的能人机对弈的五子棋游戏设计与实现,文章末尾附有本毕业设 ...

  9. 常见游戏设计思路及手法

    常见游戏设计思路及手法 从设计的角度来看,任何体验都是已经被"计划"好的.但是游戏的结果,可能是一个概率事件,而这种概率事件也是体验的一部分. 游戏的类型 游戏有很多的类型,比如& ...

最新文章

  1. CF1398D Colored Rectangles (记忆化搜索DP)
  2. ASP.NET 2.0 正式版中无刷新页面的开发
  3. Windows编程---------MessageBox
  4. ubuntu锁定mysql到任务栏_ubuntu16.04与mysql的运维注意事项
  5. hdu 3339 In Action 背包+flyod
  6. 瑞士轮(洛谷-P1309)
  7. 如何实现响应式布局?
  8. sublime c语言如何编译,Sublime Text 3 实现C语言代码的编译和运行(示例讲解)
  9. 菜鸟学Linux 第093篇笔记 keepalived
  10. 【译】采用微前端架构
  11. CopyU!v2 已经收录到腾讯软件管家!
  12. Visual Studio内存泄露检测工具
  13. Xamarin.Android之绑定库教程
  14. matlab模拟风场竖桥向时程,大跨度桥梁三维脉动风场的计算机模拟
  15. Notepad++ 设置tab为N个空格
  16. 【技术人快报】摩拜单车多地区现Bug+iCloud完成中国本土化落地
  17. 学习笔记(97):R语言入门基础-pairs绘图
  18. 中山大学南方学院计算机专业分数线,中山大学南方学院历年录取分数线多少及各省最低投档线统计表...
  19. 计量大学计算机学院,计算机科学与技术
  20. CreateProcess创建一个隐藏进程

热门文章

  1. 【新的开始】记录每天背的单词,准备考研。(6月7日)
  2. amd锐龙笔记本cpu怎么样_锐龙酷睿谁更适合你?轻薄本处理器天梯图见分晓
  3. UC浏览器版爱情买卖
  4. RPC-BDY(4)-nacos注册中心
  5. echarts的X轴文字倾斜显示、竖向显示、上下错开显示
  6. cc2540 cc2541 开发板资料更新日志
  7. c8051f340定时器2中断以及初值设置
  8. 【VBS教程】 VBS能够干什么
  9. Opencv判断颜色相似的图片
  10. 应聘Java笔试时可能出现问题及其答案