Gomoku五子棋OC实现
2015-10-29 13:19
507 查看
最近有朋友在学习UI,想制作一个简单的五子棋来练手,但不知道思路,我就写了一个五子棋来作为引导吧。
提到五子棋,首先就是得考虑到一个棋盘的问题,由于朋友是初学UI,所以在棋盘布局上就是用了view的方法创建了棋盘,tableView等方法应该会更好一些,感兴趣的朋友可以去学习学习相关知识。五子棋是15 x 15的布局,代码实现如下
实际效果如图
![](http://img.blog.csdn.net/20151029134346546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
有了棋盘之后就是落子的问题,实际上,本程序采用的并不是真正意义上得“落子”,而是在每个可以落子的点预设了没有初始化颜色的button,通过button点击事件来改变button的颜色,达到实际落子的效果,预设棋子代码如下
如果为黑子,则为“black”,如果没有子,则为“empty”, 说明该处可以放置棋子 ,根据放置棋子的颜色,向用于存储棋盘棋子信息的可变数组_dataSource传值,代码实现如下
至此,游戏的判断功能也有了,但是在一方获胜之后程序依旧能够继续执行,需要对游戏结束做一个控制,这里用的是将所有棋子信息都改成了获胜子的信息,代码如下
提到五子棋,首先就是得考虑到一个棋盘的问题,由于朋友是初学UI,所以在棋盘布局上就是用了view的方法创建了棋盘,tableView等方法应该会更好一些,感兴趣的朋友可以去学习学习相关知识。五子棋是15 x 15的布局,代码实现如下
for (int i = 0; i < 15; i++) { UIView *view = [[UIView alloc] initWithFrame:CGRectMake(45, 100 + i * 20, 280, 1)]; view.backgroundColor = [UIColor blackColor]; [self.view addSubview:view]; [view release]; for (int j = 0; j < 15; j++) { UIView *view = [[UIView alloc] initWithFrame:CGRectMake(45 + j * 20, 100, 1, 280)]; view.backgroundColor = [UIColor blackColor]; [self.view addSubview:view]; [view release]; } }
实际效果如图
有了棋盘之后就是落子的问题,实际上,本程序采用的并不是真正意义上得“落子”,而是在每个可以落子的点预设了没有初始化颜色的button,通过button点击事件来改变button的颜色,达到实际落子的效果,预设棋子代码如下
// 预设棋子 for (int i = 0 ; i < 15; i++) { for (int j = 0; j < 15; j++) { UIButton *chess = [UIButton buttonWithType:UIButtonTypeSystem]; chess.frame = CGRectMake(45 + 20 * j, 100 + 20 * i, 18, 18); chess.center = CGPointMake(45 + 20 * j, 100 + 20 * i); chess.layer.cornerRadius = 9; chess.layer.masksToBounds = YES; [chess addTarget:self action:@selector(playChess:) forControlEvents:UIControlEventTouchUpInside]; [self.view addSubview:chess]; [chess release]; [_dataSource addObject:@"empty"]; } }该程序没有使用自定义视图,但是吧每个棋子需要有自己的属性,也就是“没被点击empty”, “黑子black”, 和“白子white”, 这些属性我通过创建一个可变数组_dataSource的属性来存储,方便管理。同时,五子棋还需判断当前回合是黑子还是白子的回合,我定义了一个flag属性来标记回合。基本逻辑是当点击某个落子点的时候,如果该落子点有白子,则该落子点为“white”,
如果为黑子,则为“black”,如果没有子,则为“empty”, 说明该处可以放置棋子 ,根据放置棋子的颜色,向用于存储棋盘棋子信息的可变数组_dataSource传值,代码实现如下
if (_flag) { sender.backgroundColor = [UIColor blackColor]; [_dataSource replaceObjectAtIndex:(15 * y + x) withObject:@"black"]; _labelTurn.text = @"white turn"; } else { sender.backgroundColor = [UIColor whiteColor]; [_dataSource replaceObjectAtIndex:(15 * y + x) withObject:@"white"]; _labelTurn.text = @"black turn"; } _flag = !_flag;至此,基本的棋盘和落子功能已经实现了,现在需要判断的是赢得比赛的逻辑。一个比较通行的方法是每次落子完成后对这个数组横向,纵向,斜向四个方向分别遍历,找到至少五个值相同的即为获胜,返回数组内存储的值即可。在这里,每次落子都遍历数组效率太低,考虑每次落子对该子周围的棋子进行遍历,提高程序效率,代码如下
// 向右 int xRight = x + 1; int yRight = y; int countRight = 0; while ([_dataSource[15 * yRight + xRight] isEqualToString:_dataSource[15 * y + x]]) { countRight++; xRight++; if (xRight >= 15) { break; } } // 左上 int xLeftUp = x - 1; int yLeftUp = y - 1; int countLeftUp = 0; while ([_dataSource[15 * yLeftUp + xLeftUp] isEqualToString:_dataSource[15 * y + x]]) { countLeftUp++; xLeftUp--; yLeftUp--; if (xLeftUp < 0 || yLeftUp < 0) { break; } } // 右下 int xRightDown = x + 1; int yRightDown = y + 1; int countRightDown = 0; while ([_dataSource[15 * yRightDown + xRightDown] isEqualToString:_dataSource[15 * y + x]]) { countRightDown++; xRightDown++; yRightDown++; if (xRightDown >= 15 || yRightDown >= 15) { break; } } // 右上 int xRightUp = x + 1; int yRightUp = y - 1; int countRightUp = 0; while ([_dataSource[15 * yRightUp + xRightUp] isEqualToString:_dataSource[15 * y + x]]) { countRightUp++; xRightUp++; yRightUp--; if (xRightUp >= 15 || yRightUp < 0) { break; } } // 左下 int xLeftDown = x - 1; int yLeftDown = y + 1; int countLeftDown = 0; while ([_dataSource[15 * yLeftDown + xLeftDown] isEqualToString:_dataSource[15 * y + x]]) { countLeftDown++; xLeftDown--; yLeftDown++; if (xLeftDown < 0 || yLeftDown >= 15) { break; } } // 判断输赢 if ((countUp + countDown >= 4) || (countLeft + countRight >= 4) || (countLeftDown + countRightUp >= 4) || (countRightDown + countLeftUp >= 4)) { NSLog(@"%@ win", _dataSource[15 * y + x]); _labelWin.text = [_dataSource[15 * y + x] stringByAppendingString:@" win"];当然,可以考虑使用递归来获取count,有兴趣的朋友可以自己尝试。
至此,游戏的判断功能也有了,但是在一方获胜之后程序依旧能够继续执行,需要对游戏结束做一个控制,这里用的是将所有棋子信息都改成了获胜子的信息,代码如下
// 游戏结束后不再能够落子 for (int i = 0; i < 225; i++) { [_dataSource replaceObjectAtIndex:i withObject:_labelWin.text]; }
相关文章推荐
- golang反射与反射三法则
- HDU_3666_THE MATRIX PROBLEM(差分约束+spfa+slf优化)
- Algorithms—68.Text Justification
- django modeForm总结!
- 收藏的兼容各浏览器的日历控件(ie6-11\ff\google\safri)
- django models 晋级
- django rest framework - 数据解析
- Sublime Text3 + Golang搭建开发环境
- jango.contrib.sessions-SessionBase
- django.session-middleware
- django-admin sites
- django.core-validators
- django.forms.widget-ChoiceFieldRenderer
- django.forms.widget-ChoiceInput
- Hello,Algorithm!(你好,算法!)
- django.forms-Widget和Media间的联系
- dajngo.forms.widget-Media
- django signal 拾遗
- Proof for Floyd-Warshall's Shortest Path Derivation Algorithm Also Demonstrates the Hierarchical Path Construction Process
- django.relatedField-关联域