`
butnet
  • 浏览: 84686 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

俄罗斯方块,机器人设计

阅读更多

前不久收拾台式机,
发现些东东,
以前写的小程序:俄罗斯方块,
于是打开玩了会,
看到界面相当丑,
于是想再改一下,
打开源代码,惊奇的发现,
代码中定义了一个机器人的抽象类,
但真正处理玩游戏的方法并没有实现,
于是我就想实现这个方法,
做一个机器人,
在做这个机器人时,想了很多办法,
但最后只实现了一个很简单的算法,
这个机器人还不怎么智能.
先把代码发在这,以后有时间再改进改进!
没地方发代码,需要的向vipexxe at 126 dot com 发邮件
我的机器人:

package com.bokee.nicend.boxgame.main;

import com.bokee.nicend.boxgame.game.Box;
import com.bokee.nicend.boxgame.gui.GamePanel;
import com.bokee.nicend.boxgame.robot.AbstractGamePanel;
import com.bokee.nicend.boxgame.robot.Step;

public class MyRobot extends Robot {
    public MyRobot(GamePanel panel) {
        super(panel);
    }

    @Override
    public void doBox(Box box) {
        方案1(getData(), box, true);
    }

    /**
     * @param data
     *            环境数据
     * @param box
     *            当前要处理的方块
     * @param canDepth 是否允许递归判断下一个方块信息
     */
    private Step 方案1(boolean[][] data, Box box, boolean canDepth) {
        Box boxBack = box.copy();// 备份原方块信息
        Box minBox = box.copy();// 最少空格时的方块信息
        /**
         * 最优化方法
         */
        Step bestStep = new Step();
        /**
         * 综合两次的最优方法
         */
        Step bestTwoStep = new Step();

        boolean[][] dataBack = copyData(data);// 备份环境数据

        // 虚拟游戏
        AbstractGamePanel abstractGamePanel = new AbstractGamePanel();

        // 此方块的 每种变形 遍历
        for (int j = 0; j < 4; j++) {
            // 按每个X坐标 遍历
            for (int i = 0; i <= getGamePanelWidth() - box.getBoxWidth(); i++) {
                // 设置方块位置
                box.setPoint(i, /* 0-box.getBoxHeight() */0);
                // 设置虚拟游戏环境
                abstractGamePanel.setData(data);
                abstractGamePanel.setBox(box);

                while (abstractGamePanel.moveDown())
                    ;

                Step currentStep = new Step();
                currentStep.setChage(j);
                currentStep.setX(box.getX());

                currentStep.setLine(abstractGamePanel.getDisponseLineNumber());
                currentStep.setRectCount(abstractGamePanel.getSpaceRectInBoxsHeight());
                currentStep.setHeight(data.length - abstractGamePanel.getRectHeight() - currentStep.getLine());
                currentStep.setSpaceCount(abstractGamePanel.getSpaceCountInBoxsHeight());
                currentStep.setSpaceNumber(abstractGamePanel.getLineSpaceNumber());

                if (canDepth) {
                    Box nextBox = box.willNext();
                    Step currnetNextBestStep = 方案1(copyData(data), nextBox, false);
                    // 两步总共消去的行数
                    currnetNextBestStep.setLine(currnetNextBestStep.getLine() + currentStep.getLine());
                    if (currnetNextBestStep.compareTo(bestTwoStep) > 0) {
                        bestTwoStep = currnetNextBestStep;
                        bestStep = currentStep;
                        minBox = box.copy();
                    }
                } else {
                    if (currentStep.compareTo(bestStep) > 0) {
                        bestStep = currentStep;
                        bestTwoStep = currentStep;
                        minBox = box.copy();
                    }
                }
                data = copyData(dataBack);
            }
            // 方块变形 进入下一个循环
            box.chang();
        }

        if (canDepth) {
            int x = minBox.getX();
            for (int i = 0; i < bestStep.getChage(); i++)
                moveUp();
            for (int i = 0; x < boxBack.getX() - i; i++)
                moveLeft();
            for (int i = 0; boxBack.getX() + i < x; i++)
                moveRight();
        }
        return bestStep;
    }

    private boolean[][] copyData(boolean[][] data) {
        return GamePanel.copyData(data);
    }
}

如果你觉得有趣,也可以自己继承Roboot类,实现一个自己的机器人,
看看我们的机器人,哪个的更优化.
机器人用于计算的虚拟游戏环境

package com.bokee.nicend.boxgame.robot;

import java.awt.Point;
import java.util.LinkedList;
import java.util.List;

import com.bokee.nicend.boxgame.game.Box;

/**
* 虚拟游戏
* @author Butnet
*/
public class AbstractGamePanel {
    /**
     * 游戏环境数据
     */
    private boolean[][] space = null;
    /**
     * 当前的方块
     */
    private Box box = null;

    public Box getBox() {
        return box;
    }

    public void setBox(Box box) {
        this.box = box;
    }

    public void setData(boolean[][] data) {
        this.space = data;
    }

    public boolean[][] getData() {
        return space;
    }

    /**
     * 将方块b设置为不能移动
     * @param b
     */
    public void setNoMove(Box b) {
        if (b.getY() + b.getBoxHeight() > space.length)
            return;
        int[][] d = b.getPoints();
        for (int i = 0; i < d.length; i++) {
            if (b.getY() + d[i][1] < 0 || b.getX() + d[i][0] < 0)
                continue;
            space[b.getY() + d[i][1]][b.getX() + d[i][0]] = false;
        }
    }

    /**
     * 在虚拟游戏中把当前方块向下移动
     * @return 返回移动成功返回true,不能移动返回false
     */
    public boolean moveDown() {
        if (!canDown()) {
            setNoMove(box);
            return false;
        }
        if (box.getY() + box.getBoxHeight() == space.length) {
            setNoMove(box);
            return false;
        }
        box.setY(box.getY() + 1);
        return true;
    }

    /**
     * 判断当前方块是否能下移
     * @return
     */
    private boolean canDown() {
        int[][] ps = box.getPoints();
        for (int i = 0; i < ps.length; i++) {
            if (box.getY() + 1 + ps[i][1] >= space.length)
                return false;
            if (!space[box.getY() + 1 + ps[i][1]][box.getX() + ps[i][0]])
                return false;
        }
        return true;
    }

    /**
     * 用每行的空格生成一个数值,用于优化判断
     * @return
     */
    public int getLineSpaceNumber() {
        int index = getRectHeight() - 1;
        if (index == -1)
            return 0;
        int re = 0;
        for (int i = index; i < space.length; i++) {
            int line = 0;
            for (int j = 0; j < space[i].length; j++)
                if (space[i][j])
                    line++;
            re = re * 10 + line;
        }
        return re;
    }

    /**
     * 取得消取的行数
     *
     * @return
     */
    public int getDisponseLineNumber() {
        int index = getRectHeight() - 1;
        if (index == -1)
            return 0;
        int line = 0;
        for (int i = index; i < space.length; i++) {
            boolean is = true;
            for (int j = 0; j < space[i].length; j++) {
                if (space[i][j]) {
                    is = false;
                    break;
                }
            }
            if (is)
                line++;
        }
        return line;
    }

    /**
     * 点数 下边的方块矩形中为空的空格个数
     *
     * @return
     */
    public int getSpaceCountInBoxsHeight() {
        // TEST CASE 2
        int allSpaceCount = 0;
        for (int col = 0; col < space[0].length; col++) {
            boolean start = false;
            for (int row = 0; row < space.length; row++) {
                if (!start) {
                    if (!space[row][col])
                        start = true;
                    continue;
                }
                if (space[row][col])
                    allSpaceCount++;
            }
        }
        if (1 == 1)
            return allSpaceCount;

        // TEST CASE 1
        int topIndex = -1;
        for (int i = 0; i < space.length; i++) {
            for (int j = 0; j < space[i].length; j++) {
                if (!space[i][j]) {
                    topIndex = i;
                    break;
                }
            }
            if (topIndex != -1)
                break;
        }
        if (topIndex == -1)
            return 0;
        int count = 0;
        for (int i = topIndex; i < space.length; i++) {
            for (int j = 0; j < space[i].length; j++) {
                if (space[i][j])
                    count++;
            }
        }
        return count;
    }

    /**
     * 返回 下边方块形成的空格区域个数
     *
     * @return
     */
    public int getSpaceRectInBoxsHeight() {
        int topIndex = -1;
        for (int i = 0; i < space.length; i++) {
            for (int j = 0; j < space[i].length; j++) {
                if (!space[i][j]) {
                    // System.out.println("i="+i+", j="+j);
                    // System.out.println("Box.X="+box.getX()+"
                    // Box.Y="+box.getY());
                    topIndex = i;
                    break;
                }
            }
            if (topIndex != -1)
                break;
        }
        if (topIndex == -1)
            return 0;

        List<Point> ps = new LinkedList<Point>();
        for (int i = topIndex; i < space.length; i++) {
            for (int j = 0; j < space[i].length; j++) {
                if (space[i][j]) {
                    ps.add(new Point(i, j));
                }
            }
        }
        // TODO: 返回 下边方块形成的空格区域个数
        List<List<Point>> rects = new LinkedList<List<Point>>();
        for (int i = 0; i < ps.size(); i++) {
            Point p = ps.get(i);
            List<Point> rect = null;
            boolean add = false;
            for (List<Point> r : rects) {
                if (r.contains(new Point(p.x - 1, p.y)))
                    r.add(p);
                else if (r.contains(new Point(p.x + 1, p.y)))
                    r.add(p);
                else if (r.contains(new Point(p.x, p.y - 1)))
                    r.add(p);
                else if (r.contains(new Point(p.x, p.y + 1)))
                    r.add(p);
                else if (r.contains(p))
                    ;
                else
                    continue;
                add = true;
                break;
            }
            if (add)
                continue;
            rect = new LinkedList<Point>();
            rects.add(rect);
            rect.add(p);
        }
        // 返回区域个数
        return rects.size();
    }

    /**
     * 判断不能移动的方块组成的高度
     * @return
     */
    public int getRectHeight() {
        int topIndex = -1;
        for (int i = 0; i < space.length; i++) {
            for (int j = 0; j < space[i].length; j++) {
                if (!space[i][j]) {
                    topIndex = i;
                    break;
                }
            }
            if (topIndex != -1)
                break;
        }
        return topIndex + 1;
    }
}

用于机器人比较优劣的步骤类:

package com.bokee.nicend.boxgame.robot;

/**
* 保存机器人每步的结果
*
* @author Butnet
*/
public class Step {
    /**
     * 此时的方块变形次数
     */
    int chage = 0;
    /**
     * 此时方块的X坐标
     */
    int x = 0 ;
    /**
     * 空格的个数
     */
    int spaceCount = 0;//1
    /**
     * 空格形成的连续区域个数
     */
    int rectCount = 0;//
    /**
     * 结果在区域中的高度
     */
    int height = 0;//2
    /**
     * 每行中空格形成的数值
     */
    int spaceNumber = 0;//
    /**
     * 这一步所得到的权值
     */
    int roleValue = 0;
    /**
     * 这一步消去的方块行数
     */
    int line = 0;//0
    /**
     * 以最坏情况构造一个步骤
     */
    public Step() {
        chage = 0;
        x = 0;
        spaceCount = Integer.MAX_VALUE;
        rectCount = Integer.MAX_VALUE;
        height = Integer.MAX_VALUE;
        spaceNumber = Integer.MAX_VALUE;
        roleValue = Integer.MIN_VALUE;
    }

    public int getSpaceCount() {
        return spaceCount;
    }

    public int getSpaceNumber() {
        return spaceNumber;
    }
    public int getHeight() {
        return height;
    }
    public int getLine() {
        return line;
    }
    public int getRectCount() {
        return rectCount;
    }
    public int getRoleValue() {
        return roleValue;
    }

    public void setSpaceCount(int spaceCount) {
        this.spaceCount = spaceCount;
    }

    public void setRectCount(int rectCount) {
        this.rectCount = rectCount;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public void setSpaceNumber(int spaceNumber) {
        this.spaceNumber = spaceNumber;
    }

    public void setRoleValue(int roleValue) {
        this.roleValue = roleValue;
    }

    public void setLine(int line) {
        this.line = line;
    }

    public int getChage() {
        return chage;
    }

    public void setChage(int chage) {
        this.chage = chage;
    }

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }
    /**
     * 比较两个步骤的优劣
     * @return 如果更优化返回 1 相同返回 0 落后返回 -1
     * */
    public int compareTo(Step step){
        if(line>step.line)
            return 1;
        if(line==step.line){
            if(spaceCount<step.spaceCount)
                return 1;
            if(spaceCount==step.spaceCount){
                if(height<step.height)
                    return 1;
                if(height==step.height){
                    if(rectCount<step.rectCount)return 1;
                    if(rectCount==step.rectCount){
                        if(spaceNumber<step.spaceNumber)return 1;
                        if(spaceNumber==step.spaceNumber)return 0;
                        return -1;
                    }
                    return -1;
                }
                return -1;
            }
            return -1;
        }
        return -1;
    }
}

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics