文章目录

  • 0.说明
  • 1.基本要求
  • 2.思路分析(加入核心代码)
    • 2.1 游戏初始化局面
    • 2.2 两点是否可连
    • 2.3 游戏是否结束
    • 2.4 判断死局
  • 3.注意事项与全部代码

0.说明

对于数据结构和算法,我并不是很精通(真的很一般),因此在这里只是做一个自己的简单分享,其实从这次数据结构课设中看出了自己存在了许多在这方面的不足。我的代码还存在一些不足,比如得到两个拐点最短路径的方法我并不是采用广度优先算法,而是使用的深度优先。顺便演示一下最终的效果:

1.基本要求

  1. 生成游戏初始局面;
  2. 每次用户选择两个图形,如果图形能满足一定条件(如果两个图形一样,且这个两个图形直接存在少于 3 个弯的路径),则两个图形都能消掉。给定具有相同图形的任意两个格子,我们需要寻找这两个格子之间在转弯最少的情况下,经过格子数目最少的路径。如果这个最优路径的转弯数目少于 3,则这个两个格子可以消去;
  3. 判断游戏是否结束。如果所有图形全部消去,游戏结束;
  4. 判断死锁,当游戏玩家不可能消去任意两个图像的时候,游戏进入“死锁”状态。当游戏进入“死锁”状态,可以随机打乱局面,解除“死锁”。

2.思路分析(加入核心代码)

以下仅是我个人的思路

2.1 游戏初始化局面

  • 加载图片
  • 生成随机成对布局

2.2 两点是否可连

  • 先判断直连

        /*** 判断是否可以直连** @param x1 当前位置点的横坐标* @param y1 当前位置点的纵坐标* @param x2 目标位置点的横坐标* @param y2 目标位置点的纵坐标* @return 是否可连*/public boolean isLineLink(int x1, int y1, int x2, int y2) {if (x1 == x2) {int minY = Math.min(y1, y2) + 1;int maxY = Math.max(y1, y2);while (minY < maxY) {if (map[minY][x1] != 0) {return false;}minY++;}return true;} else if (y1 == y2) {int minX = Math.min(x1, x2) + 1;int maxX = Math.max(x1, x2);while (minX < maxX) {if (map[y2][minX] != 0) {return false;}minX++;}return true;} else {return false;}}
    
  • 再判断是否折一次可连

        /*** 判断是否可以通过一次折点连通** @param x1 当前位置点的横坐标* @param y1 当前位置点的纵坐标* @param x2 目标位置点的横坐标* @param y2 目标位置点的纵坐标* @param g 画笔* @return 是否可连*/public boolean isLinkByOne(int x1, int y1, int x2, int y2, Graphics g) {g.setColor(Color.RED);if (isLineLink(x1, y1, x1, y2) && map[y2][x1] == 0 && isLineLink(x1, y2, x2, y2)) {g.drawLine(x1 * 50 + 25, y1 * 50 + 25, x1 * 50 + 25, y2 * 50 + 25);g.drawLine(x1 * 50 + 25, y2 * 50 + 25, x2 * 50 + 25, y2 * 50 + 25);return true;} else if (isLineLink(x1, y1, x2, y1) && map[y1][x2] == 0 && isLineLink(x2, y1, x2, y2)) {g.drawLine(x1 * 50 + 25, y1 * 50 + 25, x2 * 50 + 25, y1 * 50 + 25);g.drawLine(x2 * 50 + 25, y1 * 50 + 25, x2 * 50 + 25, y2 * 50 + 25);return true;}return false;}
    
  • 最后判断图片是否可以两次可连 --> 深度优先搜索

        /*** 深度优先搜索* 判断是否可以通过两次折点连通 - 如果存在,在此基础上得到最短路径** @param x1 当前位置点的横坐标* @param y1 当前位置点的纵坐标* @param x2 目标位置点的横坐标* @param y2 目标位置点的纵坐标* @param inflectionPointNum 当前折点的次数* @param direction 当前方向:无(-1) 右(0) 下(1) 左(2) 右(3)* @param step 当前走的步数*/public void isLinkByTwo(int x1, int y1, int x2, int y2, int inflectionPointNum, int direction, int step) {//发现折点次数达到三次就返回,表示路径不行if (inflectionPointNum == 3) {return;}//记录该点位置到路径数组中tempPath[step][0] = y1;tempPath[step][1] = x1;//查看是否到达目标点if (x1 == x2 && y1 == y2) {//说明找到了更短的,就将这个更短路径放入到最短路径数组中存储if (step < minStep) {minStep = step;for (int i = 0; i <= minStep; i++) {minPath[i][0] = tempPath[i][0];minPath[i][1] = tempPath[i][1];}}return;}//标记当前点已经访问isVisited[y1][x1] = 1;int tx;int ty;//尝试不同的方向for (int i = 0; i < 4; i++) {tx = x1 + dx[i];ty = y1 + dy[i];/*1.tx >= 0 && tx < LENGTH && ty >= 0 && ty < LENGTH 保证不越界map[ty][tx] == 0 保证是空白区isVisited[ty][tx] == 0 保证是未访问的2.tx == x2 && ty == y2 说明是目标点*/if (tx >= 0 && tx < LENGTH && ty >= 0 && ty < LENGTH && map[ty][tx] == 0 && isVisited[ty][tx] == 0 || tx == x2 && ty == y2) {//标记即将查找的点为 已访问isVisited[ty][tx] = 1;if (direction == -1) {//如果无方向,这是第一次深度搜索的状态isLinkByTwo(tx, ty, x2, y2, inflectionPointNum, i, step + 1);} else if (i != direction) {//如果即将走的点的方向与原来行走的点方向不一致isLinkByTwo(tx, ty, x2, y2, inflectionPointNum + 1, i, step + 1);} else {//如果方向一致:可以与第一个if的代码合并,但为了层次更为清晰,这里分开写isLinkByTwo(tx, ty, x2, y2, inflectionPointNum, i, step + 1);}//访问完毕,回溯回来就标记为未访问,给后面的点来查找isVisited[ty][tx] = 0;}}}
    

    广度优先搜索其实更好,但我有特别纠结却又不太好描述的问题导致我写到一般就没再继续用广度优先,总感觉对于 ”寻找这两个格子之间在转弯最少的情况下,经过格子数目最少的路径“ 有点问题,脑子绕不过来。

2.3 游戏是否结束

  • 用一个count全局变量来记录当前剩余的数目

2.4 判断死局

  • 对每个不为空的点进行深度优先搜索,如果该点返回true即找到有可连,就不再继续继续其它点的搜索
  • 判断一个地图是否为死局需要时间,而在这个过程中如果进行其它操作比如“重新开始游戏”就可能会弹出对话框上一张地图是死锁,而此时对于上一张是否为死锁是毫无意义的,因此我加入了一个地图版本号nowVersion,在每次更新地图时都会改变,值为当前系统时间 System.currentTimeMillis()
    /*** 深度优先搜索* 搜索有没有值为value并与最初点可连的点** @param x1 当前点的横坐标* @param y1 当前点的纵坐标* @param value 最初点的值* @param inflectionPointNum 拐点个数* @param direction 当前方向* @param step 当前步数* @return 是否找到*/public boolean search(int x1, int y1, int value, int inflectionPointNum, int direction, int step) {if (inflectionPointNum == 3) {return false;}/*步数不为0是保证与刚开始的搜索不会冲突,否则刚已进入最初的搜索就会表明找到*/if (value == runMap[y1][x1] && step != 0) {//说明找到了一条return true;}isVisitedForThread[y1][x1] = 1;int tx;int ty;boolean isFind = false;//尝试不同的方向for (int i = 0; i < 4 && !isFind; i++) {tx = x1 + dx[i];ty = y1 + dy[i];/*tx >= 0 && tx < LENGTH && ty >= 0 && ty < LENGTH && isVisitedForThread[ty][tx] == 0 不越界并且未被访问runMap[ty][tx] == 0 临时地图的该坐标为null则可走value == runMap[ty][tx] 临时地图的该坐标就为目标相等值则可走*/if (tx >= 0 && tx < LENGTH && ty >= 0 && ty < LENGTH && isVisitedForThread[ty][tx] == 0 && (runMap[ty][tx] == 0 || value == runMap[ty][tx])) {isVisitedForThread[ty][tx] = 1;if (direction == -1) {isFind = search(tx, ty, value, inflectionPointNum, i, step + 1);} else if (i != direction) {isFind = search(tx, ty, value, inflectionPointNum + 1, i, step + 1);} else {isFind = search(tx, ty, value, inflectionPointNum, i, step + 1);}isVisitedForThread[ty][tx] = 0;}}return isFind;}

3.注意事项与全部代码

  • 我会把项目(包括代码,图片以及背景音乐代码)放在我的百度网盘:https://pan.baidu.com/s/1ykr53VP1zvfvk9VHG413yA?pwd=1314

  • 图片你可以自定义,但需要是 50*50 大小的图片

  • 代码注释比较详细,可以明确知道某段代码是在做什么

连连看核心算法与基本思想(附全部项目代码链接与代码详细注释)相关推荐

  1. [转]连连看核心算法详解

    [url]http://bbs.9ria.com/viewthread.php?tid=63206[/url] 最近做了个连连看游戏,综合网上各种不同的思路,整理出了个人认为大家都比较好理解的一套思路 ...

  2. 数据结构与算法综合实验(附完整项目)

    数据结构与算法综合实验--练练看系统 系统设计 效果展示 1. 菜单界面 2.游戏界面 3.游戏结束界面 开源链接 linkGame代码传送门

  3. 最小错误率贝叶斯决策的基本思想_太赞了!机器学习基础核心算法:贝叶斯分类!(附西瓜书案例及代码实现)...

    Datawhale 作者:尹晓丹,Datawhale优秀学习者 寄语:首先,简单介绍了生成模型和判别模型,对条件概率.先验概率和后验概率进行了总结:其次,对朴素贝叶斯的原理及公式推导做了详细解读:再次 ...

  4. 太赞了!机器学习基础核心算法:贝叶斯分类!(附西瓜书案例及代码实现)

    Datawhale 作者:尹晓丹,Datawhale优秀学习者 寄语:首先,简单介绍了生成模型和判别模型,对条件概率.先验概率和后验概率进行了总结:其次,对朴素贝叶斯的原理及公式推导做了详细解读:再次 ...

  5. 【机器学习入门】机器学习基础核心算法:贝叶斯分类!(附西瓜书案例及代码实现)...

    Datawhale 作者:尹晓丹,Datawhale优秀学习者 寄语:首先,简单介绍了生成模型和判别模型,对条件概率.先验概率和后验概率进行了总结:其次,对朴素贝叶斯的原理及公式推导做了详细解读:再次 ...

  6. 韩国美女连连看核心算法

    精选的韩国美女,看着一个个沉鱼落雁,闭月羞花之貌的美人,着实令人心神俱醉,目不暇接."媚眼含羞合,丹唇逐笑开","俊眉修眼,顾盼神飞",如此一个小游戏,却让你赏 ...

  7. SCAN算法 | 磁头引臂调度问题 | 双磁头进阶 | Java实现(详细注释)

    写在前面 欢迎讨论. 问题描述 用JAVA同步方法实现磁头引臂调度问题,采用SCAN算法. 要求:(1) 给出核心调度解法,用JAVA类实现,其中包含require(dest)和release()两个 ...

  8. 1470篇!CVPR2020结果出炉(附13篇论文链接/开源代码/解读)

    点击上方"视学算法",选择加"星标"或"置顶" 重磅干货,第一时间送达 本文转载自:极市平台 编辑:Amusi(CVer) 今天,计算机视觉 ...

  9. 数学建模常用算法:蚁群算法求解tsp问题+att48算例测试【java实现--详细注释】

    代码 蚂蚁类 package com.dam.heuristic.aco.test;import java.util.*;public class Ant {//蚂蚁所走的城市序列private Li ...

最新文章

  1. 安装Nginx的方法教程
  2. 群雄逐鹿,谁将赢得5G时代的物联网战争?
  3. Linux预备知识(三):系统调用-用户态/内核态
  4. topcoder13444
  5. aws集群重启_在AWS中设置Cassandra集群
  6. gradle-com.android.build.api.transform.TransformException:Error while generating the main dex list
  7. 台大李宏毅Machine Learning 2017Fall学习笔记 (14)Unsupervised Learning:Linear Dimension Reduction
  8. INV 调试: 如何获取库存物料事务处理调试信息
  9. CSS 控制滚动条样式
  10. 用nginx转发请求tomcat 如何配置访问日志获取真实ip
  11. 【转】C#通过WMI设置NTFS目录共享和目录安全
  12. android拦截彩信,Android手机恶意彩信拦截系统的设计和实现
  13. collapsar(collapsar网名什么意思)
  14. C# vb .net实现消除红眼效果
  15. mysql的double类型数据_mysql数据类型double和decimal区别详解
  16. 纳芯微携手企企通,打造全新数字化采购管理系统
  17. ESP8266驱动SG90舵机控制开关灯(灯的开关)的折腾记录
  18. python循环遍历-for循环
  19. 10分钟搞定miniconda-python环境安装
  20. AI:大模型领域最新算法SOTA总结、人工智能领域AI工具产品集合分门别类(文本类、图片类、编程类、办公类、视频类、音频类、多模态类)的简介、使用方法(持续更新)之详细攻略

热门文章

  1. css如何在下拉框添加倒三角,CSS给选中元素增加倒三角形(示例代码)
  2. 使用webpack搭建react项目
  3. Windows 同时访问内网和外网解决方案
  4. MySQL千万级数据量优化方案
  5. 3D数学系列之——从“蒙的挺准”到“蒙的真准”解密蒙特卡洛积分!
  6. 一文读懂多元回归分析
  7. 一文简单理解《Effective Java》建议
  8. thinkphp6 框架源码分析
  9. 图的连通性和连通分量
  10. WEB API新增整理(三)