先上效果图
- 功能展示

- 初高级棋盘切换效果

实现思路及主要代码详解
1.绘制棋盘
利用quartz2d绘制棋盘.代码如下
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
- (void)drawbackground:(cgsize)size{
self.gridwidth = (size.width - 2 * kboardspace) / self.gridcount;
//1.开启图像上下文
uigraphicsbeginimagecontext(size);
//2.获取上下文
cgcontextref ctx = uigraphicsgetcurrentcontext();
cgcontextsetlinewidth(ctx, 0.8f);
//3.1 画16条竖线
for (int i = 0; i <= self.gridcount; i ++) {
cgcontextmovetopoint(ctx, kboardspace + i * self.gridwidth , kboardspace);
cgcontextaddlinetopoint(ctx, kboardspace + i * self.gridwidth , kboardspace + self.gridcount * self.gridwidth);
}
//3.1 画16条横线
for (int i = 0; i <= self.gridcount; i ++) {
cgcontextmovetopoint(ctx, kboardspace, kboardspace + i * self.gridwidth );
cgcontextaddlinetopoint(ctx, kboardspace + self.gridcount * self.gridwidth , kboardspace + i * self.gridwidth);
}
cgcontextstrokepath(ctx);
//4.获取生成的图片
uiimage *image=uigraphicsgetimagefromcurrentimagecontext();
//5.显示生成的图片到imageview
uiimageview * imageview = [[uiimageview alloc]initwithimage:image];
[self addsubview:imageview];
uigraphicsendimagecontext();
}
|
2.点击棋盘落子
1)根据落子位置求出该棋子的行号与列号.
2)判断落子位置是否已经有棋子,有则不能下.如果没有,将棋子保存在字典中,以列号和行号组合起来的字符串为key值.
代码如下:
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
//点击棋盘,下棋
- (void)tapboard:(uitapgesturerecognizer *)tap{
cgpoint point = [tap locationinview:tap.view];
//计算下子的列号行号
nsinteger col = (point.x - kboardspace + 0.5 * self.gridwidth) / self.gridwidth;
nsinteger row = (point.y - kboardspace + 0.5 * self.gridwidth) / self.gridwidth;
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",col,row];
if (![self.chessmandict.allkeys containsobject:key]) {
uiview * chessman = [self chessman];
chessman.center = cgpointmake(kboardspace + col * self.gridwidth, kboardspace + row * self.gridwidth);
[self addsubview:chessman];
[self.chessmandict setvalue:chessman forkey:key];
self.lastkey = key;
//检查游戏结果
[self checkresult:col androw:row andcolor:self.isblack];
self.isblack = !self.isblack;
}
}
|
3.检测游戏结果
每落一个棋子就要多游戏结果进行一次检查,判断四个方向上是否有大于等于5个同色的棋子连成一线,有则提示游戏输赢结果,无则游戏继续.算法为,从当前棋子位置向前遍历,直到遇到与自己不同色的棋子,累加同色棋子的个数,再往后遍历,直到遇到与自己不同色的棋子,累加同色棋子的个数.得到该方向相连同色棋子的总个数
代码如下
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 |
//判断是否大于等于五个同色相连
- (bool)checkresult:(nsinteger)col androw:(nsinteger)row andcolor:(bool)isblack anddirection:(gmkdirection)direction{
if (self.samechessmanarray.count >= 5) {
return yes;
}
uicolor * currentchessmancolor = [self.chessmandict[[nsstring stringwithformat:@"%ld-%ld",col,row]] backgroundcolor];
[self.samechessmanarray addobject:self.chessmandict[self.lastkey]];
switch (direction) {
//水平方向检查结果
case gmkhorizontal:{
//向前遍历
for (nsinteger i = col - 1; i > 0; i --) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",i,row];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
//向后遍历
for (nsinteger i = col + 1; i < kgridcount; i ++) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",i,row];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
if (self.samechessmanarray.count >= 5) {
[self alertresult];
return yes;
}
[self.samechessmanarray removeallobjects];
}
break;
case gmkvertical:{
//向前遍历
for (nsinteger i = row - 1; i > 0; i --) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",col,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
//向后遍历
for (nsinteger i = row + 1; i < kgridcount; i ++) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",col,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
if (self.samechessmanarray.count >= 5) {
[self alertresult];
return yes;
}
[self.samechessmanarray removeallobjects];
}
break;
case gmkobliquedown:{
//向前遍历
nsinteger j = col - 1;
for (nsinteger i = row - 1; i >= 0; i--,j--) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",j,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor || j < 0) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
//向后遍历
j = col + 1;
for (nsinteger i = row + 1 ; i < kgridcount; i++,j++) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",j,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor || j > kgridcount) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
if (self.samechessmanarray.count >= 5) {
[self alertresult];
return yes;
}
[self.samechessmanarray removeallobjects];
}
break;
case gmkobliqueup:{
//向前遍历
nsinteger j = col + 1;
for (nsinteger i = row - 1; i >= 0; i--,j++) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",j,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor || j > kgridcount) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
//向后遍历
j = col - 1;
for (nsinteger i = row + 1 ; i < kgridcount; i++,j--) {
nsstring * key = [nsstring stringwithformat:@"%ld-%ld",j,i];
if (![self.chessmandict.allkeys containsobject:key] || [self.chessmandict[key] backgroundcolor] != currentchessmancolor || j < 0) break;
[self.samechessmanarray addobject:self.chessmandict[key]];
}
if (self.samechessmanarray.count >= 5) {
[self alertresult];
return yes;
}
[self.samechessmanarray removeallobjects];
}
break;
}
return no;
}
|
对外提供,重新开始,悔棋,切换初高级棋盘的三个接口
重新开始
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
- (void)newgame{
self.isover = no;
self.lastkey = nil;
[self.samechessmanarray removeallobjects];
self.userinteractionenabled = yes;
[self.chessmandict removeallobjects];
for (uiview * view in self.subviews) {
if ([view iskindofclass:[uiimageview class]]) {
continue;
}
[view removefromsuperview];
}
self.isblack = no;
}
|
悔棋
?| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
//撤回至上一步棋
- (void)backonestep:(uibutton *)sender{
if(self.isover) return;
if (self.lastkey == nil) {
sender.enabled = no;
cgfloat width = screen_width * 0.4 * screen_width_ratio;
uiview * tip = [[uiview alloc]initwithframe:cgrectmake(0, 0, width, 0.6 * width)];
tip.backgroundcolor = [uicolor colorwithwhite:1 alpha:0.8];
tip.layer.cornerradius = 8.0f;
[self addsubview:tip];
tip.center = cgpointmake(self.width * 0.5, self.height * 0.5);
uilabel * label = [[uilabel alloc]init];
label.text = self.chessmandict.count > 0 ? @"只能悔一步棋!!!" : @"请先落子!!!";
label.font = [uifont systemfontofsize:15];
[label sizetofit];
label.center = cgpointmake(tip.width * 0.5, tip.height * 0.5);
[tip addsubview:label];
self.userinteractionenabled = no;
dispatch_after(dispatch_time(dispatch_time_now, (int64_t)(2.0 * nsec_per_sec)), dispatch_get_main_queue(), ^{
self.userinteractionenabled = yes;
sender.enabled = yes;
[tip removefromsuperview];
});
return;
}
[self.chessmandict removeobjectforkey:self.lastkey];
[self.subviews.lastobject removefromsuperview];
self.isblack = !self.isblack;
self.lastkey = nil;
}
|
切换初高级键盘
?| 1 2 3 4 5 6 7 8 9 10 |
//改变键盘级别
- (void)changeboardlevel{
for (uiview * view in self.subviews) {
[view removefromsuperview];
}
[self newgame];
self.ishighlevel = !self.ishighlevel;
[self drawbackground:self.bounds.size];
}
|
demo中的一个小技巧
用字典存放棋子,以棋子的列号和行号组合起来的字符串为key值,value值为棋子view.这样处理,在判断某行某列是否有棋子就非常简单了。
总结
以上就是ios游戏开发之五子棋oc版的全部内容,希望本文对大家开发ios有所帮助,如果本文有不足之处,欢迎大家提供建议和指点!








发表评论
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。