写一个简易版的连连看

[url=http://yeepay-dev.iteye.com/blog/2059620]写一个简易版的连连看[/url]

游戏规则:

1.游戏棋盘大小为6X6的矩阵,共有6种颜色的图片

2.每次初始化随机填充棋盘,同一种颜色的格子数量必须为偶数个

3.同色两个格子无障碍连线不超过2个折点则允许消除

4.不需要做出图形界面,程序启动后生成的棋盘直接在控制以数字格式输出(格式见下方)

5.程序监听控制台输入(输入格式如:2,3;4,2),程序根据输入的坐标判断两个格子能否连接消除,如果满足条件则消除,否则给出相应提示

6.每次消除后控制台输出当前棋盘,并监听下次输入,直到全部消除

输出格式:数字表示不同颜色,0表示已消除的空格

0 0 0 4 0 0

1 0 4 2 1 0

0 0 3 0 2 0

0 5 3 0 0 0

0 0 5 0 0 0

0 0 0 0 0 0


package come.chenjo.linkgame;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Random;
/**
* 游戏区域类
* @author Jonathan Chen
*
*/
public class Chessboard {
//定义一个二维数组来表示游戏区域
private int[][] board;
//定义区域的大小
public static final int BOARD_SIZE = 6;
/**
* 初始化游戏区域
*/
public void initBoard(){
List<Integer> numbers = new ArrayList<Integer>();
//生成最初的6组数字,因为我发现完全靠随机有时会漏掉1-6中的某个数字
for(int i=0; i<6; i++){
numbers.add(i+1);
numbers.add(i+1);
}
//随机生成12组数字
Random random = new Random();
int temp = 0;
for(int i=0; i<12; i++){
temp = random.nextInt(6)+1;
numbers.add(temp);
numbers.add(temp);
}
//打乱次序
Collections.shuffle(numbers);
//初始化二维数组
board = new int[6][6];



temp=0;
for(int i=0; i<BOARD_SIZE; i++){
for(int j=0; j<BOARD_SIZE; j++){
board[j][i] = numbers.get(temp++).intValue();
}
}
}
/**
* 游戏区域坐标系的定义: 以左上角为原点, 从原点向右为X轴, 向下为Y轴
* 普通二维数组的控制台输出恰恰相反,以左上角为原点,从原点向右为Y轴(第二维度), 向下为X轴(第一维度)
* 为了统一二者的坐标系, 注意下面输出二维数组时有意对调了第一维度和第二维度
*/
public void printBoard(){
for(int i=0; i<BOARD_SIZE; i++){
for(int j=0; j<BOARD_SIZE; j++){
System.out.print(" " + board[j][i]);
}
System.out.println();
}
}

public static void main(String[] args){
Chessboard c = new Chessboard();
c.initBoard();
c.printBoard();
}

public void setBoard(int posX, int posY, int chessman){
this.board[posX][posY] = chessman;
}

public int[][] getBoard(){
return this.board;
}
}



package come.chenjo.linkgame;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* 简易版的连连看游戏
* @author Jonathan Chen
*
*/
public class LinkGame {
//图片一的x坐标
private int posX1 = 0;
//图片一的y坐标
private int posY1 = 0;
//图片二的x坐标
private int posX2 = 0;
//图片二的y坐标
private int posY2 = 0;
//定义游戏区域
private Chessboard chessboard;
/**
* 构造器, 初始化游戏区域
* @param chessboard
*/
public LinkGame(Chessboard chessboard){
this.chessboard = chessboard;
}
/**
* 检查用户输入是否合法
* @param inputStr 用户从控制台输入的字符串
* @return
*/
public boolean isValid(String inputStr){
String regex = "^\\d,\\d;\\d,\\d$";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(inputStr);
if(!m.find()){
chessboard.printBoard();
System.out.println("请输入图片的坐标,应以x1,y1;x2,y2的格式输入:");
return false;
}

String[] inputStrArr = inputStr.split(";");
String[] posStrArrA = inputStrArr[0].split(",");
String[] posStrArrB = inputStrArr[1].split(",");
try{
posX1 = Integer.parseInt(posStrArrA[0]) - 1;
posY1 = Integer.parseInt(posStrArrA[1]) - 1;
posX2 = Integer.parseInt(posStrArrB[0]) - 1;
posY2 = Integer.parseInt(posStrArrB[1]) - 1;

}catch(NumberFormatException e){
chessboard.printBoard();
System.out.println("请输入图片的坐标,应以x1,y1;x2,y2的格式输入:");
return false;
}
//检查输入数值是否在范围之内
if(posX1 < 0 || posX1 >= Chessboard.BOARD_SIZE
|| posY1 <0 || posY1 >= Chessboard.BOARD_SIZE
|| posX2 <0 || posX2 >= Chessboard.BOARD_SIZE
|| posY2 <0 || posY2 >= Chessboard.BOARD_SIZE){
System.out.println("X与Y坐标只能大于等于1,且小于等于" + Chessboard.BOARD_SIZE
+ ",请重新输入:");
return false;
}
//检查输入的位置是否已经没有图片
int[][] board = chessboard.getBoard();
if(board[posX1][posY1] == 0 || board[posX2][posY2] == 0){
System.out.println("此位置已不存在图片(非零数字),请重新输入:");
return false;
}
//检查输入的位置是否重复
if(posX1 == posX2 && posY1 == posY2){
System.out.println("两幅图片坐标相同,请重新输入:");
return false;
}
//检查输入的图片是否相同
if(board[posX1][posY1] != board[posX2][posY2]){
System.out.println("这两幅图片不相同,请重新输入:");
return false;
}

return true;
}
/**
* 开始游戏
* @throws Exception
*/
public void start() throws Exception{
// true表示游戏结束
boolean isOver = false;
chessboard.initBoard();
chessboard.printBoard();
System.out.println("请输入图片的坐标,应以x1,y1;x2,y2的格式输入:");
// 获取键盘输入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String inputStr = null;
// br.readLine: 每当用户从键盘输入一行按回车键, 则输入被br读取
while( (inputStr=br.readLine()) != null){
if(!isValid(inputStr)){
// 如果不合法, 则要求重新输入
continue;
}
//检测是否满足两图片间的连线的条件
if(isLink(posX1, posY1, posX2, posY2, chessboard.getBoard())){
//删除满足连线条件的两图片
removeLinkedImages(posX1, posY1, posX2, posY2);
chessboard.printBoard();
System.out.println("请输入图片的坐标,应以x1,y1;x2,y2的格式输入:");
//判断是否全部图片都以消除
if(isWon(chessboard.getBoard())){
//如果是则该场游戏结束
isOver = true;
}
}
else{
chessboard.printBoard();
System.out.println("不符合连线规则(最多两折三连线),请输入两幅图片的坐标:");
}
// 询问用户是否继续游戏
if (isOver) {
// 如果继续,重新初始化游戏区域,继续游戏
if (isReplay()) {
isOver = false;
chessboard.initBoard();
chessboard.printBoard();
continue;
}
// 如果不继续,则退出程序
break;
}
}
}
/**
* 判断游戏输赢
* @param board
* @return 如果全部图片都已消除(以0表示), 则返回真
*/
private boolean isWon(int[][] board) {
for(int i=0; i<board.length; i++){
for(int j=0; j<board[i].length; j++){
if(board[i][j] != 0){
return false;
}
}
}
return true;
}
/**
* 删除已连接的两图片
* @param posX1
* @param posY1
* @param posX2
* @param posY2
*/
public void removeLinkedImages(int posX1, int posY1, int posX2, int posY2){
this.chessboard.setBoard(posX1, posY1, 0);
this.chessboard.setBoard(posX2, posY2, 0);
}
/**
* 是否再次开始游戏
* @return
* @throws Exception
*/
public boolean isReplay() throws Exception {
String message = "恭喜您,您通过了!";
System.out.println(message + "再下一局?(y/n)");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
if(br.readLine().equals("y")){
return true;
}
return false;
}
/**
* 判断两图片能否相连
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
public boolean isLink(int posX1, int posY1, int posX2, int posY2, int[][] board){

//是否可以一直线相连
if(isLinkByOneLine(posX1, posY1, posX2, posY2, board)){
return true;
}
//是否可以两直线相连
if(isLinkByTwoLines(posX1, posY1, posX2, posY2, board)){
return true;
}
//是否可以三直线相连
if(isLinkByThreeLines(posX1, posY1, posX2, posY2, board)){
return true;
}
return false;
}
/**
* 判断在一列之内两图片之间是否全部是空白或直接相邻
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean containsAllOrNoneZeroInColumn(int posX1, int posY1, int posX2, int posY2, int[][] board){
//直接相连,因而不包含空白
if(Math.abs(posY1 - posY2) == 0){
return true;
}
int a = posY1 < posY2 ? posY1 : posY2;
int b = posY1 < posY2 ? posY2 : posY1;
for(int j=a+1; j < b; j++){
if(board[posX1][j] != 0){
return false;
}
}
return true;
}
/**
* 判断在一行之内两图片之间是否全部是空白或直接相邻
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean containsAllOrNoneZeroInRow(int posX1, int posY1, int posX2, int posY2, int[][] board){
//直接相连,因而不包含空白
if(Math.abs(posX1 - posX2) == 0){
return true;
}
int a = posX1 < posX2 ? posX1 : posX2;
int b = posX1 < posX2 ? posX2 : posX1;
for(int i=a+1; i < b; i++){
if(board[i][posY1] != 0){
return false;
}
}
return true;
}
/**
* 是否可以一直线相连
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isLinkByOneLine(int posX1, int posY1, int posX2, int posY2, int[][] board){

if(posX1 != posX2 && posY1 != posY2){
return false;
}
if(posX1 == posX2){
if(containsAllOrNoneZeroInColumn(posX1, posY1, posX2, posY2, board)){
return true;
}
}
if(posY1 == posY2){
if(containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY2, board)){
return true;
}
}
return false;
}
/**
* 是否可以两直线相连
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isLinkByTwoLines(int posX1, int posY1, int posX2, int posY2, int[][] board){
if(posX1 != posX2 && posY1 != posY2){
//x1,y1 to x2,y1 to x2,y2 row+col
if(containsAllOrNoneZeroInRow(posX1, posY1, posX2, posY1, board)
&& board[posX2][posY1] == 0
&& containsAllOrNoneZeroInColumn(posX2, posY1, posX2, posY2, board)){
return true;
}
//x1,y1 to x1,y2 to x2,y2 col+row
if(containsAllOrNoneZeroInColumn(posX1, posY1, posX1, posY2, board)
&& board[posX1][posY2] == 0
&& containsAllOrNoneZeroInRow(posX1, posY2, posX2, posY2, board)){
return true;
}

}
return false;
}
/**
* 是否可以三直线相连
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isLinkByThreeLines(int posX1, int posY1, int posX2, int posY2, int[][] board){
if(isOnSameEdge(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnThreeLinesLikeArc(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnThreeLinesLikeZigzag(posX1, posY1, posX2, posY2, board)){
return true;
}
return false;
}
/**
* 是否可以三直线相连,似U形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isOnThreeLinesLikeArc(int posX1, int posY1, int posX2, int posY2, int[][] board) {
if(isOnUpArc(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnDownArc(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnLeftArc(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnRightArc(posX1, posY1, posX2, posY2, board)){
return true;
}
return false;
}

/**
* 是否可以三直线相连,似向上弓形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
/*
----
| |
| |

*/
private boolean isOnUpArc(int posX1, int posY1, int posX2, int posY2, int[][] board) {
// Y --> 0
int lessY = posY1 < posY2 ? posY1 : posY2;
for(int j = lessY - 1; j >= 0; j--){
if(containsAllOrNoneZeroInRow(posX1, j, posX2, j, board)
&& containsAllOrNoneZeroInColumn(posX1, posY1, posX1, j, board)
&& containsAllOrNoneZeroInColumn(posX2, posY2, posX2, j, board)
&& board[posX1][j] == 0
&& board[posX2][j] == 0){
return true;
}
}

if( isOnSameEdge(posX1, 0, posX2, 0, board)
&& containsAllOrNoneZeroInColumn(posX1, posY1, posX1, 0, board)
&& containsAllOrNoneZeroInColumn(posX2, posY2, posX2, 0, board)
&& (board[posX1][0] == 0 && board[posX2][0] == 0
|| board[posX1][0] == 0 && board[posX2][0] == board[posX2][posY2]
|| board[posX1][0] == board[posX1][posY1] && board[posX2][0] == 0)){
return true;
}

return false;
}
/**
* 是否可以三直线相连,似向下弓形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
/*

| |
| |
----
*/
private boolean isOnDownArc(int posX1, int posY1, int posX2, int posY2, int[][] board){
int moreY = posY1 < posY2 ? posY2 : posY1;
for(int j = moreY + 1; j <= Chessboard.BOARD_SIZE - 1; j++){
if(containsAllOrNoneZeroInRow(posX1, j, posX2, j, board)
&& containsAllOrNoneZeroInColumn(posX1, posY1, posX1, j, board)
&& containsAllOrNoneZeroInColumn(posX2, posY2, posX2, j, board)
&& board[posX1][j] == 0
&& board[posX2][j] == 0){
return true;
}
}
if( isOnSameEdge(posX1, Chessboard.BOARD_SIZE - 1, posX2, Chessboard.BOARD_SIZE - 1, board)
&& containsAllOrNoneZeroInColumn(posX1, posY1, posX1, Chessboard.BOARD_SIZE - 1, board)
&& containsAllOrNoneZeroInColumn(posX2, posY2, posX2, Chessboard.BOARD_SIZE - 1, board)
&& (board[posX1][Chessboard.BOARD_SIZE - 1] == 0 && board[posX2][Chessboard.BOARD_SIZE - 1] == 0
|| board[posX1][Chessboard.BOARD_SIZE - 1] == board[posX1][posY1] && board[posX2][Chessboard.BOARD_SIZE - 1] == 0
|| board[posX1][Chessboard.BOARD_SIZE - 1] == 0 && board[posX2][Chessboard.BOARD_SIZE - 1] == board[posX2][posY2])){
return true;
}
return false;
}
/**
* 是否可以三直线相连,似向左弓形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
/*
---
|
|
---
*/
private boolean isOnLeftArc(int posX1, int posY1, int posX2, int posY2, int[][] board) {
int lessX = posX1 < posX2 ? posX1 : posX2;
for(int i = lessX - 1; i >= 0; i--){
if(containsAllOrNoneZeroInColumn(i, posY1, i, posY2, board)
&& containsAllOrNoneZeroInRow(i, posY1, posX1, posY1, board)
&& containsAllOrNoneZeroInRow(i, posY2, posX2, posY2, board)
&& board[i][posY1] == 0
&& board[i][posY2] == 0){
return true;
}
}

if( isOnSameEdge(0, posY1, 0, posY2, board)
&& containsAllOrNoneZeroInRow(0, posY1, posX1, posY1, board)
&& containsAllOrNoneZeroInRow(0, posY2, posX2, posY2, board)
&& (board[0][posY1] == 0 && board[0][posY2] == 0
|| board[0][posY1] == board[posX1][posY1] && board[0][posY2] == 0
|| board[0][posY1] == 0 && board[0][posY2] == board[posX2][posY2])){
return true;
}

return false;
}
/**
* 是否可以三直线相连,似向右弓形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
/*
---
|
|
---
*/
private boolean isOnRightArc(int posX1, int posY1, int posX2, int posY2, int[][] board) {
int moreX = posX1 < posX2 ? posX2 : posX1;
for(int i = moreX + 1; i <= Chessboard.BOARD_SIZE - 1; i++){
if(containsAllOrNoneZeroInColumn(i, posY1, i, posY2, board)
&& containsAllOrNoneZeroInRow(i, posY1, posX1, posY1, board)
&& containsAllOrNoneZeroInRow(i, posY2, posX2, posY2, board)
&& board[i][posY1] == 0
&& board[i][posY2] == 0){
return true;
}
}

if(
isOnSameEdge(Chessboard.BOARD_SIZE - 1, posY1, Chessboard.BOARD_SIZE - 1, posY2, board)
&& containsAllOrNoneZeroInRow(posX1, posY1, Chessboard.BOARD_SIZE - 1, posY1, board)
&& containsAllOrNoneZeroInRow(posX2, posY2, Chessboard.BOARD_SIZE - 1, posY2, board)
&& (board[Chessboard.BOARD_SIZE - 1][posY1] == 0 && board[Chessboard.BOARD_SIZE - 1][posY2] == 0
|| board[Chessboard.BOARD_SIZE - 1][posY1] == board[posX1][posY1] && board[Chessboard.BOARD_SIZE - 1][posY2] == 0
|| board[Chessboard.BOARD_SIZE - 1][posY1] == 0 && board[Chessboard.BOARD_SIZE - 1][posY2] == board[posX2][posY2])){
return true;
}

return false;
}
/**
* 是否可以三直线相连,似之字形
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isOnThreeLinesLikeZigzag(int posX1, int posY1, int posX2, int posY2, int[][] board) {
if(isOnZigzagWith1Row2Cols(posX1, posY1, posX2, posY2, board)){
return true;
}
if(isOnZigzagWith2Rows1Col(posX1, posY1, posX2, posY2, board)){
return true;
}

return false;
}
/**
* 是否可以三直线相连,似之字形, 两行一列
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isOnZigzagWith2Rows1Col(int posX1, int posY1, int posX2, int posY2, int[][] board) {
int moreX = posX1 < posX2 ? posX2 : posX1;
int lessX = posX1 < posX2 ? posX1 : posX2;
for(int i = lessX + 1; i < moreX; i++){
if(containsAllOrNoneZeroInColumn(i, posY1, i, posY2, board)
&& containsAllOrNoneZeroInRow(i, posY1, posX1, posY1, board)
&& containsAllOrNoneZeroInRow(i, posY2, posX2, posY2, board)
&& board[i][posY1] == 0
&& board[i][posY2] == 0){
return true;
}
}
return false;
}
/**
* 是否可以三直线相连,似之字形, 一行两列
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isOnZigzagWith1Row2Cols(int posX12, int posY12, int posX22,
int posY22, int[][] board) {
int moreY = posY1 < posY2 ? posY2 : posY1;
int lessY = posY1 < posY2 ? posY1 : posY2;
for(int j = lessY + 1; j < moreY; j++){
if(containsAllOrNoneZeroInRow(posX1, j, posX2, j, board)
&& containsAllOrNoneZeroInColumn(posX1, posY1, posX1, j, board)
&& containsAllOrNoneZeroInColumn(posX2, posY2, posX2, j, board)
&& board[posX1][j] == 0
&& board[posX2][j] == 0){
return true;
}
}
return false;
}
/**
* 是否处于游戏区域的4条边的同一边上
* @param posX1 图片一的x坐标
* @param posY1 图片一的y坐标
* @param posX2 图片二的x坐标
* @param posY2 图片二的y坐标
* @param board 游戏区域
* @return
*/
private boolean isOnSameEdge(int posX1, int posY1, int posX2, int posY2, int[][] board){
if((posY1 == posY2 && posY2 == 0)
|| (posY1 == posY2 && posY2 == Chessboard.BOARD_SIZE - 1)
|| (posX1 == posX2 && posX2 == 0)
|| (posX1 == posX2 && posX2 == Chessboard.BOARD_SIZE - 1)){
return true;
}

return false;
}

public static void main(String[] args) throws Exception{
LinkGame lg = new LinkGame(new Chessboard());
lg.start();
}
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值