20162327WJH实验五——数据结构综合应用

Posted 小飞侠WJH

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了20162327WJH实验五——数据结构综合应用相关的知识,希望对你有一定的参考价值。

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、排序算法的实现

  • 在排行榜的功能实现中会有体现,完成后补上。

以上是关于20162327WJH实验五——数据结构综合应用的主要内容,如果未能解决你的问题,请参考以下文章

实验五 数据结构综合应用

20162329 实验五:数据结构综合应用

20162316刘诚昊 实验五-数据结构综合应用

20162301实验五 数据结构综合应用

20162328蔡文琛 实验五 数据结构综合应用

20162308 实验五 数据结构综合应用