连连看小游戏很考验逻辑算法基本功,这里我写了个控制台的简易版本,注释都有,逻辑思想可供大家参考
思路:
1 获得一个连连看的初始棋盘
2 棋盘保存的是一个二维数组
3 设置图形的种类数(例:level=5)
4 往二维数组里随机插入1到5,并要求为偶数个
5 判断消除条件(边界消除,直线消除,一折消除,两折消除
import java.util.Random;
import java.util.Scanner;
public class linklinkLook {
int rows;
int cols;
int level = 5;// 图像的种类数
int [] [] checkboard; // 棋盘
public void init() {
//让用户输入行数和列数(行列至少有一个为偶数)
Scanner sc = new Scanner(System.in);
do {
System.out.println("请输入棋盘行数和列数");
rows = sc.nextInt();
cols = sc.nextInt();
} while(rows * cols % 2 != 0);
// 初始化棋盘
checkboard = new int[rows][cols];
// 生成棋盘,将指定范围的数字随机生成后放到棋盘中。要求随机乱序,要求数字是成对的
Random rd = new Random();
int num = 0;
if (rows % 2 == 0) {
// 说明行数为偶数
for(int i = 0; i < rows; i += 2) {
for (int j = 0; j < cols; j ++) {
num = rd.nextInt(level) + 1; // [0, 5) + 1 后为[1, 6)转化成int就是[1, 5]
checkboard[i][j] = num;
checkboard[i + 1][j] = num;
}
}
return;
}
// 如果行不是偶数,那么列肯定是偶数
for (int i = 0; i < rows; ++ i) {
for (int j = 0; j < cols; ++ j) {
num = rd.nextInt(level) + 1;
checkboard[i][j] = num;
checkboard[i][ ++ j] = num;
}
return;
}
}
public void shuffle() {
int x1, x2, y1, y2, temp;
for(int i = 0; i < rows * cols * level; ++ i) {
x1 = (int)(Math.random()*rows);
x2 = (int)(Math.random()*rows);
y1 = (int)(Math.random()*cols);
y2 = (int)(Math.random()*cols);
temp = checkboard[x1][y1];
checkboard[x1][y1] = checkboard[x2][y2];
checkboard[x2][y2] = temp;
}
}
public void show() {
System.out.print(" ");
for (int i = 1; i <= cols; ++ i) {
System.out.print("*" + i + "* ");
}
System.out.println("n");
for (int i = 0; i < rows; ++ i) {
for (int j = 0; j < cols; ++ j) {
if (j == 0) {// 说明是第一列
System.out.print("*" + (i + 1) + "* ");
}
if(checkboard[i][j] == 0) {// 说明这个位置已经消除
System.out.print(" ");
}else {
System.out.print(checkboard[i][j] + " ");
}
}
System.out.print("*" + (i + 1) + "*nn");
}
System.out.print(" ");
for (int i = 1; i <= cols; ++ i) {
System.out.print("*" + i + "* ");
}
System.out.println("n");
}
public void startGame() {
int x1, y1, x2, y2;
Scanner sc = new Scanner(System.in);
do {
System.out.println("请输入要消除的两个点的坐标(0 0 0 0):");
x1 = sc.nextInt() - 1;
y1 = sc.nextInt() - 1;
x2 = sc.nextInt() - 1;
y2 = sc.nextInt() - 1;
// 消除规则,初始校验 :两个位置的值是否相等,检查是否越界,是否是同一个点
if(x1 < 0 || x1 >= rows || x2 < 0 || x2 >= rows || y1 < 0 || y1 >= cols || y2 < 0 || y2 >= cols) {
System.out.println("越界。。。");
continue;
}
if(x1 == x2 && y1 == y2) {
System.out.println("同一个点不能消除。。。");
continue;
}
if(checkboard[x1][y1] != checkboard[x2][y2]) {
System.out.println("图形不同不能消除。。。");
continue;
}
// 是否能边界消除、直线消除、一折消除、两折消除
if(checkBound(x1, y1, x2, y2) || checkonLine(x1, y1, x2, y2) || checkoneTurn(x1, y1, x2, y2)
|| checkTwoTurn(x1, y1, x2, y2)) {
checkboard[x1][y1] = 0;
checkboard[x2][y2] = 0;
show(); //刷新棋盘
continue;
}
}while(!checkGameOver());
}
private boolean checkBound(int x1, int y1, int x2, int y2) {
if(x1 == x2 && (x1 == 0 || x1 == rows - 1)) {
return true;
}
if(y1 == y2 && (y1 == 0 || y1 == cols - 1)) {
return true;
}
return false;
}
private boolean checkonLine(int x1, int y1, int x2, int y2) {
if(x1 == x2) { // 同行
int min = y1 > y2 ? y2 : y1;
int max = y1 > y2 ? y1 : y2;
for (int i = min + 1; i < max; ++ i) {
if (checkboard[x1][i] != 0) {
return false;
}
}
return true;
}
if(y1 == y2) { // 同列
int min = x1 > x2 ? x2 : x1;
int max = x1 > x2 ? x1 : x2;
for (int i = min + 1; i < max; ++ i) {
if (checkboard[i][y1] != 0) {
return false;
}
}
return true;
}
return false;
}
private boolean checkoneTurn(int x1, int y1, int x2, int y2) {
// 一折消除
if(checkboard[x1][y2] == 0 && checkonLine(x1,y1,x1,y2)&&checkonLine(x2,y2,x1,y2)) {
// 与x1,y1同行,与x2,y2同列
return true;
}if(checkboard[x2][y1]==0 && checkonLine(x1,y2,x2,y1)&&checkonLine(x2,y2,x2,y1)) {
return true;
}
return false;
}
private boolean checkTwoTurn(int x1, int y1, int x2, int y2) {
boolean flag1 = true;
boolean flag2 = true;
// 两个折点在同一列平移判断
for(int i = 1; i < cols + 1; ++ i) {
if(i==y1|i==y2) {
++ i;
}
if(checkonLine(x1,y1,x1,i)&&checkonLine(x2,y2,x2,i)&&checkonLine(x1,i,x2,i)) {
// 说明能消,直接返回true
return true;
}
flag1 = false;// 折点在同一列能消失败了
}
// 两个折点在同一行平移判断
for(int i = 1; i < rows + 1; ++ i) {
if(i==x1|i==x2) {
++ i;
}
if(checkonLine(x1,y1,y1,i)&&checkonLine(x2,y2,y2,i)&&checkonLine(y1,i,y2,i)) {
// 说明能消,直接返回true
return true;
}
flag2 = false;// 折点在同一行能消失败了
}
return flag1||flag2;
}
public boolean checkGameOver(){
for(int [] arr: checkboard) {
for(int num : arr) {
if(num != 0) {
return false;
}
}
}
System.out.println("恭喜通关!!!");
return true;
}
public static void main(String[] args) {
linklinkLook lll = new linklinkLook();
lll.init();
lll.shuffle();
lll.show();
lll.startGame();
}
}
值得注意的一点,以上设计并没有包括死局的判断,感兴趣的小伙伴可以自行拓展 需要用到链表结构,字典结构,结合泛型来实现(有向邻接表思想)
死局例如:



