草庐IT

java - 将随机迷宫生成合并到我的游戏中(Java)

coder 2024-04-02 原文

我目前正在用 Java 制作迷宫解谜游戏,但遇到了麻烦。我能找到的所有随机迷宫生成算法都以一种我无法弄清楚如何在我当前代码中实现的方式输出。我正在考虑使用 Depth First Search , Recursive Backtracker , 或 Prim's Algorithm ,因为我认为它们是最容易实现的,同时还能产生好的迷宫。使用与我当前程序一起使用的那些算法之一的工作用途是什么?这是我的游戏类:(也请随时指出任何不好的做法,我是 Java 的新手)

package game;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class Game extends JPanel implements ActionListener, KeyListener {

    private boolean upPressed    = false;
    private boolean downPressed  = false;
    private boolean rightPressed = false;
    private boolean leftPressed  = false;

    private final int playerDiam = 100;
    private final int playerSpeed = 15;
    private final int tileSize = 400;

    private int[][] maze = {{1, 1, 1, 1, 1, 1},
                            {1, 2, 1, 1, 3, 1},
                            {1, 0, 1, 0, 0, 1},
                            {1, 0, 1, 0, 1, 1},
                            {1, 0, 0, 0, 1, 1},
                            {1, 1, 1, 1, 1, 1},
                           };
    private int[][] initX = new int[maze.length][maze.length];
    private int[][] initY = new int[maze.length][maze.length];

    private int deltaX = -210;
    private int deltaY = -210;

    private String screen = "menu";


    public Game() {
        setFocusable(true);
        addKeyListener(this);
        setUpInitialCoordinates();
        Timer timer = new Timer(1000 / 60, this);
        timer.start();
    }

    @Override
    public void actionPerformed(ActionEvent e) {
        tick();
    }

    private void setUpInitialCoordinates() {
        int x = 0;
        int y;
        for (int[] rowData : maze) {
            y = 0;
            for (int ignored : rowData) {
                initX[x][y] = x * tileSize;
                initY[x][y] = y * tileSize;
                y++;
            }
            x++;
        }
    }

    private void generateMaze() {
    }

    private void tick() {
        if (screen.equals("playing")) {
            if (upPressed) {
                deltaY += playerSpeed;
            } else if (downPressed) {
                deltaY -= playerSpeed;
            }
            if (rightPressed) {
                deltaX -= playerSpeed;
            } else if (leftPressed) {
                deltaX += playerSpeed;
            }
        }
        repaint();
    }

    @Override
    public void keyTyped(KeyEvent e) {}

    @Override
    public void keyPressed(KeyEvent e) {
        if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() ==   KeyEvent.VK_W) {
            upPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode() == KeyEvent.VK_S) {
            downPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
            rightPressed = true;
        } else if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
            leftPressed = true;
        }
    }


    @Override
    public void keyReleased(KeyEvent e) {
        if (screen.equals("menu") && e.getKeyCode() == KeyEvent.VK_ENTER) {
            upPressed = false;
            downPressed = false;
            rightPressed = false;
            leftPressed = false;
            screen = "playing";
        } else if (screen.equals("playing")) {
            if (e.getKeyCode() == KeyEvent.VK_UP || e.getKeyCode() ==    KeyEvent.VK_W) {
                upPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_DOWN || e.getKeyCode()   == KeyEvent.VK_S) {
                downPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_RIGHT || e.getKeyCode() == KeyEvent.VK_D) {
                rightPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_LEFT || e.getKeyCode() == KeyEvent.VK_A) {
                leftPressed = false;
            } else if (e.getKeyCode() == KeyEvent.VK_P) {
                screen = "paused";
            }
        } else if (screen.equals("paused" ) && e.getKeyCode() ==     KeyEvent.VK_P) {
            upPressed = false;
            downPressed = false;
            rightPressed = false;
            leftPressed = false;
            screen = "playing";
        }
    }

    @Override
    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.setFont(new Font("Aharoni", Font.PLAIN, 36));
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, getWidth(), getHeight());
        switch (screen) {
            case "menu":
                g.setColor(Color.BLACK);
                g.drawString("Labyrinth", 300, 200);
                g.drawString("Press Enter to Play!", getWidth() / 3, 500);
                break;
            case "playing":
                int x = 0;
                int y = 0;

                for (int[] rowData : maze) {
                    for (int cellData : rowData) {
                        if (cellData == 1) {
                            g.setColor(Color.DARK_GRAY);
                            g.fillRect(x + deltaX, y + deltaY, tileSize, tileSize);
                        } else if (cellData == 2) {
                            g.setColor(Color.GREEN);
                            g.fillRect(x + deltaX, y + deltaY, tileSize, tileSize);
                        } else if (cellData == 3) {
                            g.setColor(Color.YELLOW);
                            g.fillRect(x + deltaX, y + deltaY, tileSize,   tileSize);
                        }
                        x += tileSize;
                        if (x == maze.length * tileSize) {
                            x = 0;
                            y += tileSize;
                        }
                    }
                }   g.setColor(Color.RED);
                g.fillOval(getWidth() / 2, getHeight() / 2, playerDiam, playerDiam);
                break;
            case "gameOver":
                g.setColor(Color.BLACK);
                g.drawString("Game Over",getWidth() / 3 ,50 );
                break;
            case "paused":
                g.setColor(Color.BLACK);
                g.drawString("Paused", getWidth() / 3, 50);
                break;
        }
    }
}

最佳答案

作为开始我会

  1. 清除迷宫
  2. 随机添加墙
  3. 为存在的所有入口/导出点对创建随机路径

    • 清除沿着它们的迷宫单元。

如果你只需要迷宫求解器(一些生成迷宫的算法需要它们)

使用求解器,您可以将算法更改为

  1. 清除迷宫
  2. 添加随机墙

    • 如果添加它仍然提供解决方案
  3. 循环bullet(2) N次

你需要小心如何添加墙

  • 例如,如果您只添加简单的线条,那么迷宫将如下所示:
  • >

这是它的代码(使用链接答案中的类)

// generate random maze with path from x0,y0 to x1,y1 present, n walls
void A_star::generate(int x0,int y0,int x1,int y1,int n)
    {
    int x,y,i,j,dx,dy,l,*p;
    // [clear map]
    for (y=0;y<ys;y++)
     for (x=0;x<xs;x++)
      map[y][x]=A_star_space;
    // temp space
    p=new int [xs>>1]; if (p==NULL) return;
    // generate n walls
    for (i=0;i<n;i++)
        {
        // random start pos,dir,length
        x =Random(xs);
        y =Random(ys);
        dx=Random(4);
        l =Random(xs>>2)+2;
             if (dx==0) { dx=+1; dy= 0; }
        else if (dx==1) { dx=-1; dy= 0; }
        else if (dx==2) { dx= 0; dy=+1; }
        else if (dx==3) { dx= 0; dy=-1; }
        // add wall to maze remember set cells (for remowal if needed)
        for (j=0;l;l--,x+=dx,y+=dy)
         if ((x>=0)&&(x<xs))
          if ((y>=0)&&(y<ys))
           if (map[y][x]!=A_star_wall)
            {
            p[j]=x; j++;
            p[j]=y; j++;
            map[y][x]=A_star_wall;
            }
        // is there solution?
        compute(x0,y0,x1,y1);
        // if not remowe last added wall
        if (ps==0) for (;j;)
            {
            j--; y=p[j];
            j--; x=p[j];
            map[y][x]=A_star_space;
            }
        }
    delete[] p;
    }

由这段代码生成:

 A_star map;
 map.resize(256,256); 
 map.generate(5,5,250,250,500);

关于java - 将随机迷宫生成合并到我的游戏中(Java),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29664280/

有关java - 将随机迷宫生成合并到我的游戏中(Java)的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby - 在 jRuby 中使用 'fork' 生成进程的替代方案? - 2

    在MRIRuby中我可以这样做:deftransferinternal_server=self.init_serverpid=forkdointernal_server.runend#Maketheserverprocessrunindependently.Process.detach(pid)internal_client=self.init_client#Dootherstuffwithconnectingtointernal_server...internal_client.post('somedata')ensure#KillserverProcess.kill('KILL',

  3. ruby - 如何使用 Ruby aws/s3 Gem 生成安全 URL 以从 s3 下载文件 - 2

    我正在编写一个小脚本来定位aws存储桶中的特定文件,并创建一个临时验证的url以发送给同事。(理想情况下,这将创建类似于在控制台上右键单击存储桶中的文件并复制链接地址的结果)。我研究过回形针,它似乎不符合这个标准,但我可能只是不知道它的全部功能。我尝试了以下方法:defauthenticated_url(file_name,bucket)AWS::S3::S3Object.url_for(file_name,bucket,:secure=>true,:expires=>20*60)end产生这种类型的结果:...-1.amazonaws.com/file_path/file.zip.A

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby - 如果指定键的值在数组中相同,如何合并哈希 - 2

    我有一个这样的哈希数组:[{:foo=>2,:date=>Sat,01Sep2014},{:foo2=>2,:date=>Sat,02Sep2014},{:foo3=>3,:date=>Sat,01Sep2014},{:foo4=>4,:date=>Sat,03Sep2014},{:foo5=>5,:date=>Sat,02Sep2014}]如果:date相同,我想合并哈希值。我对上面数组的期望是:[{:foo=>2,:foo3=>3,:date=>Sat,01Sep2014},{:foo2=>2,:foo5=>5:date=>Sat,02Sep2014},{:foo4=>4,:dat

  6. ruby-on-rails - Ruby on Rails - 为文本区域和图片生成列 - 2

    我是Rails的新手,所以请原谅简单的问题。我正在为一家公司创建一个网站。那家公司想在网站上展示它的客户。我想让客户自己管理这个。我正在为“客户”生成一个表格,我想要的三列是:公司名称、公司描述和Logo。对于名称,我使用的是name:string但不确定如何在脚本/生成脚手架终端命令中最好地创建描述列(因为我打算将其设置为文本区域)和图片。我怀疑描述(我想成为一个文本区域)应该仍然是描述:字符串,然后以实际形式进行调整。不确定如何处理图片字段。那么……说来话长:我在脚手架命令中输入什么来生成描述和图片列? 最佳答案 对于“文本”数

  7. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  8. ruby-on-rails - 如何生成传递一些自定义参数的 `link_to` URL? - 2

    我正在使用RubyonRails3.0.9,我想生成一个传递一些自定义参数的link_toURL。也就是说,有一个articles_path(www.my_web_site_name.com/articles)我想生成如下内容:link_to'Samplelinktitle',...#HereIshouldimplementthecode#=>'http://www.my_web_site_name.com/articles?param1=value1¶m2=value2&...我如何编写link_to语句“alàRubyonRailsWay”以实现该目的?如果我想通过传递一些

  9. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

  10. ruby-on-rails - 如何在 Rails 3 中创建自定义脚手架生成器? - 2

    有这些railscast。http://railscasts.com/episodes/218-making-generators-in-rails-3有了这个,你就会知道如何创建样式表和脚手架生成器。http://railscasts.com/episodes/216-generators-in-rails-3通过这个,您可以了解如何添加一些文件来修改脚手架View。我想把两者结合起来。我想创建一个生成器,它也可以创建脚手架View。有点像RyanBates漂亮的生成器或web_app_themegem(https://github.com/pilu/web-app-theme)。我

随机推荐