职场文秘网

首页 > 文秘写作 > 毕业设计 / 正文

基于Java的图片连连看游戏设计研究

2023-03-30 10:25:04

李少芳

(莆田学院 机电与信息工程学院, 福建 莆田 351100)

游戏产业作为现代电脑电子技术的产物,正以其独特的魅力在娱乐领域占据主流位置.随着Java的广泛应用,以及Java开发系统的可移植性的提高,Java开发的游戏大受欢迎.虽然Java开发的游戏在画面表现、场景效果等受到一定的限制,但是游戏响应比较快,具备一定的优势[1-5].连连看游戏是源自中国台湾的桌面小游戏,经过发展,众多程序员开发出桌面游戏、在线游戏和社交游戏等多种版本的连连看[6].饱受工作压力的人们通常没有太多的时间进行复杂的游戏,而对于这种动动鼠标就能过关的游戏情有独钟.宠物连连看、数字连连看[6]、果蔬连连看、阿达连连看等各种琳琅满目的连连看版本,网上甚至推出在线自己制作的全免费连连看游戏,提供下载,享受轻松、自由、快乐的游戏休闲时刻.一些连连看游戏已成为幼儿园大班科学活动备选项目.许多人在PC机或手机上都玩过图片连连看游戏,看着很简单,但自己真的动手设计,完成过程其实很艰辛.如果是制作手机连连看游戏,编译完成的连连看游戏需要将生成的安装包上传至手机,在生成的源文件里打开bin文件,将里面的apk文件通过数据线下载至手机,apk文件即游戏安装包.在手机上找到下载完成的 apk文件,点击安装.安装成功后,即可进入连连看游戏登录界面[7].

连连看,又称对对卡,是指图案配对的一种经典的电子益智游戏,游戏规则是将相同图案的两张图片用三根以内的直线连在一起消除[8].具体操作是:在游戏中,玩家可以将2个相同图案的图片成对连接起来,连接线不多于3根直线,就可以成功将对子消除.第一次使用鼠标点击地图上的一张图片,这张被选中的图片将加框显示;
再次用鼠标点击第二张图片,若该图片与被选中图片的图案相同,且把第一张图片到第二张图片连起来,中间的直线不超过3根,则消掉这两张图片,否则第一张图片恢复成未被选中状态,而第一张图片变成被选中状态.当将棋盘上的对子全部消除掉时,判为胜利.可以限制玩家选择图片的时间不超过30秒,超过时间而未消除一对则判为输掉.连连看游戏通过选择不同的地图、游戏速度、背景音乐,规则简单容易上手.

游戏界面的主窗体的棋盘网格可以设计,格子中的图片随着格子的大小自适应显示.关卡1按10×8设置,效果图如图1所示.关卡2按12×10设置.游戏进度可以根据消除的图片数量/网格数量进行计算显示,也可以设定一定的游戏得分规则,按消除的图片数量计算积分排列名次,增加游戏的竞技乐趣.主窗体上还添加菜单设置.菜单的具体实现如下:先建立JMenuBar菜单栏,新建四个JMenu菜单[9-10],分别命名为游戏开局、难度设置、音效音乐和计时得分,如图2所示.“游戏开局”菜单下建立JMenuItem菜单项,分别命名为开始、结束、撤销、提示、乱序和暂停;
“难度设置”菜单下建立JMenuItem菜单项,分别命名为关卡1、关卡2;
“音效音乐”菜单下建立JMenuItem菜单项,分别命名为音效、音乐,“计时得分”菜单下建立JMenuItem菜单项,分别命名为时间、进度、生命、得分、排名等.

图1 按10×8设置的关卡1游戏界面主窗体

图2 游戏界面的菜单设置

各菜单项功能说明如下:

开始:开始新的游戏.

结束:结束正在进行中的游戏.

撤销:撤销最近一次消除动作.

提示:加框提示要消除的两张图片,扣除一个生命值.

乱序:打乱当前剩余的图案,扣除两个生命值.

暂停:暂停游戏,不计游戏时间.

关卡1:棋盘大小设置为10×8,游戏时间240秒,生命值4.

关卡2:棋盘大小设置为12×10,游戏时间360秒,生命值6.

音效:开启/关闭游戏音效.

音乐:开启/关闭背景音乐.

时间:显示剩余的游戏时间,按秒显示.

进度:按百分比显示游戏进度.

生命:显示当前剩余的生命值,生命值为0,则结束游戏.

得分:显示玩家所得分数.

排名:点击后可查看排行榜.

建立菜单的代码如下:

JMenuBar menubar=new JMenuBar();//菜单栏

JMenu gameMenu1=new JMenu("游戏开局");

JMenu gameMenu2=new JMenu("难度设置");

JMenu gameMenu3=new JMenu("音效音乐");

JMenu gameMenu4=new JMenu("计时得分");

JMenuItem m11=new JMenuItem("开始", KeyEvent.VK_A);//设置快捷方式Ctrl+A

JMenuItem m12=new JMenuItem("结束");

……

JMenuItem m45=new JMenuItem("排名");

menubar.add(gameMenu1);// 把菜单项添加到菜单中

menubar.add(gameMenu2);

menubar.add(gameMenu3);

menubar.add(gameMenu4);

gameMenu1.add(m11);

gameMenu1.add(m12);

……

游戏界面图片显示的实现过程如下:首先收集一张游戏主界面背景图片bg01.jpg和20张圣诞卡通图片,分别命名为a1.png,a2.png,……,a20.png,存放于工程文件夹的png文件夹下.根据主界面棋盘网格的多少,20张圣诞卡通图片要重复多次读取,例如8行10列的棋盘网格,总共要显示80张图片,则对于20张圣诞卡通图片每张需要显示4次.图片显示可以根据主界面棋盘网格的大小设置为自适应大小.背景图片变量bg和存放20张圣诞卡通图片的数组img定义代码如下:

public static Image bg= new ImageIcon("png\bg01.jpg").getImage();

public static Imageimg=new Image[20];

static {

for (int i=0; i < img.length; i++) {

try{

img[i]=ImageIO.read(new File("png\a" + (i + 1) + ".png"));

}catch(IOException e){ e.printStackTrace(); }

}}

如果背景图片未设置自适应大小,则其显示效果不能按窗口大小拉伸显示,相应代码为g.drawImage(bg, 0, 0, this);设置背景图片自适应大小显示,可以通过this获取窗体大小来拉伸显示图片,相应代码如下:

ImageIcon m=new ImageIcon(bg);

m.setImage(bg.getScaledInstance(this.getWidth(),this.getHeight(),Image.SCALE_AREA_AVERAGING));

g.drawImage(m.getImage(), 0, 0, this);

连连看的棋盘网格可以简单地看成一个二维数组,数组的大小取决于所要绘制的图片个数,但是必须要保证图片是成对出现的.首先定义一个棋盘Chess类,其成员变量status表示棋盘网格图片的状态,对应给定的20张圣诞卡通图片,设定棋盘网格图片的状态值分别为1~20.当图片状态值为0时,表明图片被消除.以10行12列的棋盘网格为例,总共要显示120张图片,则对于20张圣诞卡通图片每张需要循环显示6次,用count表示图片循环显示的次数.棋盘网格数组arr的横、纵坐标值是棋盘网格的行和列,行取值范围为1~10,列取值范围为1~12,采用随机方式填充设置棋盘网格图片[11].伪随机数在软件开发和程序设计中应用很广,Java提供了多种生成伪随机数的方法,如Random类和Math类,不同算法产生的伪随机数的随机性有所差别,可以根据实际需要选择以满足不同的设计要求.这里选用Random类来产生随机数,棋盘网格数组arr中最上面一行、最下面一行、最左边一列和最右边一列的值初始化为0.

相应的代码如下:

class Chess {

private int status;

public Chess(int status) { this.status=status;}

public int getStatus() { return status;}

public void setStatus(int status) { this.status=status;}

}

Chess arr=new Chess[row + 2][col+ 2];

public void init() {

for (int i=0; i < arr[0].length; i++) {

arr[0][i]=new Chess(0);

arr[arr.length - 1][i]=new Chess(0);

}

for (int i=0; i < arr.length; i++) {

arr[i][0]=new Chess(0);

arr[i][arr[0].length - 1]=new Chess(0);

}

Random random=new Random();

for (int i=1; i <= 20; i++) {

int count=0;

while (count < row*col/20) {

int x=random.nextInt(row) + 1;

int y=random.nextInt(col) + 1;

if (arr[x][y]==null) {arr[x][y]=new Chess(i);count++;}

}}}

//棋盘网格图片的显示

for (int i=1; i < arr.length; i++) {

for (int j=1; j < arr[i].length; j++) {

if (arr[i][j].getStatus() != 0) {

int x=(j-1) *gridWidth + left;

int y=(i-1) * gridHeight + up;

g.drawImage(img[arr[i][j].getStatus() - 1], x,y,this);

}}}

连连看的游戏规则是点击两张相同图案的图片,当这两张图片能够用不超过三根直线相连时,则可以消除这两张图片.判断两个图片的图案相同比较简单,设定20张图片的状态值分别为1~20,则只需对比图片的状态值是否相同.消除图片算法中比较难的是判断两个图片的连接是否超过两次拐角.消除图片的情况有三种:一是直线连通,即两张图片直接通过一根直线相连,如图3所示;
二是一拐角连通,即两张图片通过一个拐角连接的两条直线连通,如图4所示;
三是二拐角连通,即两张图片通过两个拐角连接的三条直线连通,如图5、图6所示.当判断两张图片连通可以被消除时,则将这两张图片所对应的状态值置零,棋盘网格图片消除.

图3 横向相邻直线连通效果图

图4 一拐角L型连通的示意图

情况1 直线连通.两张图片直接连通的方式有4种,分别是纵向相邻、横向相邻、横向中间为空和纵向中间为空.如果是两张图片相邻的话,只需要判断两个图片的行或列值是否相差1,如图3所示.对于中间为空的两个图片,则需要判断两个图片之间是否存在其他图片.

设点a的坐标值为(ax,ay),点b的坐标值为(bx,by),则点a与点b直线连通线的绘制代码如下:

Point a=list.get(0);

Point b=list.get(1);

int ax=a.y * gridWidth + left;

int ay=a.x * gridHeight + up;

int bx=b.y * gridWidth + left;

int by=b.x * gridHeight + up;

g2d.drawLine(ax, ay, bx, by);

情况2 一拐角连通.两张图片通过一个拐角连接的两条直线连通,即L型连通,如图4所示.设绿色的A、B格子表示要判断是否连通的两张相同图案的图片,细点填充的格子表示其他图案的图片,白色背景的格子表示没有图片.要判断图片A和图片B是否一拐角连通,其实相当于以图片A和图片B为一对对角顶点划出一个矩形,然后找出C、D两点,然后判断路径ADB和ACB上是否存在状态不为0的图片.

设点a的坐标值为(ax,ay),点b的坐标值为(bx,by),拐点c的坐标值为(cx,cy),则点a与点b通过一个拐点进行L型连通时L型线的绘制代码如下:

Point a=list.get(0);

Point c=list.get(1);

Point b=list.get(2);

int ax=a.y* gridWidth + left;

int ay=a.x* gridHeight + up;

int cx=c.y* gridWidth + left;

int cy=c.x* gridHeight + up;

int bx=b.y* gridWidth + left;

int by=b.x* gridHeight + up;

g2d.drawLine(ax, ay, cx, cy);

g2d.drawLine(cx, cy, bx, by);

情况3 二拐角连通.两张图片通过两个拐角连接的三条直线连通,分U型连通和非U型连通,如图5、图6所示.要判断图片A与图片B是否二拐角连通,其实可以转化为判断能否找到一个点C,满足C与图片A直线连通,且C与图片B一拐角p连通,或者找到一个点D,满足D与图片B直线连通,且D与图片A一拐角连通.

图5 二拐角U型连通的示意图

图6 二拐角非U型连通的示意图

设点a的坐标值为(ax,ay),点b的坐标值为(bx,by),拐点c的坐标值为(cx,cy),另一个拐点d的坐标值为(dx,dy),则点a与点b通过两个拐点进行连通时轨迹线的绘制代码如下:

Point a=list.get(0);

Point c=list.get(1);

Point d=list.get(2);

Point b=list.get(3);

int ax=a.y*gridWidth +left;

int ay=a.x*gridHeight +up;

int cx=c.y*gridWidth +left;

int cy=c.x*gridHeight + up;

int dx=d.y*gridWidth +left;

int dy=d.x*gridHeight +up;

int bx=b.y*gridWidth +left;

int by=b.x*gridHeight +up;

g2d.drawLine(ax, ay, cx, cy);

g2d.drawLine(cx, cy, dx, dy);

g2d.drawLine(dx, dy, bx, by);

游戏音效上可以在图片消除时设置一个简短的提示音效,也可以添加背景音乐.目前由于Java语言中AudioClip包的废弃,导致背景音乐通常要导入第三方的jar包来解决.利用Java语言的AudioInputStream流文件读入方式定义Music类.设音乐文件路径为工程文件夹下的wav//r.wav,需要播放背景音乐时,只需通过定义Music类对象m,即Music m=new Music();并调用m.player().

Music类实现背景音乐播放的相关代码如下:

import java.io.File;

import java.io.IOException;

import javax.sound.sampled.*;

public class Music {

private int t=0; // 音乐播放时间

AudioInputStream bgMusic;

private boolean playing=false;

public boolean isPlaying() {return playing;}

public void setPlaying(boolean playing) {this.playing=playing;}

public int getT() {return t;}

public void setT(int t) {this.t=t;}

public Music() {

try {

bgMusic= AudioSystem.getAudioInputStream(new File("wav//r.wav"));

} catch (UnsupportedAudioFileException e) {e.printStackTrace();}

catch (IOException e) {e.printStackTrace();} //获得音频输入流

}

public void player() {

AudioInputStream ais;

AudioFormat baseFormat;

DataLine.Info info;

ais=bgMusic;

baseFormat=ais.getFormat();//指定声音流中特定数据格式

info=new DataLine.Info(SourceDataLine.class, baseFormat);

SourceDataLine line=null;//定义SourceDataLine类变量line

try {

line=(SourceDataLine) AudioSystem.getLine(info);

line.open(baseFormat);

//打开指定格式的行,获得所需的系统资源

line.start();// 允许line执行数据 I/O

int BUFFER_SIZE=4000 * 4;

int intBytes=0;

byte audioData=new byte[BUFFER_SIZE]; // 音频数据数组

while (intBytes != -1 && (playing == false)) {

intBytes=ais.read(audioData, 0, BUFFER_SIZE);

// 从音频流读取BUFFER_SIZE字节,并放入字节数组intBytes

if (intBytes >= 0) {

line.write(audioData, 0, intBytes);//将音频数据写入

t += 1;

}}} catch (LineUnavailableException | IOException e1) {e1.printStackTrace();}

}}

设计主窗体游戏界面比较简单,难点是如何判别连通消除图片的算法.本文用Java语言设计图片连连看游戏,用到的关键技术包括游戏界面图片的自适应显示、初始化棋盘网格生成地图、消除图片的算法分析以及游戏音效和背景音乐设置等.由于图片设置自适应显示,实测游戏的响应速度会变慢,应优先选用合适大小的连连看图片,尽量减少图片转换时间.为了用户更好的体验,在一些细节设计上还有待进一步优化和完善,比如通过多线程添加背景音乐[12]、按消除图片的比例添加显示进度条、计时增加游戏难度、历史排行榜的记录等,将另文阐述.

猜你喜欢 坐标值拐角棋盘 Where Is My Home?考试与评价·七年级版(2020年4期)2020-10-23大跨度钢结构安装三维坐标拟合转换建筑科技(2018年2期)2018-10-25基于二分法迭代的凸模数控铣削加工编程*机械研究与应用(2018年3期)2018-07-11走过那一个拐角美文(2017年4期)2017-02-23拐角遇到奇迹小雪花·初中高分作文(2016年5期)2016-05-14基于宏程序的数控车削加工应用装备制造技术(2016年12期)2016-02-23棋盘人生小资CHIC!ELEGANCE(2015年12期)2015-09-10棋盘里的天文数字科普童话·百科探秘(2014年8期)2014-08-15棋盘疑案智慧与创想(2013年10期)2013-11-28棋盘游乐园小朋友·快乐手工(2009年5期)2009-06-11

Tags: 连连看   研究   设计  

搜索
网站分类
标签列表