扫雷05 埋雷
布局设计
根据游戏难度分为三种布设,都为正方形(9x9/16x16/24x24)
为了减低游戏设计的难度,直接在类成员中定义了一个26*26的二维指针数组,为此还两个获取相应行列位置的雷区块的值(0-8代表这个区块周围的雷的数量,-1代表有雷块,-2代表挖开了的无雷块)
1: MineBlock* _land[26 * 26]; //土地,放置地雷,,多出两行两列,为了统一操作
2: ////////////////////////////////////////////////////////////////////
3: 获取行列坐标上的雷区块的精灵的地址
4: Block * GameScene::getRowColAddr(int r,int c)
5: {
6: assert(r >= 0 && r < 26 && c >= 0 && c < 26);
7: return _land[r * 26 + c]; //第r行c列的地址
8: }
9: 获取行列坐标上的雷区块的精灵的属性值
10: t int GameScene::getRowColValue(int r,monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 16pt; padding-right: 0px; background-color: white"> 11: //r和c的值应该在[1,24]是土地的
12: assert(r >= 0 && r < 26 && c >= 0 && c < 26);
13: return _land[r * 26 + c]->getValue(); //第r行c列的值
14: }
埋雷及雷区初始化
埋雷位置由随机数生成,个数已经确定好了。(简单10个,一般48个,苦难96个)
埋雷只是设置了相应的位置的数值,还没有加载显示。相关的操作在触摸事件点击到相应的位置后才会有。
埋雷之后还有对相应的位置加载相关的图片,这些放在初始化雷区精灵里面来做。
埋雷BuryMine()函数的实现
1: //////////////////////////////////////////////////////////
2: // 埋雷
3: bool GameScene::BuryMine()
4: {
5: switch (_customs) {
6: case 1:
7: _MaxRanks = 9;
8: _mine = 10;
9: break;
10: case 2:
11: _MaxRanks = 16;
12: _mine = 48;
13: break;
14: case 3:
15: _MaxRanks = 24;
16: _mine = 96;
17: break;
18: }
19:
20: //创建雷块,并初始化其值为0
21: for (int r = 0; r <= _MaxRanks + 1; ++r) {
22: for (int c = 0; c <= _MaxRanks + 1; ++c) {
23: _land[r * 26 + c] = new MineBlock();
24: _land[r * 26 + c]->setValue(0);
25: }
26: }
27:
28: //创建雷区的地雷
29: srand((unsigned int)time(NULL));
30:
31: int i = 0;
32: int row = 1,col = 1;
33: while (i < _mine) { //随机设置雷的位置
34: row = rand() % _MaxRanks + 1;
35: col = rand() % _MaxRanks + 1;
36: if (getRowColValue(row,col) != 0) {
37: continue;
38: }
39: getRowColAddr(row,col)->setValue(-1); //雷的代号是-1
40: // CCLog("row = %d col = %d [%d]",row,col,getRowColValue(row,col));
41: ++i;
42: }
43: //计算非雷块的周围的雷的数量,得到其值
44: int sum = 0;
45: for (int r = 1; r <= _MaxRanks; ++r) {
46: for (int c = 1; c <= _MaxRanks; ++c) {
47: if (getRowColValue(r,c) == -1) {
48: continue;
49: }
50: sum = 0;
51: sum += getRowColValue(r + 1,c - 1) == -1 ? 1 : 0; // r-1,c-1 r-1,c r-1,c+1
52: sum += getRowColValue(r + 1,c) == -1 ? 1 : 0; // r,c-1 r,c r,monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 16pt; padding-right: 0px; background-color: white"> 53: sum += getRowColValue(r + 1,c + 1) == -1 ? 1 : 0; // r+1,c-1 r+1,c r+1,monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 16pt; padding-right: 0px; background-color: #f4f4f4"> 54: sum += getRowColValue(r,c - 1) == -1 ? 1 : 0;
55: //sum += getRowColValue(r,c) == -1 ? 1 : 0;
56: sum += getRowColValue(r,c + 1) == -1 ? 1 : 0;
57: sum += getRowColValue(r - 1,monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 16pt; padding-right: 0px; background-color: #f4f4f4"> 58: sum += getRowColValue(r - 1,c) == -1 ? 1 : 0;
59: sum += getRowColValue(r - 1,monospace; width: 100%; border-bottom-style: none; color: black; padding-bottom: 0px; direction: ltr; text-align: left; padding-top: 0px; border-right-style: none; padding-left: 0px; margin: 0em; border-left-style: none; line-height: 16pt; padding-right: 0px; background-color: #f4f4f4"> 60: //设置land格子周边的雷数
61: getRowColAddr(r,c)->setValue(sum);
62: }
63:
64: return true;
65: }
雷区初始化函数initmine函数的实现
因为在coco3.x中,init相关函数已经是protected成员,所以这里要修改MineBlock类的定义。
为MineBlock类添加一个public方法@H_301_681@indirectInit和indirectInitWithTexture来间接的调用这两个父类的接口,因为父类中是protected的,所以才能调用。如果是private的,那是不行的。
修改后的MineBlock类定义
1: class MineBlock :public Sprite
2: {
3: public:
4: MineBlock() { _dig = false; }
5: bool indirectInit() { return init(); }
6: bool indirectInitWithTexture(cocos2d::Texture2D* t) { return initWithTexture(t); }
7: void setValue(short v) { _value = (short)v; }
8: int getValue() { return (int)_value; }
9: bool getFlag() { return _flag; }
10: void setFlag(bool flag) { _flag = flag; }
11: bool getDig() { return _dig; }
12: void setDig(bool dig) { _dig = dig; }
13: bool callinitWithTexture(Texture2D* t) { return Sprite::initWithTexture(t); }
14: private:
15: short _value; //周围的雷数,之前有char表示,在移植到安卓的时候出错
16: bool _flag; //是否被标记
17: bool _dig; //是否被挖开
18: };
InitMine函数
1: //////////////////////////////////////////////////////////////////
2: // 初始化雷区精灵
3: bool GameScene::InitMine()
5: //初始化精灵保存数组
6: _ArraySprite = __Array::create();
7: if (!_ArraySprite) {
8: return false;
9: }
10: _ArraySprite->retain();
11: //获取精灵尺寸
12: float w = WinWidth / _MaxRanks;
13:
14: //初始化雷区精灵
15: for (int r = 0; r <= _MaxRanks + 1; ++r) {
16: for (int c = 0; c <= _MaxRanks + 1; ++c) {
17:
18: //全部都初始化为未踩的状态
19: MineBlock * mb = getRowColAddr(r,c);
20: if (!mb) {
21: return false;
22: }
23:
24: mb->indirectInitWithTexture(CCTextureCache::sharedTextureCache()->textureForKey("no.png"));
25: mb->setValue(getRowColValue(r,c));
26: mb->setFlag(false); //设置为未标记状态
27: if (r == 0 || c == 0 || r == _MaxRanks + 1 || c == _MaxRanks + 1) {
28: mb->retain(); //保留下来,但是不加入到游戏场景中
29: continue;
30: }
31:
32: addChild(mb); //加载精灵到游戏场景层
33: mb->setScale(w / mb->getContentSize().width);
34: mb->setAnchorPoint(Vec2(0.0f,.0f));
35: //设置精灵挂载的位置
36: mb->setPosition(Vec2((r - 1)*w,(c - 1)*w) + _layerColor->getPosition());
37: //添加到数组
38: _ArraySprite->addObject(mb);
39: }
40: }
41: return true;
42: }