📄 model.java
字号:
/*
* Created on 2005-3-15
*/
package jcase.lianliankan;
/**
* @author javacat
* This is the puzzle model
*/
public class Model {
// empty character
public static final char EMPTY = 0;//'-';
public static final char PLACEHOLDER = '-';
public static final char[] CHARSETS = new char[]{
'0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z'
};
private char[][] matrix;
private int columns,rows,count;
private int emptyCount=0;
private int[] nextPair;
public int getColumns(){
return columns;
}
public int getRows(){
return rows;
}
/**
* 得到指定位置的字符。
* @param x
* @param y
* @return
*/
public char getChar(int x, int y){
try {
return matrix[x][y];
} catch (IndexOutOfBoundsException e) {
e.printStackTrace();
return EMPTY;
}
}
/**
* 根据指定的字符串行创建model。
* 这种创建方式用于前期测试或者从文件读入游戏。
* 参考随机生成model的方法
* @param lines
* @return
*/
public static Model createModel(String[] lines){
int h=lines.length;
int w=lines[0].length();
char[][] matrix = new char[w][h];
for(int i=0;i<h;i++){
for(int j=0;j<w;j++){
matrix[j][i] = lines[i].charAt(j);
if(matrix[j][i]==PLACEHOLDER){
matrix[j][i]=EMPTY;
}
}
}
return new Model(matrix);
}
/**
* 随机产生model
* @param columns--盘面列数,因为第一列和最后一列是空的,所以model的字符数组列数应该是这个值+2.
* @param rows --盘面行数,因为第一行和最后一行是空的,所以model的字符数组行数应该是这个值+2.
*/
public static Model createRandomModel(int columns,int rows){
char[][] matrix = new char[columns+2][rows+2];
int len=CHARSETS.length;
int size = columns*rows;
int half=size/2;
char[] chars = new char[size];
for(int i=0;i<half;i++){
chars[i]=CHARSETS[(int)(len*Math.random())];
chars[half+i]=chars[i];
}
int repeat = (int)(size*Math.random());
int pos1,pos2;
char tmp;
for(int i=0;i<repeat;i++){
pos1= (int)(size*Math.random());
pos2=(int)(size*Math.random());
tmp=chars[pos2];
chars[pos2]=chars[pos1];
chars[pos1]=tmp;
}
for(int i=0;i<rows;i++){
for(int j=0;j<columns;j++){
matrix[j+1][i+1]=chars[i*columns+j];
}
}
return new Model(matrix);
}
public Model(char[][] matrix){
this.matrix = matrix;
columns = matrix.length;
rows = matrix[0].length;
count = columns*rows;
countEmpty();
}
/**
* 试图消除指定位置的两个目标
* 如果这两个目标之间有通路,则消除之,并且返回扫描到的x或者y轴坐标,
* 否则返回null
*/
public int[] defuse(int x1,int y1,int x2,int y2){
int[] path=getPath(x1,y1,x2,y2);
if(path!=null){
matrix[x1][y1]=EMPTY;
matrix[x2][y2]=EMPTY; //empty two puzzle
emptyCount+=2;
}
return path;
}
/**
* Check the specified two cells could be linked or not.
* If there's a path, return the axis
*/
protected int[] getPath(int x1,int y1, int x2, int y2){
if(x1==x2 && y1==y2){
return null;
}
if(matrix[x1][y1]!=matrix[x2][y2]){
return null;
}
if(matrix[x1][y1]==EMPTY){
return null;
}
if(matrix[x2][y2]==EMPTY){
return null;
}
int x,y,step;
//scan horizental
for(x=0;x<getColumns();x++){
// (x1,y1) --> (x,y1)
boolean breaked=false;
for(step=Math.min(x,x1);step<=Math.max(x,x1);step++){
if(step==x1) continue; //do not check(x1,y2)
if(matrix[step][y1]!=EMPTY){
breaked=true;
break;
}
}
if(breaked){
continue;
}
// (x,y1) --> (x,y2)
for(step=Math.min(y1,y2)+1;step<Math.max(y1,y2);step++){
if(matrix[x][step]!=EMPTY){
breaked=true;
break;
}
}
if(breaked){
continue;
}
// (x,y2) --> (x2,y2)
for(step=Math.min(x,x2);step<=Math.max(x,x2);step++){
if(step==x2) continue; //do not check (x2,y2)
if(matrix[step][y2]!=EMPTY){
breaked=true;
break;
}
}
if(!breaked){
//record two point (x,y1),(x,y2)
int[] rec=new int[]{x,-1};
return rec;
}
}
//if horizental scan finished and have not find a path,
//then scan vertical
for(y=0;y<getRows();y++){
boolean breaked = false;
// (x1,y1) --> (x1,y)
for(step=Math.min(y,y1);step<=Math.max(y,y1);step++){
if(step==y1) continue; //do not check (x1,y1)
if(matrix[x1][step]!=EMPTY){
breaked = true;
break;
}
}
if(breaked){
continue;
}
// (x1,y) --> (x2,y)
for(step=Math.min(x1,x2)+1;step<Math.max(x1,x2);step++){
if(matrix[step][y]!=EMPTY){
breaked=true;
break;
}
}
if(breaked){
continue;
}
// (x2,y) --> (x2,y2)
for(step=Math.min(y,y2);step<=Math.max(y,y2);step++){
if(step==y2) continue ; //do not check (x2,y2)
if(matrix[x2][step]!=EMPTY){
breaked = true;
break;
}
}
if(!breaked){
//record two point (x1,y),(x2,y)
int[] rec=new int[]{-1,y};
return rec;
}
}
return null;
}
/**
* 检查是否过关(牌都消掉了)
*/
public boolean isAllDefused(){
return (count-countEmpty())==0;
}
/**
* 检查是否还有可以消除的格子
* @return 如果还有可以消除的则返回true,否则返回false
*/
public boolean check(){
return check(0);
}
/**
* 洗牌
*/
public void wash(){
int cln=columns-2;
int size = cln*(rows-2);
int repeat = (int)(size*Math.random());
int x1,y1,x2,y2,pos1,pos2;
char tmp;
for(int i=0;i<repeat;i++){
pos1= (int)(size*Math.random());
pos2=(int)(size*Math.random());
x1=pos1%cln+1;
y1=pos1/cln+1;
x2=pos2%cln+1;
y2=pos2/cln+1;
tmp=matrix[x2][y2];
matrix[x2][y2]=matrix[x1][y1];
matrix[x1][y1]=tmp;
}
}
private boolean check(int index){
int y=index/columns;
int x=index%columns;
for(int i=index+1;i<count;i++){
if(getPath(x,y,i%columns,i/columns)!=null){
//找到一对可以消除的,记录其坐标
nextPair = new int[4];
nextPair[0]=x;
nextPair[1]=y;
nextPair[2]=i%columns;
nextPair[3]=i/columns;
return true;
}
}
index++;
if(index< (count-1)){
return check(index);
}
nextPair=null;
return false;
}
private int countEmpty(){
if(emptyCount==0){
for(int j=0;j<rows;j++){
for(int i=0;i<columns;i++){
if(matrix[i][j]==EMPTY)
emptyCount++;
}
}
}
return emptyCount;
}
/**
* 得到下一对可以消除的目标,通常用于提示用户
*/
public int[] getNextPair(){
return nextPair;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -