最近做了一个不是图形界面的连连看小游戏,如果后期加上图片之类的估计会更美观些,将代码分享出来。。
感觉比较难的是关于那个三线连消除的部分,想的有些费力,不过想通了就好了,其中还会有一些需要考虑行遍历还是列遍历,怎么遍历之类的问题,主要还是要屡清楚思路,不然会被绕进去的。
一线连:
其实一线连是最简单易实现的,但又确实2,3连的基础。
一线连要考虑的是(1)行相等还是列相等(2)遍历的其实条件和结束条件,也即是求着同行(或同列)的最大值,最小值。(3)for循环遍历是否为零即可,这一点有可以分成两种方法:一,可以判断数组每个元素是否都为0,。二,或者判断两点间的和是否为零。
二线连:
有了一线连的基础,二线连就相对简单易想了,既是两个一线连,再加过渡点为零即可。
三线连:
最最头痛的三线连,不过想想也还不算难,既是以p1点为标准,对其行遍历寻找出一点(1)该点为零(2)与p1点一连线为真,与p2二连线也为真;
行遍历要从0,到a[].length,这一点上我被坑了下,如果不是完全遍历,是会漏掉很多情况的。之后列遍历也一样~
还有一点事关于棋盘生成的,棋盘生成是数组两两赋值,然后再打乱,在这里,打乱的时候我采取的办法是,随机生成4个数,作为两个数的下表,在交换这两个数,循环的次数大一点就可以达到目的了。
其他的地方都还比较一般,写出来比较顺利。而且大部分也都写了注释。
package com.nh;
import java.util.Scanner;
import java.util.Random;
import com.nh.Point;
public class chess{
public static void main(String[] agrs ){
Scanner sc=new Scanner(System.in);
System.out.println("请选择行数(row):");
int row=sc.nextInt();
int col;
do{
System.out.println("请选择行数(col)(请填写偶数哟!~):");//确保输出的棋盘是偶数,可以完全消除;
col=sc.nextInt();
}while(col%2!=0);
System.out.println("请选择难度指数:");
int degree=sc.nextInt();
//生成棋盘
int[][] chess=new int[row][col];
//给棋盘中的位置赋值;
assign(chess,degree);
//打乱棋盘中两两相邻是一样的数的状态;
Randomchess(chess); //乱序棋盘已生成
System.out.println("游戏开始");
//输出已生成的棋盘;
printArray(chess);
//定义两个点:方便之后的判断工作
Point p1=new Point();
Point p2=new Point();
boolean isGameOver=false;
//循环输入两个数,并且执行判断;
do{
System.out.println("请输入要消除的两数字的行号和列号(格式为:x1 y1 x2 y2)");
p1.x=sc.nextInt();
p1.y=sc.nextInt();
p2.x=sc.nextInt();
p2.y=sc.nextInt();
//1.先用isEliminate对输入的点是否可以消除进行判断;
int num=isEliminate(chess,p1,p2);
switch( num ){
case 1:
System.out.println("两点的位置不可已相同!");break;
case 2:
System.out.println("您输入的两点的值不等,请重新输入!");break;
case 3:
//2.判断的输入的点符合条件后对数组进行赋值为零的操作;
chess[p1.x][p1.y]=0;
chess[p2.x][p2.y]=0;
//3.进行游戏结束的判断
isGameOver=checkGame(chess);break;
case 4:
System.out.println("对不起输入有误!请重新尝试!");break;
}
printArray(chess);
}while(!isGameOver);//注意:如果用do while结构while中的内容是不成立的条件。并且若表示条件并列不成立要用&&
System.out.println("恭喜通过!");
}
//对棋盘赋值;但并不打乱
public static void assign(int[][] a,int degree){
Random r=new Random();
int row=a.length;
int col=a[0].length;
for(int i=0;i<row;i++){
//对边框赋值为零
if(i==0||i==row-1){
for(int j=0;j<col;j++){
a[i][j]=0;
}
}else{
for(int j=0;j<col;){
//对边框赋值为零
if(j==0||j==col-1){
a[i][j]=0;
j++;
}else{
//对其他值随机赋值
a[i][j]=r.nextInt(degree)+1;
if(a[i][j]==0){
a[i][j]+=1;
}
a[i][j+1]=a[i][j];
j+=2;
}
}
}
}
}
//对已经生成的棋盘打乱顺序
public static void Randomchess(int[][] a){
Random r=new Random();
int row=a.length;
int col=a[0].length;
for(int i=0;i<row*col*10;i++){
int x1=r.nextInt( row-2 )+1;
int y1=r.nextInt( col-2 )+1;
int x2=r.nextInt( row-2 )+1;
int y2=r.nextInt( col-2 )+1;
int temp=a[x1][y1];
a[x1][y1]=a[x2][y2];
a[x2][y2]=temp;
}
}
public static void printArray(int[][] a){
int row=a.length;
int col=a[0].length;
showColsNum(col);
for(int i=0;i<row;i++){
//如果是第零行和最末行就输出边框:
if(i==0||i==row-1){
//输出行号
System.out.print(" \t");
for(int j=0;j<col;j++){
System.out.print("#\t");
}
System.out.println("\t ");
}else{
//其他的就照常输出
//输出行号
System.out.print(i+"\t");
for(int j=0;j<col;j++){
//但正常输出元素之前,列号为0和col-1的也应输出的是边框;
if(j==0||j==col-1){
System.out.print("#\t");
}else{
//对内部已经消除的元素清空输出:
if(a[i][j]==0){
System.out.print("\t");
}else{
System.out.print(a[i][j]+"\t");
}
}
}
System.out.println("\t"+i);
}
}
showColsNum(col);
}
//显示列号:
public static void showColsNum(int col){
System.out.print(" \t \t");
for( int i=1;i<col-1;i++){
System.out.print("*"+i+"*\t");
}
System.out.println();
}
public static int isEliminate(int[][] a,Point p1,Point p2){
//1。判断两点不是统一个点:
if( p1.equals( p2 ) ){
return 1;
}
//2.两点的值是否相同:
if( a[p1.x][p1.y]!=a[p2.x][p2.y] ){
return 2;
}
//3.判断两点之间的连线情况:
if( doOneLine(a,p1,p2) || doTwoLine(a,p1,p2) || doThreeLine(a,p1,p2) ) {
return 3;
}
return 4;
}
public static boolean doOneLine(int[][] a,Point p1,Point p2){
//定义最大值,最小值
int max;
int min;
//判断是循环列还是循环行
if(p1.x==p2.x){
max=Max(p1.y,p2.y);
min=Min(p1.y,p2.y);
return RunRowCheck(a,p1.x,max,min);
}
if( p1.y==p2.y ){
max=Max(p1.x,p2.x);
min=Min(p1.x,p2.x);
return RunColCheck(a,p1.y,max,min);
}
return false;
}
//循环行判断是否连线处都是零;
public static boolean RunRowCheck(int[][] a,int x,int max,int min){
int sum=0;
for(int i=min+1;i<max;i++){
sum=sum+a[i][x];
}
if(sum==0){
return true;
}
return false;
}
//循环列判断是否连线处都是零;
public static boolean RunColCheck(int[][] a,int x,int max,int min){
int sum=0;
for(int i=min+1;i<max;i++){
sum=sum+a[x][i];
}
if(sum==0){
return true;
}
return false;
}
//判断最大值
public static int Max(int x,int y){
if(x>y){
return x;
}else{
return y;
}
}
//判断最小值
public static int Min(int x,int y){
if(x>y){
return y;
}else{
return x;
}
}
//2连线
public static boolean doTwoLine(int[][] a,Point p1,Point p2){
Point p3=new Point();
int max;
int min;
int num=1;
//判断是循环列还是循环行
//两种情况:1.p3.x=p1.x;p3.y=p2.y
// 2。p3.x=p2.x;p3.y=p1.y
//1:p3.x=p1.x;p3.y=p2.y
p3.x=p1.x;
p3.y=p2.y;
if(a[p3.x][p3.y]==0){
//先判断p3与p1(列相同):
max=Max(p1.y,p3.y);
min=Min(p1.y,p3.y);
if(RunColCheck(a,p1.x,max,min)){
//继续判断p2和p3(行相同)
max=Max(p3.x,p2.x);
min=Min(p3.x,p2.x);
if(RunRowCheck(a,p3.y,max,min)){
return true;
}
}
}
p3.y=p1.y;
p3.x=p2.x;
if( a[p3.x][p3.y]==0 ){
//先判断p3与p1(行相同):
max=Max(p1.x,p3.x);
min=Min(p1.x,p3.x);
if(RunRowCheck(a,p1.y,max,min)){
//继续判断p2和p3(列相同)
max=Max(p3.y,p2.y);
min=Min(p3.y,p2.y);
return RunColCheck(a,p3.x,max,min);
}
return false;
}
return false;
}
//3连线
public static boolean doThreeLine(int[][] a,Point p1,Point p2){
Point p3=new Point();
Point p4=new Point();
// 边框消除:
if( (p1.x==p2.x&&p1.x==1) || (p1.y==p2.y&&p1.y==1) ){
return true;
}else{
//内部消除
//行遍历:
for(int i=0;i<a.length;i++){
p3.y=p1.y;
p3.x=i;
if(a[p3.x][p3.y]==0){
if( doOneLine(a,p1,p3) ){
if( doTwoLine(a,p3,p2) ){
return true;
}
}
}
}
//列遍历
for(int j=0;j<a[0].length;j++){
p3.x=p1.x;
p3.y=j;
if(a[p3.x][p3.y]==0){
if(doOneLine(a,p1,p3)){
if( doTwoLine(a,p3,p2) ){
return true;
}
}
}
}
return false;
}
}
public static void Swap(Point p1,Point p2){
Point temp=new Point();
temp=p1;
p1=p2;
p2=temp;
}
public static boolean checkGame(int[][] a){
int sum=0;
for(int i=0;i<a.length;i++){
for(int j=0;j<a[0].length;j++){
//1.按照垂直方向:
sum=sum+a[i][j];
}
}
if(sum==0){
return true;
}else{
return false;
}
}
}
下面是定义的一个Point类:
package com.nh;
public class Point{
public int x;
public int y;
public boolean equals(Point p1){
if(this.x==p1.x&&this.y==p1.y){
return true;
}else{
return false;
}
}
}