看到师兄在玩连连看的游戏,于是乎突然想写一个自己的连连看游戏。我写的这个没有界面,只是一个控制台演示版,当然在这个基础上,用SWING或者Android的GridView扩充界面我想应该很容易吧。不再啰嗦赘述。
连连看游戏关键还是算法问题,任何两个棋子之多经过两个直角的折角连通就可以消去。能消去的两个棋子分以下三种情况:
1 可以用一条直线直接相连
2 经过一个折角相连
3 经过两个折角相连
在设计可以考虑,采用递归的思想,3-->2,2--->1 ,我的程序仅仅使用了3--->2而对于2,我没用递归。下面分享我的代码,欢迎拍砖。
import java.awt.Point; import java.util.Random; import java.util.Scanner; public class Test { private int row_len;//行数(开始和结束行值为辅助作用) private int colunm_len;//列数(开始和结束列值为辅助作用) private int a[][];//存储整个棋盘值 private static final int NUMBER_SIZE=10;//图片的数目 public static void main(String[] args) { Test t=new Test(); Point p1 =new Point(); Point p2 =new Point(); t.showQiPan(); while(true){ t.getPoint(p1,p2); t.docheck(p1, p2); if(p1.x==0) break; } } /* * 得到输入点的坐标 */ private void getPoint(Point p1, Point p2) { Scanner scanner=new Scanner(System.in); System.out.println("输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束)"); p1.x=scanner.nextInt(); p1.y=scanner.nextInt(); p2.x=scanner.nextInt(); p2.y=scanner.nextInt(); } /* * 初始化并显示棋盘 */ public void showQiPan(){ init(); show_array(); } /* * 初始化 */ public void init(){ Scanner scanner=new Scanner(System.in); System.out.println("难度系数控制:"); System.out.println("行数:"); row_len=scanner.nextInt(); System.out.println("列数"); colunm_len=scanner.nextInt(); if(colunm_len%2!=0){ System.err.println("请保证输入的列号为偶数"); System.exit(0); } a=new int[row_len][colunm_len]; for(int j=0;j<colunm_len;j++){ a[0][j]=0; a[row_len-1][j]=0; } for(int j=0;j<row_len;j++){ a[j][0]=0; a[j][colunm_len-1]=0; } for(int i=1;i<row_len-1;i++) for(int j=1;j<colunm_len-1;j=j+2){ int value=0; while(value==0){ Random r=new Random(); value=r.nextInt(NUMBER_SIZE); } a[i][j]=value; a[i][j+1]=value; } /* * 随机调换a[][]中的值 */ for(int i=1;i<(row_len-2)*(colunm_len-2);i++){ int index_x1=0; int index_y1=0; int index_x2=0; int index_y2=0; Random r=new Random(); while(index_x1==0){ index_x1=r.nextInt(row_len-1); } while(index_x2==0){ index_x2=r.nextInt(row_len-1); } while(index_y1==0){ index_y1=r.nextInt(colunm_len-1); } while(index_y2==0){ index_y2=r.nextInt(colunm_len-1); } int tmp=a[index_x1][index_y1]; a[index_x1][index_y1]=a[index_x2][index_y2]; a[index_x2][index_y2]=tmp; } } /* * 显示数组值 */ public void show_array(){ System.out.print(" "); for(int i=1;i<colunm_len-1;i++) System.out.print("*"+i+"*"); System.out.print("\n"); for(int i=0;i<row_len;i++){ if(i!=0&&i!=row_len-1) System.out.print(i); else System.out.print(" "); for(int j=0;j<colunm_len;j++){ System.out.print(" "+a[i][j]+" "); } System.out.print("\n"); } } /* * 验证两点是否可以取消 */ public void docheck(Point p1,Point p2){ Point p3=new Point(-1,-1); if(a[p1.x][p1.y]==a[p2.x][p2.y]){ if(isSameLine(p1, p2)||isSingleBrokenLine(p1, p2)||isDoubleBreakLine(p1, p2, p3)){ a[p1.x][p1.y]=0; a[p2.x][p2.y]=0; } show_array(); }else System.out.println("输入两点值不同,请重新选择"); } /* * 是否直接可以连通 */ public boolean isSameLine(Point p1,Point p2){ int i; if(p1.x==p2.x){ int min_y=Math.min(p1.y, p2.y); int max_y=Math.max(p1.y, p2.y); for(i=min_y+1;i<max_y;i++) if(a[p1.x][i]!=0) return false; if(i==max_y) return true; }else if(p1.y==p2.y){ int min_x=Math.min(p1.x, p2.x); int max_x=Math.max(p1.x, p2.x); for(i=min_x+1;i<max_x;i++) if(a[i][p1.y]!=0) return false; if(i==max_x) return true; } return false; } /* * 是否一个折线可以连通 */ public boolean isSingleBrokenLine(Point p1,Point p2){ int min_y=Math.min(p1.y, p2.y); int max_y=Math.max(p1.y, p2.y); int min_x=Math.min(p1.x, p2.x); int max_x=Math.max(p1.x, p2.x); Point tmp=new Point(); tmp.x=min_x; tmp.y=min_y; if(p1.equals(tmp)||p2.equals(tmp)){ boolean flag=true; if(a[min_x][max_y]!=0&&a[max_x][min_y]!=0) return false; else if(a[min_x][max_y]==0){ for(int i=min_y+1;i<max_y;i++){ if(a[min_x][i]!=0){ flag=false; break; } if(flag) for(int j=min_x+1;j<max_x;j++){ if(a[j][max_y]!=0){ flag=false; break; } } } if(flag){ /* for(int j=min_x+1;j<max_x;j++){ System.out.print(a[j][max_y]); } System.out.println("\n"); for(int i=min_y+1;i<max_y;i++){ System.out.print(a[min_x][i]); } System.out.println("\n");*/ return true; } } else if(a[max_x][min_y]==0){ flag=true; for(int i=min_y+1;i<max_y;i++){ if(a[max_x][i]!=0){ flag=false; break; } if(flag) for(int j=min_x+1;j<max_x;j++){ if(a[j][min_y]!=0){ flag=false; break; } } } if(flag){ /* for(int j=min_x+1;j<max_x;j++){ System.out.print(a[j][min_y]); } System.out.println("\n"); for(int i=min_y+1;i<max_y;i++){ System.out.print(a[max_x][i]); } System.out.println("\n");*/ return true; } } }else if(p1.x!=p2.x&&p1.y!=p2.y){ boolean flag=true; if(a[min_x][min_y]!=0&&a[max_x][max_y]!=0) return false; else if(a[min_x][min_y]==0){ for(int i=min_y+1;i<max_y;i++){ if(a[min_x][i]!=0){ flag=false; break; } if(flag) for(int j=min_x+1;j<max_x;j++){ if(a[j][min_y]!=0){ flag=false; break; } } } if(flag) return true; } else if(a[max_x][max_y]==0){ flag=true; for(int i=min_y+1;i<max_y;i++){ if(a[max_x][i]!=0){ flag=false; break; } if(flag) for(int j=min_x+1;j<max_x;j++){ if(a[j][max_y]!=0){ flag=false; break; } } } if(flag) return true; } } return false; } public boolean isDoubleBreakLine(Point p1,Point p2,Point p3){ boolean flag=false; if(p1.y==p2.y){ if(p1.x<p2.x) flag=horizonVerify(p1,p2,p3); else flag=horizonVerify(p2,p1,p3); }else if(p1.x==p2.x){ if(p1.y<p2.y) flag=verticalVerify(p1,p2,p3); else flag=verticalVerify(p2,p1,p3); }else { if(p1.x<p2.x) flag=horizonVerify(p1,p2,p3); else flag=horizonVerify(p2,p1,p3); if(!flag){ if(p1.y<p2.y) flag=verticalVerify(p1,p2,p3); else flag=verticalVerify(p2,p1,p3); }else return true; } return flag; } /* * 水平判定 */ private boolean horizonVerify(Point p1,Point p2,Point p3){ for(int i=0;i<colunm_len;i++){ if(i!=p1.y&&a[p1.x][i]==0){ Point p=new Point(p1.x,i); if(isSingleBrokenLine(p, p1)&&isSingleBrokenLine(p, p2)){ p3.x=p1.x; p3.y=i; return true; } } } return false; } /* * 垂直判定 */ private boolean verticalVerify(Point p1,Point p2,Point p3){ for(int i=0;i<row_len;i++){ if(i!=p1.x&&a[i][p1.y]==0){ Point p=new Point(i,p1.y); if(isSingleBrokenLine(p, p1)&&isSingleBrokenLine(p, p2)){ p3.x=p1.x; p3.y=i; return true; } } } return false; } }
难度系数控制: 行数: 5 列数 6 *1**2**3**4* 0 0 0 0 0 0 1 0 5 5 6 9 0 2 0 1 6 1 4 0 3 0 9 4 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 1 1 1 2 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 6 9 0 2 0 1 6 1 4 0 3 0 9 4 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 2 2 1 3 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 9 0 2 0 1 0 1 4 0 3 0 9 4 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 2 1 2 3 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 9 0 2 0 0 0 0 4 0 3 0 9 4 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 3 1 1 4 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 4 0 3 0 0 4 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 3 2 2 4 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 5 5 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 3 3 3 4 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0 输入选择的两个点的坐标值(以空格隔开,以0 0 0 0 结束) 0 0 0 0 *1**2**3**4* 0 0 0 0 0 0 1 0 0 0 0 0 0 2 0 0 0 0 0 0 3 0 0 0 0 0 0 0 0 0 0 0 0
结果中第一行是行号,第一列是列号,输入是坐标值,如果输入点的坐标值相同并且满足上面的三个情况之一,既可以消去,
并将值改为0.
当然程序也有不足之处,当出现死局时,应当重新将剩余的棋子摆盘。你还可以加上提示功能,对棋盘中非零的坐标点进行遍 历。当棋盘值全为零时,既可以获胜。如果向更加完善,加一个计时器来倒计时也可以增加趣味性。