第二个游戏 —— 连连看
今天又写了一个游戏 ——连连看,这个是个很经典的游戏,
我也想来试试看,如何实现它。
关键部分在于如何判定两个选中单元格是可以相连的。
经过分析,可以看到,连接的方式为一下几种模式
不管上述的哪种模式,都可以总结为如下的公式:
沿着x方向的所有x进行遍历,对于任何一个x来说,y1-y2之间的连接线如果是可以连接的,
而且,x1,y1~x,y1和x2,y2, x, y2之间都是可以连通的,那么这两个点就是可以连接的。
具体算法实现如下:
1 package org.stephen.connecty.control; 2 3 import org.stephen.connecty.model.Cell; 4 import org.stephen.connecty.model.Game; 5 import org.stephen.connecty.model.Grid; 6 import org.stephen.connecty.model.Position; 7 import org.stephen.connecty.model.Route; 8 9 public class RouteFinder { 10 11 public Grid grid = new Grid(); 12 13 public void before() { 14 Game game = Game.getInstance(); 15 for (int x = 0; x < Game.COLUMN_COUNT; x++) { 16 for (int y = 0; y < Game.ROW_COUNT; y++) { 17 grid.cells[y][x] = new Cell(); 18 grid.cells[y][x].type = game.grid.cells[y][x].type; 19 grid.cells[y][x].selected = game.grid.cells[y][x].selected; 20 grid.cells[y][x].destroyed = game.grid.cells[y][x].destroyed; 21 grid.cells[y][x].marked = false; 22 } 23 } 24 } 25 26 public Route find(Position first, Position second) { 27 28 Route vertical = findVertical(first, second); 29 if (vertical != null) { 30 return vertical; 31 } 32 33 Route horizontal = findHorizontal(first, second); 34 if (horizontal != null) { 35 return horizontal; 36 } 37 38 return null; 39 } 40 41 private Route findHorizontal(Position first, Position second) { 42 for (int x = 0; x < Game.COLUMN_COUNT; x++) { 43 boolean firstOk = false; 44 boolean secondOk = false; 45 boolean connectorOk = false; 46 47 firstOk = checkHorizontalEmpty(first.x, x, first.y); 48 secondOk = checkHorizontalEmpty(second.x, x, second.y); 49 connectorOk = checkVerticalEmpty(first.y, second.y, x); 50 if (firstOk && secondOk && connectorOk) { 51 return new Route(first, new Position(x, first.y), new Position( 52 x, second.y), second); 53 } 54 } 55 return null; 56 } 57 58 private Route findVertical(Position first, Position second) { 59 for (int y = 0; y < Game.ROW_COUNT; y++) { 60 boolean firstOk = false; 61 boolean secondOk = false; 62 boolean connectorOk = false; 63 64 firstOk = checkVerticalEmpty(first.y, y, first.x); 65 secondOk = checkVerticalEmpty(second.y, y, second.x); 66 connectorOk = checkHorizontalEmpty(first.x, second.x, y); 67 if (firstOk && secondOk && connectorOk) { 68 return new Route(first, new Position(first.x, y), new Position( 69 second.x, y), second); 70 } 71 } 72 return null; 73 } 74 75 private boolean checkVerticalEmpty(int y, int y2, int x) { 76 int start = Math.min(y, y2); 77 int end = Math.max(y, y2); 78 79 for (int i = start; i <= end; i++) { 80 if (!grid.cells[i][x].destroyed && !grid.cells[i][x].selected) { 81 return false; 82 } 83 } 84 return true; 85 } 86 87 private boolean checkHorizontalEmpty(int x, int x2, int y) { 88 int start = Math.min(x, x2); 89 int end = Math.max(x, x2); 90 91 for (int i = start; i <= end; i++) { 92 if (!grid.cells[y][i].destroyed && !grid.cells[y][i].selected) { 93 return false; 94 } 95 } 96 return true; 97 } 98 99 }
上述算法的代码实现了描述中的搜索。但是搜索最佳路径时,可以把所有的可行路径都列出,然后寻找最短的那条。
另外,本次实现的代码中包含了,计时、皮肤等功能,
预留了模式(向左移动,向右移动等)、设置(难度,声音等)等的扩展接口,有兴趣的读者,可以自行完成。
但是,该代码的MouseListener.onClick反应不是很灵敏,导致操作上的问题。 —— 这是一个已知的Bug。
同时,由于Java书写的,也看到了性能问题,以后可以考虑改为Android来书写。
源代码位置:https://files.cnblogs.com/stephen-wang/Connecty.zip
-----------------------------------------------------------------
现为独立咨询师。为软件企业或者其他企业的软件采购部门提供咨询,帮助改进软件开发流程,员工技术能力提升,以帮助企业在质量成本交货期三方面得到改善。