果蔬连连看

[size=xx-large]果蔬连连看[/size]
[size=x-large]
像连连看、扫雷、五子棋等游戏从小就玩,我最爱玩的就是连连看了,闲下来就玩,连连看有很多种,像是宠物、石头、麻将、果蔬连连看等等,我最喜欢的还是果蔬连连看。当我们要做这个项目时,我第一个想做的就是连连看。
其实这些游戏刚开始的做法都差不多,它们都是棋盘类游戏,就要先做一个界面,然后在画布上把棋盘画出来,有了前面的学习基础,这一步就很简单了。做这类游戏,最难的就是算法了。想连连看的算法,一定要事先想清楚,图片是怎样消掉的。还要清楚一点就是图片的消失只是一个表象,在幕后是操作数组。下面就是我做的果蔬连连看,一起看看吧。[/size]

[size=x-large]
首先,要先做一个界面,然后将棋盘画在画布上。
关于界面的做法,之前的几个项目中都有做过,要注意的是界面的布局设置,还有面板的放置位置。对于画棋盘,五子棋,黑白棋需要画出来,连连看其实没必要将棋盘显示的画出来,只需要将图片重绘在画布上即可。需要注意的是,重绘前一定要先获取画布。
[/size]
[size=x-large]
1.定义配置信息的接口
[/size]
/**
*
* 配置信息的接口
*
*/
public interface Config
{
// 左上角的点
public static final int X0 = 10, Y0 = 30;

//简单
public static final int ROWS0 = 7, COLUMNS0 = 9; // 横线和竖线的条数
int UI_WIDTH0 = 500;
int UI_HEIGHT0 = 500; //初始界面大小

//一般
public static final int ROWS1 = 13, COLUMNS1 = 15; // 横线和竖线的条数
int UI_WIDTH1 = 800;
int UI_HEIGHT1 = 800; //一般界面大小

//困难
public static final int ROWS2 = 13, COLUMNS2 = 19; // 横线和竖线的条数
int UI_WIDTH2 = 1000;
int UI_HEIGHT2 = 800; //困难界面大小

// 单元格大小
public static final int SIZE = 50;

// 图片大小
public static final int CELL_SIZE = 50;
}


[size=x-large]
2.初始化中间的绘制面板
[/size]
/**
* 初始化中间绘制面板的方法
*/
public DrawPanel()
{
//设置大小
this.setPreferredSize(new Dimension());

//设置背景色
this.setBackground(new Color(0,255,255));


//设置布局为流式居中对齐,间距为0
FlowLayout flayout=new FlowLayout();
this.setLayout(flayout);

//设置边框
javax.swing.border.LineBorder border=new javax.swing.border.LineBorder(Color.LIGHT_GRAY);
this.setBorder(border);
}

[size=x-large]
3.定义单元格和图片数组,并将图片放到数组中
[/size]

 /**
* 定义初始化数据的方法
* @param rows 线的行数
* @param columns 线的列数
*/

public static void initData(int rows, int columns)
{

//定义单元格和图片数组
CELL = new int[rows + 1][columns + 1];
CELL_IMG = new ImageIcon[rows - 1][columns - 1];

// 创建随机数对象
java.util.Random rd = new java.util.Random();

//创建Integer型队列
ArrayList<Integer> list = new ArrayList<Integer>();

//****************将元素加到队列中******************//

for (int i = 0; i < CELL_IMG.length * CELL_IMG[0].length / 2; i++)
{

// 随机一个数字
int num = rd.nextInt(30) + 1;

// 往队列中加两次,保证每个数字出现的次数都是偶数次
list.add(num);
list.add(num);

}

//将图片添加到图片数组中
for (int i = 1; i < CELL.length - 1; i++)
{
for (int j = 1; j < CELL[i].length - 1; j++)
{
// 取一个随机的下标
int index = rd.nextInt(list.size());

// 移除被随机到的下标对应的元素
int t = list.remove(index);
CELL[i][j] = t;
CELL_IMG[i - 1][j - 1] = new ImageIcon("images/draw" + t + ".jpg");

}
}

//System.out.println(" "+CELL.length);
}

[size=x-large]
4.重写paint()方法,将图片绘制到画布上
[/size]

/**
* 重写paint方法
*/
public void paint(Graphics g)
{

//调用父类中的 paint方法
super.paint(g);

if(!(DrawPanel.CELL==null))
{
// 重绘图片
for (int i = 1; i < DrawPanel.CELL.length; i++)
{
for (int j = 0; j <DrawPanel. CELL[i].length; j++)
{

// 根据下标计算每个单元格左上角的坐标
int x1 = SIZE * j;
int y1 = SIZE * i;

if (DrawPanel.CELL[i][j] != 0)
{
//如果单元格为空,画图片
g.drawImage(DrawPanel.CELL_IMG[i-1][j-1].getImage(), x1, y1, SIZE,SIZE, null);

}
}
}
}

}



[size=x-large]
然后就是给画布添加监听器,实现监听,当鼠标点击画布上的图标时,就会有相应的动作。
[/size]
[size=x-large]
1.画布监听器要继承鼠标适配器
[/size]
public class DrawListener extends MouseAdapter implements Config 


[size=x-large]
2.在鼠标点击式的方法中,获取鼠标点击处的坐标
3.计算该坐标在哪个单元格中
4.根据单元格,操作图片数组,即消去图片
[/size]
/**
* 鼠标点击时的方法
*/
public void mouseReleased(MouseEvent e)
{
//获得第一次点击的坐标
int x=e.getX();
int y=e.getY();

if(count==0)
{
//判断鼠标点击的位置是在哪个单元格中
r1=(y-Y0)/SIZE;
c1=(x-X0)/SIZE;

num1=DrawPanel.CELL[r1][c1];
count++;
}
else
{
r2=(y-Y0)/SIZE;
c2=(x-X0)/SIZE;
num2=DrawPanel.CELL[r2][c2];
count--;

//如果不是自己本身,是相同的图片,且不为空
if((r1!=r2||c1!=c2)&&num1==num2&&num1!=0)
{
//如果某一个方法返回true
if(SuanFa.checkRow(r1,c1,r2,c2)
||SuanFa.checkCulumn(r1,c1,r2,c2)||SuanFa.checkOne(r1, c1, r2, c2)
||SuanFa.checkTwo1(r1, c1, r2, c2)||SuanFa.checkTwo2(r1, c1, r2, c2))
{

//消去点击的图片
DrawPanel.CELL[r1][c1]=0;
DrawPanel.CELL[r2][c2]=0;

//刷新窗体
javax.swing.SwingUtilities.updateComponentTreeUI(fu);
}
}
}

}


[size=x-large]
最后就是算法了,关于算法,要先自己画图看看到底有几种消去图片的方式,搞清楚怎样才能消去,同行,同列,不同行,不同列,边界怎样消去等等,注意要用循环判断该单元格是否为空,只要途中遇到一个不为空,就不能连。[/size]
[size=x-large]1.同行[/size]
/**
*同行的算法
*/
public static boolean checkRow(int r1,int c1,int r2,int c2)
{
if(r1!= r2)
{
//如果不是同行,返回false
return false;
}

//如果是同行
for(int i=Math.min(c1,c2)+1;i<Math.max(c1,c2);i++)
{
if(DrawPanel.CELL[r1][i]!=0)
{
//只要中途碰到一个不为空,就不能连
return false;
}
}

//如果该循环执行完,表示可以连
return true;
}
[size=x-large]
2.同列[/size]

/**
* 判断同列可否相消的方法
* @param r1点击的第一个点所在格子的下标
* @param c1点击的第一个点所在格子的下标
* @param r2点击的第二个点所在格子的下标
* @param c2点击的第二个点所在格子的下标
* @return false或true
*/
public static boolean checkCulumn(int r1, int c1, int r2, int c2)
{

if (c1 != c2)
{
//如果不是同列,返回false
return false;
}

//如果是同列
for (int j = Math.min(r1, r2)+1; j < Math.max(r1, r2); j++)
{
if (DrawPanel.CELL[j][c1] != 0)
{
//只要中途碰到一个不为空,就不能连
return false;
}
}


return true;
}
[size=x-large]
3.一个拐点[/size]
/**
* 有一个拐点的方法
* @param r1点击的第一个点所在格子的下标
* @param c1点击的第一个点所在格子的下标
* @param r2点击的第二个点所在格子的下标
* @param c2点击的第二个点所在格子的下标
* @return false或true
*/
public static boolean checkOne(int r1, int c1, int r2, int c2)
{

if (DrawPanel.CELL[r1][c2] == 0 && checkRow(r1, c1, r1, c2)
&& checkCulumn(r1, c2, r2, c2))
{
//若果拐点为空,且连线上都为空 ,返回true

return true;

}

if (DrawPanel.CELL[r2][c1] == 0 && checkRow(r2, c2, r2, c1)
&& checkCulumn(r1, c1, r2, c1))
{
//若果拐点为空,且连线上都为空 ,返回true
}
//否 则,返回false
return false;
}

[size=x-large]4.两个拐点[/size]
/**
* 有两个拐点的方法
* @param r1点击的第一个点所在格子的下标
* @param c1点击的第一个点所在格子的下标
* @param r2点击的第二个点所在格子的下标
* @param c2点击的第二个点所在格子的下标
* return false或true
*/

public static boolean checkTwo1(int r1, int c1, int r2, int c2)
{
for (int i = 0; i < DrawPanel.CELL[0].length; i++)
{
if (DrawPanel.CELL[r1][i] == 0 && DrawPanel.CELL[r2][i] == 0
&& checkRow(r1, c1, r1, i) && checkRow(r2, c2, r2, i)
&& checkCulumn(r1, i, r2, i))
{
//若果拐点为空,且连线上都为空 ,返回true




return true;
}

}
//否 则,返回false
return false;
}
public static boolean checkTwo2(int r1, int c1, int r2, int c2)
{
for(int j=0;j<DrawPanel.CELL.length;j++)

{
if(DrawPanel.CELL[j][c1]==0&&DrawPanel.CELL[j][c2]==0
&&checkCulumn(r1,c1,j,c1)&&checkCulumn(r2,c2,j,c2)
&& checkRow(j, c1, j, c2))
{
//若果拐点为空,且连线上都为空 ,返回true

return true;
}
}
//否 则,返回false
return false;
}


[size=x-large]整个项目中,最应该注意的问题就是传参的问题,像是在添加监听器是,一定要将画布传入。还有就是要注意单元格数组和图片数组的操作,数组初始化,当点击图片可以连接时,数组的值设为空等等。[/size]
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值