`
butnet
  • 浏览: 89038 次
  • 性别: 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;
    }
}

分享到:
评论

相关推荐

    C#俄罗斯方块

    【C#俄罗斯方块】 C#是一种面向对象的编程语言,由微软开发,广泛应用于桌面应用、游戏开发、Web应用和服务端开发等。在“C#俄罗斯方块”项目中,我们将探讨如何利用C#来实现这个经典的游戏。 1. **图形用户界面...

    TetrisPlayground:高级机器学习的最终项目。 构建机器人来对抗这个俄罗斯方块沙盒!

    俄罗斯方块 AI 环境马特·布伦曼这是我在 2014 年秋季塔夫茨大学高级机器学习课程的最后一个项目。它是一个俄罗斯方块 AI 环境,让用户可以定义代理并轻松将它们插入系统。 这是 ML/AI 学生尝试构建游戏程序的一种...

    pygame实现俄罗斯方块游戏(AI篇2)

    在本篇中,我们将深入探讨如何使用Python的pygame库实现俄罗斯方块游戏的AI功能,这是系列教程的第二部分。我们将解决之前版本中的一些问题,让机器人的决策更智能,以便更好地模仿人类玩家的行为。 首先,我们需要...

    ABB杯智能技术创新大赛1

    赛题的核心是让参赛者设计一个能够自主玩俄罗斯方块的机器人系统。首先,我们需要理解比赛的规则和场景设定。初赛与决赛的场景略有不同,但基本目标一致:利用机器人准确地接住和摆放随机生成的俄罗斯方块,尽可能...

    基于强化学习的逃生游戏与俄罗斯方块。.zip

    基于强化学习的逃生游戏与俄罗斯方块。 强化学习(Reinforcement Learning, RL),又称再励学习、评价学习或增强学习,是机器学习的范式和方法论之一。它主要用于描述和解决智能体(agent)在与环境的交互过程中通过...

    Tetris:俄罗斯方块游戏,利用electron方式来写node.js桌面程序,提供一个非传统方法(大数组记录“棋局”)来进行“棋局”控制,最终目的是想做一个聪明的机器人,它玩俄罗斯方块能比我强,呵呵!

    霍兰的《涌现》和KK的《失控》,产生了对人工智能的莫大兴趣,也对面向对象思想有了更深入的理解,终极目标是想写一个自动玩俄罗斯方块的小机器人。 ##设计思路 全面应用面向对象的设计思想,让功能内聚性强。 把七...

    340个Proteus仿真通用项目案例.zip、流水灯、跑马灯、数码管动态显示、报警器与旋转灯、智能温控器、电压表等等

    (proteus)俄罗斯方块程序.zip (大杂烩)proteus仿真MCS51一百例.zip 001 流水灯.zip 002 跑马灯.zip 003 闪烁灯.zip 0031、编码开关试验.zip 004 按键识别.zip 005 简单输入输出控制.zip 006 数码管静态显示.zip ...

    经典游戏源代码合集

    3. **俄罗斯方块**:俄罗斯方块的实现涉及到游戏对象的生成、旋转、下落以及消除。源码中可能包含了一些基础的矩阵操作和游戏循环的知识。 4. **棋类游戏**(如井字游戏或国际象棋):这类游戏主要展示的是游戏规则...

    毕业设计分组-汇总表.pdf

    11. **游戏与多媒体**:基于单片机实现的俄罗斯方块游戏和音乐播放器设计,展示了单片机在娱乐和媒体应用方面的潜力。 12. **工厂自动化与配电系统**:车间低压配电系统设计、中小型工厂变电所电气二次部分设计,是...

    proteus仿真设计实例

    7. **红外遥控六足爬虫机器人设计**:这是一个综合项目,涉及到硬件搭建、遥控信号处理和机器人控制算法。你需要理解如何通过红外遥控器控制机器人的运动,并处理复杂的控制逻辑。 8. **俄罗斯方块游戏**:此实例...

    scratch游戏源码24个(完整版).zip

    4. **俄罗斯方块.sb2**:这个项目会涉及到游戏循环、物体下落、旋转、碰撞检测和消除行的逻辑。 5. **聊天机器人.sb2**:聊天机器人涉及到自然语言处理的简单形式,可以学习到事件触发、字符串处理和简单的对话逻辑...

    DCtime_TetrisBot:这是我的11年级小论文程序设计项目

    该项目的核心是用Python编写了一个自动玩俄罗斯方块的机器人,不仅锻炼了编程技能,还体现了逻辑思维和问题解决的能力。 Python作为一种易学易用的编程语言,是初学者入门的理想选择。在这个项目中,开发者利用...

    java小游戏

    这些小游戏可能涵盖多种类型,如猜数字、扫雷、俄罗斯方块等,它们通常结构简单,易于实现,同时也富有娱乐性。 在Java中开发小游戏,开发者会使用Java的基础语法,包括类、对象、方法、循环、条件判断等。例如,`...

    大量国赛 省赛 智能小车的原理图库+PCB库-电路方案

    压缩包内的“俄罗斯方块游戏的大概算法.doc”可能是一个关于如何实现游戏逻辑的文档,虽然与智能小车直接关联不大,但可以作为学习单片机编程和算法设计的参考。通过阅读这个文档,我们可以了解如何利用单片机实现...

    8080汇编手册.pdf

    - **游戏开发**:使用8080处理器开发简单的游戏,如俄罗斯方块等,以展示汇编语言在图形处理方面的应用。 - **嵌入式系统控制**:设计一个基于8080处理器的嵌入式控制系统,用于控制小型机器人或其他机械设备。 ...

    VB编程资源大全(源码 其它3)

    里面有用 vb 处理俄罗斯方块的核心内容及简单注释(8KB) 584,g014.zip breakthrough游戏(保持小球在屏幕上跳动)源程序(50KB) 585,g013.zip 3维迷宫游戏的源程序(40KB) 586,g012.zip 射击(导弹)游戏...

    VB编程资源大全(源码 其它1)

    里面有用 vb 处理俄罗斯方块的核心内容及简单注释(8KB) 584,g014.zip breakthrough游戏(保持小球在屏幕上跳动)源程序(50KB) 585,g013.zip 3维迷宫游戏的源程序(40KB) 586,g012.zip 射击(导弹)游戏...

    VB编程资源大全(源码 其它2)

    里面有用 vb 处理俄罗斯方块的核心内容及简单注释(8KB) 584,g014.zip breakthrough游戏(保持小球在屏幕上跳动)源程序(50KB) 585,g013.zip 3维迷宫游戏的源程序(40KB) 586,g012.zip 射击(导弹)游戏...

Global site tag (gtag.js) - Google Analytics