20162327WJH实验五——数据结构综合应用
实 验 报 告
课程:程序设计与数据结构
班级: 1623
姓名: 王旌含
学号:20162327
成绩:
指导教师:娄嘉鹏 王志强
实验密级: 非密级
预习程度: 已预习
实验时间:15:25-17:15
必修/选修: 必修
实验序号: cs_23
实验内容
-
1.分析系统架构
-
2.编译、运行、测试系统
-
3.修改系统
-
4.分析数据结构、排序、查找算法的应用
一、游戏架构分析
- 游戏简介:点击游戏图标,第一个出线的界面就是游戏的主界面,界面上有四个按钮,分别是开始游戏、排行榜、选项和退出游戏。点击开始游戏按钮手机会弹出选择关卡界面(对应欢迎界面类);点击排行榜会弹出游戏的排行榜(这里会用到排序的相关知识);点击选项,会弹出声音设置以及制作人员的介绍;点击退出游戏则会直接退出游戏。目前在游戏中我们设置了十个关卡,点击对应关卡就会进入相应的游戏界面(对用选择关卡的类);游戏过程中会调用主界面类对玩家的每一步操作进行逻辑判断;通关后,会弹出胜利界面(对应胜利界面类)。游戏的大概过程就是这样的,下面会进行详细的介绍。
二、编译、运行、测试系统
- 1、用android将项目克隆指定的文件夹中
- 2、编译
- 3、运行
三、修改系统
-
1、设置一个按钮,点击后显示学号信息
在游戏的选项界面里加入一个按钮,按钮的名称为自己名字,然后在GameOption活动中获取按钮组件为按钮设置监听器,点击按钮时发出一条Tost消息显示学号。
-
2、修改地图
游戏中的地图是由16*16的二维矩阵完成的,其中1代表地板、2代表红点、3代表墙、4代表箱子、5代表搬运工,在矩阵中改变数组就会改变地图中现实的东西。
四、分析数据结构、排序、查找算法的应用
1、选择关卡的有关代码
- 1、游戏选择关卡的界面是由一个网格布局完成的
<TextView
android:id="@+id/tv_select_level"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/select_level"
android:gravity="center"
android:textSize="24sp"
android:paddingBottom="12dp"/>
<GridView//网格布局
android:id="@+id/gv_levels"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:numColumns="3"
android:layout_below="@id/tv_select_level"
android:layout_centerHorizontal="true"
android:verticalSpacing="20dp"
android:horizontalSpacing="8dp"
android:gravity="center">
</GridView>
- 2、加载网格布局后,按下关卡按钮后就会进行话地图等一系列操作
//加载布局
setContentView(R.layout.activity_game_level);
//添加到活动结束类
SysApplication.getInstance().addActivity(this);
GridView gv_levels = (GridView) findViewById(R.id.gv_levels);
ArrayAdapter<String> arrayAdapter = new ArrayAdapter<String>(this, R.layout.gv_levels_item_textview, GameLevels.getLevelList());
//网格加载适配器
gv_levels.setAdapter(arrayAdapter);
gv_levels.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
Intent intent = new Intent(GameLevelActivity.this, GameActivity.class);
intent.putExtra(GameActivity.KEY_SELECTED_LEVEL, i + 1);
MainActivity.mediaPlayer.pause();
MainActivity.mediaPlayer2.start();
MainActivity.mediaPlayer2.setLooping(true);
startActivity(intent);
}
});
2、如何绘制游戏地图(这里用到了查找的有关知识)
- 1、首先在GameLevels中制作好地图矩阵,每个数字代表的图片内容如下面的代码所示,代码中只表示了第一关的地图矩阵,后面的几个关卡类同。
public class GameLevels {
public static final int DEFAULT_ROW_NUM = 16;
public static final int DEFAULT_COLUMN_NUM = 16;
//游戏区单元格放了什么
public static int [] Steps;
public static final int FLOOR = 1; //地板
public static final int NOTHING = 0; //没有
public static final int BOX = 4; //该单元格放的是箱子
public static final int FLAG = 2; //红旗,表示箱子的目的地
public static final int MAN = 5; //搬运工
public static final int WALL = 3; //墙
public static final int MAN_FLAG = 5; //搬运工 + 小球
public static final int BOX_FLAG = 6; //箱子 + 小球
public static final int [][] LEVEL_1 = {
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 3, 2, 3, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 3, 1, 3, 3, 3, 3, 0, 0, 0, 0},
{0, 0, 0, 0, 3, 3, 3, 4, 1, 4, 2, 3, 0, 0, 0, 0},
{0, 0, 0, 0, 3, 2, 1, 4, 5, 3, 3, 3, 0, 0, 0, 0},
{0, 0, 0, 0, 3, 3, 3, 3, 4, 3, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 3, 2, 3, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}
};
- 2、创建一个线性表,元素类型设为二位数组,将写好的游戏地图放入这个线性表中,在选择关卡界面选择关卡时,会在这个线性表中调取游戏地图
public static ArrayList<int[][]> OriginalLevels = new ArrayList<>();
public static void loadGameLevels(){
if (OriginalLevels.isEmpty()) {
OriginalLevels.add(LEVEL_1);
OriginalLevels.add(LEVEL_2);
OriginalLevels.add(LEVEL_3);
OriginalLevels.add(LEVEL_4);
OriginalLevels.add(LEVEL_5);
OriginalLevels.add(LEVEL_6);
OriginalLevels.add(LEVEL_7);
OriginalLevels.add(LEVEL_8);
OriginalLevels.add(LEVEL_9);
OriginalLevels.add(LEVEL_10);
}
}
public static int [][] getLevel(int level){
loadGameLevels();
return OriginalLevels.get(level - 1);
}
- 3、确定图片的大小及显示的区域,设置for循环来遍历地图矩阵,在每个数字对应的地方画上相应的图片,这样就画好了游戏地图
private void drawGameBoard(Canvas canvas) {
Rect srcRect; //表示图片内部的区域
Rect destRect; //表示图片在屏幕中显示的区域
//得到表示局面的二维矩阵
int [][] labelInCells = mGameActivity.getCurrentState().getLabelInCells();
for (int r = 0; r < labelInCells.length; r++) //逐行地扫描矩阵
for (int c = 0; c < labelInCells[r].length; c++){ //对当前行r,逐列地扫描
destRect = getRect(r, c); //得到图片在屏幕中的显示区域
srcRect = new Rect(0, 0,GameBitmaps.FlagBitmap.getWidth(), GameBitmaps.FlagBitmap.getHeight());//获得显示图片的大小
switch (labelInCells[r][c]){
case 1:
canvas.drawBitmap(GameBitmaps.FloorBitmap,srcRect,destRect,null); //绘制地板
break;
case 2:
canvas.drawBitmap(GameBitmaps.FlagBitmap, srcRect, destRect, null); //绘制标记
break;
case 3:
canvas.drawBitmap(GameBitmaps.WallBitmap, srcRect, destRect, null); //绘制墙
break;
case 4:
canvas.drawBitmap(GameBitmaps.BoxBitmap, srcRect, destRect, null); //绘制箱子
break;
case 5:
canvas.drawBitmap(GameBitmaps.ManBitmap, srcRect, destRect, null); //绘制人
break;
case 6:
canvas.drawBitmap(GameBitmaps.ReadboxBitmap, srcRect, destRect, null); //绘制红箱子
break;
}
}
}
3、游戏按钮的支持代码
-1、绘制虚拟按钮,第一个参数是图片的来源,第二个参数是按钮的大小,第三个参数是按钮的位置
//绘制虚拟按钮
canvas.drawBitmap(GameBitmaps.UpBitmap,buttonRect,new Rect(2*width,getWidth(),3*width,getWidth()+hight),null); //绘制虚拟按键
canvas.drawBitmap(GameBitmaps.LeftBitmap,buttonRect,new Rect(width,getWidth()+hight,2*width,getWidth()+2*hight),null);
canvas.drawBitmap(GameBitmaps.OKBitmap,buttonRect,new Rect(4*width,0,5*width,hight),null);
canvas.drawBitmap(GameBitmaps.RightBitmap,buttonRect,new Rect(3*width,getWidth()+hight,4*width,getWidth()+2*hight),null);
canvas.drawBitmap(GameBitmaps.DownBitmap,buttonRect,new Rect(2*width,getWidth()+2*hight,3*width,getWidth()+3*hight),null);
- 2、保存手触摸手机的位置
public boolean onTouchEvent(MotionEvent event) {
//忽略Down, MOVE型的动作的处理
if(event.getAction() != MotionEvent.ACTION_UP || mGameActivity.getCurrentState().isGameOver())
return true;
//关卡数组的行
int r = mGameActivity.getCurrentState().getManRow();
//关卡数组的列
int c = mGameActivity.getCurrentState().getManColumn();
int touch_x = (int) event.getX(); //触摸点的x坐标
int touch_y = (int) event.getY(); //触摸点的y坐标
if (touch_blow_to_man(touch_x, touch_y,r ,c )) { //按下键
mGameActivity.getCurrentState().handleDown();
MainActivity.mediaPlayer4.start();
}
if (touch_right_to_man(touch_x, touch_y,r ,c )) { //按右键
mGameActivity.getCurrentState().handleRight();
MainActivity.mediaPlayer4.start();
}
if (touch_above_to_man(touch_x, touch_y,r ,c )) { //按上键
mGameActivity.getCurrentState().handleAbove();
MainActivity.mediaPlayer4.start();
}
if (touch_left_to_man(touch_x, touch_y,r ,c )) {//按下键
mGameActivity.getCurrentState().handleLeft();
MainActivity.mediaPlayer4.start();
}
if (touch_back_to_man(touch_x, touch_y,r ,c )) { //按重置键
mGameActivity.getCurrentState().handleback();
MainActivity.mediaPlayer3.start();
}
postInvalidate();
return true;
}
- 3、判断手触摸的位置是否为按钮的位置,如果是则执行按钮的操作
//判断按键对象
private boolean touch_blow_to_man(int touch_x, int touch_y, int manRow, int manColumn) {
int width = (int) buttonWidth;
int hight = (int) buttonHight;
Rect belowRect = new Rect(2*width,getWidth()+2*hight,3*width,getWidth()+3*hight);
return belowRect.contains(touch_x, touch_y);
}
private boolean touch_above_to_man(int touch_x, int touch_y, int manRow, int manColumn) {
int width = (int) buttonWidth;
int hight = (int) buttonHight;
Rect aboveRect = new Rect(2*width,getWidth(),3*width,getWidth()+hight);
return aboveRect.contains(touch_x, touch_y);
}
private boolean touch_left_to_man(int touch_x, int touch_y, int manRow, int manColumn) {
int width = (int) buttonWidth;
int hight = (int) buttonHight;
Rect leftRect = new Rect(width,getWidth()+hight,2*width,getWidth()+2*hight);
return leftRect.contains(touch_x, touch_y);
}
private boolean touch_right_to_man(int touch_x, int touch_y, int manRow, int manColumn) {
int width = (int) buttonWidth;
int hight = (int) buttonHight;
Rect rightRect = new Rect(3*width,getWidth()+hight,4*width,getWidth()+2*hight);
return rightRect.contains(touch_x, touch_y);
}
private boolean touch_back_to_man(int touch_x, int touch_y, int manRow, int manColumn) {
int width = (int) buttonWidth;
int hight = (int) buttonHight;
Rect rightRect = new Rect(4*width,0,5*width,hight);
return rightRect.contains(touch_x, touch_y);
}
public void handleback() {//还原建的支持代码
for (int i = 0; i < mLabelInCells.length; i++)
for (int j = 0; j < mLabelInCells[i].length; j++) {
if(temp[i][j]==5){
mManRow = i;
mManColumn = j;
}
mLabelInCells[i][j] = temp[i][j];
}
steps = 0;
}
4、如何判断游戏是否通关以及胜利界面
- 1、首先判断游戏是否通关,通关后通知通关。
//判断游戏是否通关
public boolean isGameOver(){
for(int i=0;i<mLabelInCells.length;i++)
for (int j=0;j<mLabelInCells[i].length;j++){
if(temp[i][j]==2 || temp[i][j]==6)
if (mLabelInCells[i][j]!=6)
return false;
}
return true;
}
//如果过关了,要报告过关
if(mGameActivity.getCurrentState().isGameOver()) {
Intent intent = new Intent(mContext,WinActivity.class);
GameLevels.Steps[mGameActivity.selected_level-1] = mGameActivity.getCurrentState().steps;
intent.putExtra("LV",mGameActivity.getIntent().getIntExtra(mGameActivity.KEY_SELECTED_LEVEL,1));
GameState.becom();
mGameActivity.startActivity(intent);
}
- 2、弹出的胜利界面有两个按钮,左边的按钮是返回上一关,右边的是进入下一关,是最后一关,使用Toast显示出来。
5、音效的插入
- 1、创建几个音乐播放器
mediaPlayer = MediaPlayer.create(this, R.raw.gameview);
mediaPlayer2 = MediaPlayer.create(this, R.raw.gaming);
mediaPlayer3 = MediaPlayer.create(this, R.raw.button);
mediaPlayer4 = MediaPlayer.create(this, R.raw.button2);
mediaPlayer5 = MediaPlayer.create(this, R.raw.success);
- 2、音乐播放的切换功能,例如,打开游戏是一个音乐,进入游戏界面切换另一首音乐(就是音乐开始的时间和停止时间的设定)
public void onPause() {
super.onPause();
MainActivity.mediaPlayer2.pause();
}
public void onStart() {
super.onStart();
if (!MainActivity.mediaPlayer2.isPlaying()){
MainActivity. mediaPlayer2.start();
}
7、排序算法的实现
- 在排行榜的功能实现中会有体现,完成后补上。