近期腾讯在安卓手机客户端出了个小游戏——天天爱消除。初次玩这款游戏真是觉得自己脑残,玩了半天也只能靠提示进行下去。小伙伴们个个几十万让我几万的情何以堪?!之后想了想如何自动消除,于是有了这篇文。注意这里仅仅是在Windows平台实现了算法,没有应用于android环境,所以想拿现成的辅助程序请出门左拐。

算法的实现比较容易,主要是数据结构需要注意,也是一下午就搞定了,初期为了快速开发选用了C#作为实现语言。本文的示例代码将以C#给出。

首先分析游戏,消除界面是一个7*7固定的棋盘,有有限种基本棋子(蓝,紫,红,白,咖啡,绿,橘黄),还有一些特殊功能棋子暂不考虑,下面是一张游戏截图:

连成三个通常有几种情况可以考虑,大家在玩的时候应该能体会到,下面的6个图(注意颜色区分)是以3*2为分析单元的所有情况,对于2*3其实同理,只不过要转换一下。

O

O

O

O

O

O

O

O

O

O

O

O

O

O

O

O

O

O

下面有两个图是1*4的所有情况(4*1同理):

O

O

O

O

O

O

在消除的时候通常就是按照上述规律进行的,所以我们只要对棋盘数据进行分割,然后对应上面几种情况,判断固定位置是否是相同的棋子,那么就可以直接知道应该交换哪两个位置了。

不同棋子可以用1234..这样简单表示,棋盘数据是一个7*7的二维数组,假设上图是这样一个二维数组:

new int[7, 7]

{

{4,0,0,4,1,5,3},

{1,2,1,0,1,0,5},

{5,4,6,2,0,4,3},

{2,4,6,5,1,3,5},

{1,5,3,1,0,0,5},

{6,5,3,2,2,1,2},

{1,0,5,2,0,2,2}

}; 下面对数据进行2*3、1*4划分,由于划分之后要进行判断并返回所在棋盘数组的位置,因此需要定义一个含有位置字段和数据段的一个数据结构 ,位置是通过x、y坐标来定位,也就是数组下标:

///

/// 定义棋子坐标(从0开始)

///

public struct point{

public int m_x;

public int m_y;

public point(int x, int y)

{

m_x = x;

m_y = y;

}

}; 为了能够简单初始化,所以给了一个构造函数来初始化成员。

///

/// 每个棋子都记录一个位置

///

private struct ele

{

public point m_pIndex;

public int m_data;

}; 下面的函数将棋盘数据转化为含有位置信息的新数组,通过成员refData进行存储:

///

/// 将原始数据进行转化

///

private void ConvertData() {

refData = new ele[7, 7];

for (int i = 0; i < 7; ++i)

{

for (int j = 0; j < 7; ++j)

{

refData[i, j].m_data = chessData[i, j];

refData[i, j].m_pIndex = new point(i, j);

}

}

} 最重要的就是分析单元的提取,在进行提取之前,我们首先需要定义几个标志位:

//行列计次

int s_x = 0;

int s_y = 0;

//遍历标识

bool is_2x3 = true;

bool is_3x2 = false;

bool is_1x4 = false;

bool is_4x1 = false;

bool m_bFinished = false;

s_x,s_y 是用于定位棋子的变量,因为取3*2和2*3的时候需要紧挨着取,保证不能漏掉。

下面4个bool变量标志当前正在取哪种类型的区域。

///

/// 返回下一个分析单元

///

///

private ele[,] GetNextSection()

{

ele[,] sec = null;

//纵向(2*3)遍历

if (s_x <= 5 && s_y <= 4 && is_2x3)

{

sec = new ele[2, 3]{

{refData[s_x,s_y],refData[s_x,s_y+1],refData[s_x,s_y+2]},

{refData[s_x+1,s_y],refData[s_x+1,s_y+1],refData[s_x+1,s_y+2]}

};

s_x++;

//纵向到底

if (s_x == 6)

{

//右移一个单位

s_x = 0;

s_y++;

if (s_y == 5) {

//遍历完毕

s_x = 0;

s_y = 0;

is_2x3 = false;

is_3x2 = true;

is_1x4 = false;

is_4x1 = false;

}

}

return sec;

}

//纵向(3*2)遍历

if (s_x <= 4 && s_y <= 5 && is_3x2)

{

sec = new ele[3, 2]{

{refData[s_x,s_y] ,refData[s_x,s_y+1] },

{refData[s_x+1,s_y],refData[s_x+1,s_y+1]},

{refData[s_x+2,s_y],refData[s_x+2,s_y+1]}

};

//为简化代码,对3*2的section进行矩阵变换

sec = new ele[2, 3] {

{sec[2,0],sec[1,0],sec[0,0]},

{sec[2,1],sec[1,1],sec[0,1]}

};

s_x++;

//纵向到底

if (s_x == 5)

{

//右移一个单位

s_x = 0;

s_y++;

if (s_y == 6)

{

//遍历完毕

s_x = 0;

s_y = 0;

is_2x3 = false;

is_3x2 = false;

is_1x4 = true;

is_4x1 = false;

}

}

return sec;

}

//1*4遍历

if (s_x <= 6 && s_y <= 3 && is_1x4)

{

sec = new ele[1, 4]{

{refData[s_x,s_y],refData[s_x,s_y+1],refData[s_x,s_y+2],refData[s_x,s_y+3]}

};

s_y++;

if (s_y == 4)

{

//下移一个单位

s_y = 0;

s_x++;

if (s_x == 7)

{

//遍历完毕

s_x = 0;

s_y = 0;

is_2x3 = false;

is_3x2 = false;

is_1x4 = false;

is_4x1 = true;

}

}

return sec;

}

//4*1遍历

if (s_x <= 3 && s_y <= 6 && is_4x1)

{

sec = new ele[4, 1]{

{refData[s_x,s_y]},

{refData[s_x+1,s_y]},

{refData[s_x+2,s_y]},

{refData[s_x+3,s_y]}

};

//对4*1的section进行矩阵变换

sec = new ele[1, 4]{

{sec[3,0],sec[2,0],sec[1,0],sec[0,0]}

};

s_x++;

if (s_x == 4)

{

//下移一个单位

s_x = 0;

s_y++;

if (s_y == 7)

{

//遍历完毕

s_x = 0;

s_y = 0;

is_2x3 = true;

is_3x2 = false;

is_1x4 = false;

is_4x1 = false;

m_bFinished = true;

//return null;

}

}

return sec;

}

return sec;

} 每次调用函数将返回下一个区域,这就靠自己领悟了。我觉得我写的稍微有点复杂,不过应该比较容易理解,效率上也是相当快的。

取一个区域进行分析,这里是连续分析,直到找到一个含有可交换棋子的区域 :

///

/// 返回一个可交换位置

///

///

public point[] GetNextPoints(){

point[] pt=null;

ele[,] sec;

while (pt == null && !m_bFinished)

{

sec = GetNextSection();

if (sec == null) return null;

if (sec.GetLength(0) == 1)

{

//有两种情况

if (sec[0, 0].m_data == sec[0, 1].m_data && sec[0, 0].m_data == sec[0, 3].m_data)

{

pt = new point[2]{

sec[0,2].m_pIndex,

sec[0,3].m_pIndex

};

}

else if (sec[0, 0].m_data == sec[0, 2].m_data && sec[0, 0].m_data == sec[0, 3].m_data)

{

pt = new point[2]{

sec[0,0].m_pIndex,

sec[0,1].m_pIndex

};

}

}

else if (sec.GetLength(0) == 2)

{

//只有6种可消除情况

if (sec[0, 0].m_data == sec[0, 2].m_data && sec[0, 0].m_data == sec[1, 1].m_data

|| sec[0, 1].m_data == sec[1, 0].m_data && sec[0, 1].m_data == sec[1, 2].m_data)

{

pt = new point[2]{

sec[0,1].m_pIndex,

sec[1,1].m_pIndex

};

}

else if (sec[0, 0].m_data == sec[1, 1].m_data && sec[0, 0].m_data == sec[1, 2].m_data

|| sec[1, 0].m_data == sec[0, 1].m_data && sec[1, 0].m_data == sec[0, 2].m_data)

{

pt = new point[2]{

sec[0,0].m_pIndex,

sec[1,0].m_pIndex

};

}

else if (sec[0, 0].m_data == sec[0, 1].m_data && sec[0, 0].m_data == sec[1, 2].m_data

|| sec[1, 0].m_data == sec[1, 1].m_data && sec[1, 0].m_data == sec[0, 2].m_data)

{

pt = new point[2]{

sec[0,2].m_pIndex,

sec[1,2].m_pIndex

};

}

}

}//while

return pt;

} 这个没什么技术含量,按部就班。

现在道德我们想要的两个point了,实际测试情况请看图,为了方便查看,下标进行了+1处理:

算法速度上没有严格测试,但都是瞬间完成的。

好了,大家有什么疑问欢迎提出,转载文章请说明出处:

http://my.oschina.net/ybusad/blog/153533

用java编写天天爱消除_【C#算法实现】安卓QQ小游戏天天爱消除辅助。相关推荐

  1. 【C#算法实现】QQ小游戏天天连萌(连连看)算法。

    2019独角兽企业重金招聘Python工程师标准>>> 算法是程序的灵魂,优秀的算法可以高效率解决实际问题.继腾讯安卓游戏天天爱消除之后又一款十分好玩的游戏--天天连萌,其实就是以前 ...

  2. 基于STL实现自动贪心寻路算法的贪吃蛇小游戏

    基于STL实现自动贪心寻路算法的贪吃蛇小游戏 写贪吃蛇小游戏的想法来自CometOJ-Contest#13的B题,当时用STL双端队列维护蛇身的时候觉得非常方便,现在用EasyX图形库实现一下. 运行 ...

  3. 【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置git环境和项目创建

    [Java闭关修炼]SpringBoot项目-贪吃蛇对战小游戏-配置git环境和项目创建 项目的逐步细分 配置git环境 创建项目后端 前后端不分离写法-url访问路径解析资源 安装vue vue文件 ...

  4. 【Java闭关修炼】SpringBoot项目-贪吃蛇对战小游戏-配置Mysql与注册登录模块2

    [Java闭关修炼]SpringBoot项目-贪吃蛇对战小游戏-配置Mysql与注册登录模块2 传统的登录验证模式 JWT登录验证方式 下载安装依赖 创建JWTUTIL JwtAuthenticati ...

  5. java青蛙过河打字_趣味算法——青蛙过河(JAVA)

    青蛙过河是一个非常有趣的智力游戏,其大意如下: 一条河之间有若干个石块间隔,有两队青蛙在过河,每队有3只青蛙,这些青蛙只能向前移动,不能向后移动,且一次只能有一只青蛙向前移动.在移动过程中,青蛙可以向 ...

  6. java实现种子填充算法,Java编写图形学的种子填充算法

    用C写的图形学填充算法已经很多了,看到不少帖子都是在问关于如何用Java编写图形学的填充算法,说来也巧,我刚好要做一个这个方面的实验,用的是扫描线种子填充算法,由于时间仓促,代码质量可能不算很高,希望 ...

  7. java编写应用程序_为您的Java应用程序编写数据驱动的测试

    java编写应用程序 JUnit是一个功能非常强大的测试框架,它不仅为其用户提供了编写快速简便的测试的功能,而且还为用户提供了扩展它并使其按其期望的方式工作的机会. 在JUnit之上构建了许多框架,这 ...

  8. java编写布局文件_鸿蒙OS利用JAVA编写的布局实践练习

    鸿蒙OS利用JAVA编写的布局实践练习 鸿蒙OS利用JAVA编写的布局实践练习 目录 JAVA UI框架 利用JAVA代码实现一个简单的布局 利用xml实现上述布局 JAVA UI框架 ??应用的Ab ...

  9. Java编写图像浏览器_浏览器下载图像(JAVA代码)

    03-07阅读8103 简介: JavaWeb下载文件通常分为两种类型,一种是浏览器可以识别的文件类型,例如.txt,.excel,.zip等,可以通过使用以下链接来实现标签,但图片下载确实很麻烦. ...

最新文章

  1. BUTTONS V. 2.0.0——CSS按钮库
  2. html标签的id中带有.号的获取方式
  3. Linux下用Xdebug调试php
  4. python爬虫工程师-记录一下自己找“python爬虫工程师实习生”岗位的经历
  5. VS2008工程转为VS2005(C++)
  6. com.mysql.jdbc.exceptions.jdbc4.CommunicationsException
  7. scp 安全复制(远程文件复制工具)
  8. C#,COM口,接收,发送数据
  9. libpng库的移植与使用
  10. python少儿培训视频教程
  11. 微信怎么找群聊?找回微信群聊只需要这样…
  12. Kafka集群搭建(四节点)
  13. python格式化输出
  14. 【Web】Web-API(No.69)下课倒计时-自动播放下课铃声
  15. Pytorch加载模型只导入部分层权重,即跳过指定网络层的方法
  16. Kaldi 入门使用教程
  17. linux中tomcat部署项目步骤以及命令
  18. TFN F4 高性能OTDR光时域反射仪 都具有哪些优势?
  19. 20189200余超 2018-2019-2 移动平台应用开发实践第八周作业
  20. ***防火墙密码恢复手记

热门文章

  1. Spring Boot:
  2. flask_email实现QQ邮箱发送邮件
  3. python猜数字游戏编程循环_使用python进行简单的猜数字游戏(while循环)
  4. 《零知识证明 – zkSNARK 入门》— PPIO Code Talks 第二期
  5. MODIS产品MOD13Q1简介
  6. 奇舞学院学习笔记之JavaScript一页通
  7. php 代付测试demo,php – 2checkout测试支付模拟
  8. 域名需细分,市场须细作。
  9. mac如何连接wifi?苹果Mac OS X连接隐藏的WiFi无线信号教程
  10. Matlab GUI图像学习图像处理进阶