小游戏2048

小游戏2048

#前言

​ 之前上嵌入式的推广课时,老师说在开发板上完成2048可以加分。不过由于我连基础项目都没完成,所以就没时间弄了。有点灰心,所以现在在安卓上开发了这个游戏了。
游戏结束

#从算法入手

​ 为了便于开发,首先我在vsc完成了我的2048算法代码,这部分代码写在了GameBoardUtils类中,我可以通过输入1234模拟上下左右滑动,并在终端中以4*4的形式输出游戏表盘。

​ 算法中使用了列表用于记录空的值,这样可以便于在随机生成数字时决定生成位置。使用了列表来不断记录表盘数据,这样可以撤销数据。每一次用户执行操作都会检查用户操作是否能够改变表盘,以及是否游戏结束。这个类中还有初始化游戏数据的方法initGameData(),以及恢复游戏数据的方法restoreGameData(),后者可以在执行撤销操作时或从bundle中获得数据时,传入表盘数据后完成恢复

#ui与数据

​ 展示数据使用了GridView,为改变游戏界面写了两个方法:一个是用于初始化游戏界面的,这个方法会调用setAdapter();另一个则是刷新数据。

​ 为GridView调用setOnTouchListener()来识别并执行滑动操作:在event==MotionEvent.ACTION_DOWN时记录数据,在event==MotionEvent.ACTION_UP时,也就是手指离开屏幕时识别这是什么操作,在event==MotionEvent.ACTION_MOVE时必须返回true,否则没有机会看到event==MotionEvent.ACTION_UP时。

​ 测试了以下功能,发现确实能够实现想要的效果了,但是却觉得怪怪的,好像反应太过灵敏把我愣住了。所以在返回结果数据更新的过程中,我使用了Handler延时300ms。又为了能够向用户说明2048每次随机生成的数字在哪里,使得数据刷新后不会看起来太突兀,为对应的itemView设置了透明度动画:setGeneratePosition只是为了传入生成位置,会在getView中找到这个位置并设置动画

new Handler().postDelayed(new Runnable() {
    @Override
    public void run() {
        adapter.setGeneratePosition(locationKey);
        gameViewUpdate();
    }
},DELAY_MILLIS);

​ 游戏结束后,我希望能够生成一则通知以告诉用户刚刚的游戏中,所有方块中的最大值是什么,同时会发出AlertDialog询问用户要不要继续游戏,如果用户点击确认,则直接初始化表盘数据,如果点击取消,则生成初始按钮。发送通知前,还需要为安卓8.0以上的版本设置NotificationChannel

private void gameOver() {
    if(undoButton!=null)undoButton.setEnabled(false);
    createNotificationChannel();
    NotificationCompat.Builder builder = new NotificationCompat.Builder(this,CHANNEL_ID)
            .setSmallIcon(R.drawable.abc_vector_test)
            .setContentTitle("Game Over!")
            .setContentText("max cube:"+getMaxCube())
            .setPriority(NotificationCompat.PRIORITY_HIGH)
            .setAutoCancel(true)
            .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(), 0));
    NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(this);
    notificationManagerCompat.notify(NOTIFICATION_ID,builder.build());

    AlertDialog.Builder dialog = new AlertDialog.Builder(this);
    dialog.setTitle("Game Over...")
            .setMessage("restart the game?")
            .setPositiveButton("Yes", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    restartGame();
                    Log.d(TAG, "onClick: "+getIsGameOver());
                }
            })
            .setNegativeButton("No", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    initGameData();
                    startButtonInit();
                }
            }).show();
}

​ 最后,我在按钮上设置了两个按钮:撤销和从头开始。当没有数据可撤销时,应该让撤销按钮不可点击

undoButton = menu.findItem(R.id.action_game_undo);
undoButton.setEnabled(false);

​ 为了让这个小游戏在手表上也能够运行,所以使用限定符small创建了手表专用布局,并为了能够让2048的游戏表盘最大化,为这个布局配备了没有actionBar的布局。这样,当我在gridview范围内滑动时会识别操作,但是在手表上滑动时,由于表盘太小了,而且左划总是触发返回桌面,返回后应用就被杀死了,看上去终究还是挺糟糕的 (/▽\)
手表中运行

#小结

​ 开发过程遇到最大的问题是到了后期时,随着对2048表盘的操作选项增多,逻辑有些混乱,然后重新捋捋思路,觉得所有的操作其实分为两类:修改数据,更新数据到gridview中,并且简化了一下代码

代码:https://github.com/rabbitAiry/my2048

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值