在团队项目中用到的部分游戏玩法相关逻辑
在团队项目中用到的部分游戏玩法相关逻辑总结
技术概述
该部分游戏玩法相关算法是根据游戏中的卡牌放置坐标和卡牌类型来进行玩家合作竞争得分玩法相关部分逻辑处理。卡牌种类多可以通过旋转,卡牌每边需要只能与类型相同的边相连。
技术详述
在卡卡颂这个卡牌游戏中,通过卡牌的拼接和判断卡牌之间相连的类型来放置卡牌,卡牌的视图构成一块区块占领的玩家即可得分。
流程图:
下面具体是区块的相关代码
public class Block {
String edgeString;
public HashSet<Point> pointSet = new HashSet<>();
HashMap<Point, Card> cardMap = new HashMap<>();
HashMap<Point, ArrayList<Edge>> edgeMap = new HashMap<>();
HashMap<String, Integer> scoreRecord = new HashMap<>();
ArrayList<String> playerIdArray = new ArrayList<>();
public boolean isFull = true;
int scorePerCard = 0;
int scoreAll = 0;
}
合并部分
获取参数中block中所需要的变量添加进自身的得分板块中
public void mergeBlock(Block block){
if(edgeString.equals(block.edgeString)){
pointSet.addAll(block.pointSet);
for(Point point : block.edgeMap.keySet()){
ArrayList<Edge> edgeList = new ArrayList<Edge>(){
{
add(null);
add(null);
add(null);
add(null);
}
};
if(block.edgeMap.containsKey(point))
edgeList = copy(block.edgeMap.get(point));
ArrayList<Edge> edgeList1 = new ArrayList<Edge>(){
{
add(null);
add(null);
add(null);
add(null);
}
};
if(edgeMap.containsKey(point))
edgeList1 = copy(edgeMap.get(point));
for(int i=0;i<4;i++){
if(edgeList.get(i)!=null){
edgeList1.set(i,edgeList.get(i));
}
}
edgeMap.put(point,edgeList1);
}
for(String ownerId:block.scoreRecord.keySet()){
if(scoreRecord.containsKey(ownerId)){
scoreRecord.put(ownerId,scoreRecord.get(ownerId)+block.scoreRecord.get(ownerId));
}
else {
scoreRecord.put(ownerId,block.scoreRecord.get(ownerId));
}
}
block.scoreRecord.clear();
block.edgeMap.clear();
block.pointSet.clear();
block.isFull = true;
}
}
递归判断是否区块是否完整
在得分板块不大的情况下选择了递归来判断区块是否完整,当递归后该点的卡牌不是叶子节点但并没有子节点的时候判断改区块不得分
public void Walk(Point nextPoint) {
if(!edgeMap.keySet().contains(nextPoint)){
return;
}
if(pointSet.contains(nextPoint)){
return;
}
pointSet.add(nextPoint);
ArrayList<Edge> edgeArrayList = edgeMap.get(nextPoint);
int x_nextPoint = nextPoint.getX();
int y_nextPoint = nextPoint.getY();
int mapNoNullCount = 0 ;
int edgeNoNullCount = 0 ;
for (int i = 0;i<4;i++) {
switch (i) {
case 0:
Point point = new Point(x_nextPoint, y_nextPoint - 1);
Walk(point);
mapNoNullCount += edgeMap.keySet().contains(point)? 1:0;
edgeNoNullCount += edgeArrayList.get(i)==null?0:1;
break;
case 1:
Point point1= new Point(x_nextPoint + 1, y_nextPoint);
Walk(point1);
mapNoNullCount += edgeMap.keySet().contains(point1)? 1:0;
edgeNoNullCount += edgeArrayList.get(i)==null?0:1;
break;
case 2:
Point point2= new Point(x_nextPoint , y_nextPoint+1);
Walk(point2);
mapNoNullCount += edgeMap.keySet().contains(point2)? 1:0;
edgeNoNullCount += edgeArrayList.get(i)==null?0:1;
break;
case 3:
Point point3= new Point(x_nextPoint-1 , y_nextPoint);
Walk(point3);
mapNoNullCount += edgeMap.keySet().contains(point3)? 1:0;
edgeNoNullCount += edgeArrayList.get(i)==null?0:1;
break;
default:
break;
}
}
if(mapNoNullCount!=edgeNoNullCount){
isFull=false;
}
得分部分
通过得分板块中卡牌个数来获取,区块中只有棋子最多的玩家才能得分,棋子相同的玩家可以一起得分
scoreAll = isFull ? scorePerCard * pointSet.size() : 0;
int max = 0;
for (Integer value : scoreRecord.values()) {
if (value > max) max = value;
}
for (String ownerId : scoreRecord.keySet()) {
if (scoreRecord.get(ownerId).equals(max)) {
playerIdArray.add(ownerId);
}
}
描述你是如何实现和使用该技术的,要求配合代码和流程图详细描述。可以再细分多个点,分开描述各个部分。
技术使用中遇到的问题和解决过程
在集成测试的时候对合并部分代码发现了问题,区块1为合并了区块2,在对被合并了的区块2中的hashmap的value进行操作后,合并了区块2的区块1的hashmap相应的value也发生了相应改变。直接获取hashmap中的Arraylist是引用传递,对引用的进行操作结果也会相应的改变,如果需要的只是值的引用,要新建一个空的Arraylist把值copy进去。
举个例子
这个是引用传递,当a变化的时候b也会变化
ArrayList<Edge> a = new Arraylist<Eege>(){
a.add(edge1);
};
hashmap.put(key,a);
ArrayList<Edge> b = hashmap.get(key);
值引用需要new一个新的Arraylist对象,将a中的每个元素遍历来进行赋值,再将新的ArrayList赋值给b对象
虽然是一个小问题,但是还是想了很久。
进行总结
遇到的问题很小,代码编写过程中也遇到了多多少少的问题,开发阶段单元测试也发现了许多问题改了过来,对与数据结构的知识自己还需要多加学习,这次团队项目学到了很多,也是一次积累了团队经验的宝贵经历。