毕业设计开发日志2018.04.09

开发日志本来是应该从一开始就写的,不过到了现在我才有写日志这个想法……

那就从今天开始吧。

——————————————————————

毕业设计的课题是安卓平台的陆战棋手游开发。不是很难的题目,当初也是看着简单才挑来做。

还没动手的时候去GitHub搜了搜相关的项目想找找思路,没想到还真有一个完全满足我这个课题需求的项目。不过我大学咸鱼了这么久,没读过什么源码,没有培养出读大段源码的能力和耐心。所以那个项目唯一给我的印象就是用户通过蓝牙对战,没了。连大概的项目结构我都没梳理出来。

——————————————————————

目前进度是棋盘基本结构写完,在倒腾蓝牙接口。

棋盘与棋子

棋盘是一个5*13的GridLayout,每一格是一个继承自ImageView的Field对象。Field即是营地,类内封装了它在棋盘上的坐标,营地类别(铁轨 兵站 行营 大本营),还有营地的占有者。

棋子是一个简单的Piece对象。封装了军衔和阵营属性。

通过Field.setOwner(Piece)的方法来让一个棋子站到一个营地上。

棋子移动

棋子移动是靠一个成员变量Field selected实现。当点击一个Field时,检查selected。如果为空,那么令selected等于当前点击的Field,并更改当前Field的图片,显示为已被选择。而点击时selected不为空,则有分第二次点击的Field等于或不等于selected。如果等于,也即是取消选择的意思,将selected置空,还原Field的显示。如果不等,又分目标营地占有者是不是友方的。如果是,那就是更改选择,改变selected为当前点击Field。如果不是,那么就是一个移动操作了。

棋子移动分为两个阶段。

第一阶段是检查目标区域是否是可以到达的。对于棋盘上的每个Field与其他Field的连通性,我想了很久,曾经想过用链表画成无向图,但邻接表法实在是冗余过多了。最后我给出的解决方法是用一个三维数组,棋盘上每个Field对应一个长度为八的int[],数组内的值分为0(不连通)1(普通连通)2(铁轨连通)三种,八个值对应该Field的八个方向。这样当我需要从一个Field离开,我只要查它对应的这个数组对应方向的值即可。

有了这个连通数组,检查目标可否到达就比较简单了。首先是检查目标区域是否是原位置身边的八个单步可达的位置。如果是,检查连通数组即可。如果不是身边八个位置,那么检查当前位置和目标位置是否都是铁轨,如果都是铁轨,那么就可以进行铁轨移动。铁轨移动又分为普通铁轨移动(只能直线)和工兵铁轨移动(只要是在铁轨上,到处可去)。普通铁轨移动简单,棋盘上铁轨直线横4条竖两条,检查起点终点是否在同一直线,然后检查他们之间有没有棋子即可。工兵移动比较复杂。我看网上有谈到k-means算法,但我没有花这个功夫……我只是简单进行递归移动,在递归中记录移动路线防止画圈即可。毕竟棋盘不大,这个程度的递归也不会很花时间。

第二阶段就是战斗了。在第一阶段检查完目标地点是可以到达的之后,就意味着这一次移动已经成功了,移动后无论是自己棋子杀死了对方还是被对方杀死都是第二阶段的事了。(顺带一提,目标地点是被敌方占领的行营的情况是在第一阶段之前就会检查的特殊情况,不会留到第二阶段来判断)在进入第二阶段就是棋子移动成功并和对方棋子发生战斗了。战斗就是简单地读出双方军衔比对就行,战斗函数返回一个整形值,分别有0(战斗失败)1(战斗成功)2(同归于尽)三种。根据返回结果处理Field的owner即可。

补充一小点:战斗结束后我方杀死对方军旗获得游戏胜利这种特殊情况还没处理,因为蓝牙接口还没搞好,所以现在还没有写对局流程。

——————————————————————

蓝牙接口

我一开始看了很久Android Developer上面的蓝牙开发指导,因为没有仔细一个个字看,导致没有完全看明白。谷歌放在GitHub那个demo又是忘了哪一年写的了,我导入到as后提醒项目API比当前限制的API最低版本更老……我懒得调了,就直接用txt看。前面说了,我读源码的能力真的不怎么样。是大概看懂了蓝牙服务基本写在了一个Bluetoothchatservice的类里,然后界面写了个Bluetoothfragment,然后又这样那样的。我试图直接将它的bluetoothchatservice直接搬到我的项目里用,却又出了各种奇奇怪怪的错。

后来我又去GitHub搜别的蓝牙项目,搜到一个外国的BluetoothSPP的项目,似乎是蓝牙的简单封装,在gradle添加denpendency就能直接用了。我那叫一个高兴,按着它的文档一步步写了好久。发现我在manifest添加它library里的一个devicelistactivity总是报错。研究了好久才终于发现这个智障项目的项目包本该是bluetoothspp,但实际却是bluetotoh是匹配……包名都拼错了,可想而知项目质量。最后还是把它删了,回去研究Android Developer的文档去了。

静下心来看官方文档其实还是能看懂的,并不是很复杂。首先是几行代码检查蓝牙是否可用以及是否已经打开。然后就获取BluetoothAdapter,获取已配对设备。另外新开一个线程调用BluetoothAdapter.accept()等候设备接入。新开线程是因为accept是个阻塞的方法,会阻塞进程直到有设备进入为止。另一边通过BluetoothAdapter.startDiscovery()开始扫描设备。扫描到设备后用这个BluetoothDevice开一个新线程尝试进行连接。对接成功后两边都会返回一个BluetoothSocket,用这个socket通讯就行了。

目前我的理解是这样,但实际还不知道。因为这个连接成功后的socket没法作为extra在activity之间传递。我本来的设想是在一个activity连接成功了,将socket传到gameactivity的。但既然不行,那我只好把连接也放在gameactivity了。

gameactivity本来是整个屏幕都是棋盘,一个按钮都没有。现在我也没有打算加按钮上去。右上角菜单又显得不像是一个必须进行的连接所在的地方,所以我只好找到了NavigationView这种高级玩意(并不高级……只是我从来没用过)。

在原项目新建一个NavigationActivity直接把我的项目搞坏了。它自动添加了大堆资源文件之后跟我说我当前项目API内没有NavigationView这个东西。

是的我每次建项目都选的默认的Android4.0……

而当我想把这个新的Activity删掉的时候我又发现它自动添加的各种资源文件和原本的资源文件融为一体,我并不能很好地把项目还原到之前的样子……就是这个时候我才感受到Git的重要性……

于是最后我只好新建了一个Android5.0的项目,然后把之前写好的代码搬到新项目。

中途因为头疼咸鱼了几天,到今天才终于搬好了。

——————————————————————

今天也不只是搬代码,还去捣鼓了一下悬浮窗口popupwindow。

popupwindow的使用并不是很难,首先画好xml作为布局文件,然后在代码里view.inflate,再将这个view传入popupwindow的构造函数就行了。

在这里有个很有趣的点,我以前其实也遇过一次,但后来又忘了。就是在当前activity里如何找别的xml的控件。比如我在gameactivity里面找popupview的控件,是不能直接findviewbyid的。而是应该popupview.findviewbyid()。其实也很好理解,平时单写findviewbyid其实就是this.findviewbyid嘛。但是这种小细节真的很容易忽略,遇到一次才会注意到。

今天写的整篇开发日志其实都是因为最后这一小点才有的记录一下开发中的问题的想法才写的。以后真的应该培养一下自己写博客的习惯。其实一路写程序这么久,在CSDN看别人写的博客是我非常重要的学习方法之一了。也不知道为什么自己一直没有自己写博客的这个想法。明明是对自己一路以来学习的一个总结,很有帮助的才是。

加油吧。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值