看到师兄在玩连连看的游戏,于是乎突然想写一个自己的连连看游戏。我写的这个没有界面,只是一个控制台演示版,当然在这个基础上,用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.
当然程序也有不足之处,当出现死局时,应当重新将剩余的棋子摆盘。你还可以加上提示功能,对棋盘中非零的坐标点进行遍 历。当棋盘值全为零时,既可以获胜。如果向更加完善,加一个计时器来倒计时也可以增加趣味性。