【问题标题】:Drawing lines to create a Cell in Java绘制线条以在 Java 中创建单元格
【发布时间】:2018-05-05 23:49:20
【问题描述】:

我正在尝试创建一个 DFS 生成的迷宫。我首先制作了一个有 4 行(上、右、下和左)的 Cell 对象。然后我将这些线画在迷宫JPanel 上。我的问题是大多数单元格看起来都很好,但JPanel 的左侧和顶部有粗线,我不知道如何使它成为一个常规网格。

这是我的Cell,我在其中创建线条:

boolean[] walls = {true, true, true, true};

// Draw the lines of one cell with w width and h height
void drawCell(Graphics g, int w, int h){

    // Set the color of the lines to white
    g.setColor(Color.WHITE);

    // If the top wall exists draw a top line
    if (walls[0]) {
        g.drawLine(TopLeftX(), TopLeftY(), TopRightX(w), TopRightY());
    }
    // If a right wall exists draw a right line
    if (walls[1]) {
        g.drawLine(TopRightX(w), TopRightY(), BotRightX(w), BotRightY(h));
    }
    // If a bottom wall exists draw a bottom line
    if (walls[2]) {
        g.drawLine(BotRightX(w), BotRightY(h), BotLeftX(), BotLeftY(h));
    }
    // If a left wall exists draw a left line
    if (walls[3]) {
        g.drawLine(BotLeftX(), BotLeftY(h), TopLeftX(), TopLeftY());
    }
}

// Set each coordinate for the lines, these will make a square that
// is w wide and h high
private int TopLeftX()      { return i;      }
private int TopLeftY()      { return j;      }
private int TopRightX(int w){ return i * w;  }
private int TopRightY()     { return j;      }
private int BotRightX(int w){ return i * w;  }
private int BotRightY(int h){ return j * h;  }
private int BotLeftX()      { return i;      }
private int BotLeftY(int h) { return j * h;  }

w 是单元格的宽度,h 是高度。

这是我的MazeView JPanel 我画线的地方:

class MazeView extends JPanel{

    private Cell grid[][];
    private Cell cell;

    private int row;
    private int col;

    private int width = 600;
    private int height = 580;

    // Create a maze view JPanel that is rows tall and cols wide
    MazeView(int rows, int cols){
        super.setBackground(Color.BLACK);
        super.setLayout(new GridLayout(rows, cols));

        newGrid(rows, cols);
    }

    // Paint all the cells
    public void paintComponent(Graphics g){
        super.paintComponent(g);

        // Get the height and width of each cell
        int h = height / getRows();
        int w = width / getCols();

        // Loop to draw each cell
        for (int i = 0; i <= getRows(); i++){
            for (int j = 0; j <= getCols(); j++){

                grid[i][j].drawCell(g, w, h);
            }
        }
    }
}

感谢我能得到的任何帮助。

运行时,我的网格如下所示:

【问题讨论】:

  • 我不明白你所说的“粗”线是什么意思。难道你只是在那里画了“一半”的迷宫方块?
  • 由于您的面板具有黑色背景,因此白色边框可能不是面板而是其他东西。尝试使用其他颜色进行调试(建议:看看 MiGLayout,IMO 是最好的摇摆布局管理器之一,并具有调试渲染选项)。此外,使用GridLayout 并自己渲染单元格看起来像是代码味道,即要么完全进行布局(因此使用null 布局),要么对单元格使用组件(例如JLabels)。
  • 我不这么认为,因为它完美地绘制了大部分网格。底部的图片链接显示了面板的边缘,看起来好像线条被画得很厚。
  • 这在我看来一点也不像迷宫,所以我不太确定您要做什么。我猜你会得到粗线,因为相关正方形的两条边各画一条线。从简单的东西开始,而不是创建一个大网格。也许2个正方形。看看你在有/没有墙壁的情况下并排绘制它们会发生什么。
  • 1) 提示:添加@GhostCat(或重要的@)以通知此人有新评论。 2) 为了尽快获得更好的帮助,请发布minimal reproducible exampleShort, Self Contained, Correct Example。 3) 请学习常见的 Java 命名法(命名约定 - 例如EachWordUpperCaseClassfirstWordLowerCaseMethod()firstWordLowerCaseAttribute,除非它是 UPPER_CASE_CONSTANT)并始终如一地使用它。

标签: java swing


【解决方案1】:

看看g.drawLine(TopLeftX(), TopLeftY(), TopRightX(w), TopRightY()); - 解析那些你得到坐标i, j, i*w, j 的方法的值。假设ij 是您将画一条线的单元格位置

  • 对于单元格 0/0 从 0/0 到 0/0
  • 单元格 1/0 从 1/0 到 w/0
  • 对于从 0/1 到 0/1 的单元格 0/1
  • 单元格 2/2 从 2/2 到 2*w/2

等等

因此,您需要更正所有 4 个绘制命令的坐标计算。 假设ij 是单元格的网格坐标,wh 是单元格的尺寸,那么左上角的坐标将为i * wj * h,右下角的坐标(i + 1) * w(j + 1) * h

例子:

     0   3   6   9
     --------------> x

0 |  +---+---+---+
  |  |0/0|1/0|2/0|
3 |  +---+---+---+
  |  |0/1|1/1|2/1|
6 |  +---o---+---+ 
  |  |0/2|1/2|2/2|
9 |  +---+---O---+ 
  V
  y

假设每个单元格的宽度和高度为 3 个像素。因此,底部中心单元格的坐标为:

  • 左上角 (o):x = i * w = 1 * 3 = 3y = j * h = 2 * 3 = 6
  • 右下角 (O):x = (i + 1) * w = (1 + 1) * 3 = 6y = (j + 1) * h = (2 + 1) * 3 = 9

【讨论】:

    【解决方案2】:

    嗯,它还不是迷宫。我从绘制每个单元格开始

    不要完全掌握你在尝试什么,但我认为一个单元格需要不同的颜色,而不是线条。因此,例如,白色单元格是玩家可以移动到的地方。黑色的细胞是一堵墙。不知道单条线怎么画迷宫?

    我正在尝试创建一个 DFS 生成的迷宫。

    不知道那是什么,但这里有一些旧代码可能会给你一些想法。

    这是一个迷宫,您可以为每个单元格绘制图标(而不是我上面建议的颜色)。在这个基本实现中,您只有两种类型的图标:

    1. 一层楼
    2. 一堵墙

    包含 0/1 的文件用于识别每个单元格,因此是单元格的图标

    然后你就有了一个可以在地板之间移动的棋子,当它撞到墙上时会被挡住。

    import javax.swing.*;
    import javax.swing.event.*;
    import java.awt.*;
    import java.awt.event.*;
    
    import java.io.*;
    
    public class SmallWorld extends JPanel implements KeyListener, ActionListener
    {
    
        //WORLD
        String[][] worldArray = new String[30][30];
    
        //Block colors
        private static Color redBlock = new Color(255,0,0,255);
        private static Color whiteBlock = new Color(255,255,255,255);
        private static Color blackBlock = new Color(0,0,0,150);
    
        //World images
    //  JLabel wall = new JLabel( new ImageIcon("wall.gif") );
    //  JLabel floor = new JLabel( new ImageIcon("floor.gif") );
        ImageIcon wallIcon = new ImageIcon("dukewavered.gif");
        ImageIcon floorIcon = new ImageIcon("copy16.gif");
    
        //Starting coordinates
        int blockPositionX = 1;
        int blockPositionY = 1;
    
        //Typing area to capture keyEvent
        JTextField typingArea;
        //Viewable area
        JViewport viewable;
        String type = "";
    
        JLayeredPane layeredPane;
        JPanel worldBack;
        JPanel panel;
        JPanel player;
        Dimension worldSize = new Dimension(1500, 1500);
    
        public SmallWorld() {
            super( );
    
            createWorld();
            layeredPane = new JLayeredPane();
            add(layeredPane);
            layeredPane.setPreferredSize( worldSize );
    
            worldBack = new JPanel();
            layeredPane.add(worldBack, JLayeredPane.DEFAULT_LAYER);
            worldBack.setLayout( new GridLayout(30, 30) );
            worldBack.setPreferredSize( worldSize );
            worldBack.setBounds(0, 0, worldSize.width, worldSize.height);
            worldBack.setBackground( whiteBlock );
    
            for (int i = 0; i < 30; i++) {
                for (int j = 0; j < 30; j++) {
                    JPanel square = new JPanel( new BorderLayout() );
                    worldBack.add( square );
                    type = worldArray[i][j];
                    if ( type.equals("1") )
                    {
                        square.add( new JLabel(wallIcon) );
                    }
                    else
                    {
                        square.add( new JLabel(floorIcon) );
                    }
                }
            }
    
            //Draw the player
            player = new JPanel();
            player.setBounds(50, 50, 50, 50);
            player.setBackground( Color.black );
            player.setLocation(50, 50);
            layeredPane.add(player, JLayeredPane.DRAG_LAYER);
            //set where the player starts
    //      panel = (JPanel)worldBack.getComponent( 31 );
    //      panel.add( player );
    
            //Create the typing area with keyListener, add to window
            typingArea = new JTextField(20);
            typingArea.addKeyListener(this);
            typingArea.setEditable( false );
            add(typingArea);
        }
    
        //Get the world from the DAT file and translate it into
        //a 2d array to be used by paintComponent
        public void createWorld() {
            String getData = null;
            int countRow = 0;
    
            try {
                //Get file
                FileReader fr = new FileReader("world.dat");
                BufferedReader br = new BufferedReader(fr);
                getData = new String();
                //read each line from file, store to 2d array
                while ((getData = br.readLine()) != null) {
                    if(countRow < 30) {
                        for (int i = 0; i < 30; i++) {
                            String temp = "" + getData.charAt(i);
                            worldArray[countRow][i] = temp;
                        }
                    countRow++;
                    }
                }
            } catch (IOException e) {
            System.out.println("Uh oh, got an IOException error!");
            e.printStackTrace();
            }
        }
        //Move Block around the world
        public void moveBlock() {
            Point pt = new Point();
            pt.x = blockPositionX * 50;
            pt.y = blockPositionY * 50;
    
            int x = Math.max(0, pt.x - 250);
            int y = Math.max(0, pt.y - 250);
            Rectangle r = new Rectangle(x, y, 550, 550);
            scrollRectToVisible( r );
        }
        //check for collisions with blocks
        public boolean checkCollision(int row, int col) {
            if ( worldArray[col][row].equals("1") ) {
                return true;
            }
            else {
                return false;
            }
        }
    
        public void keyTyped(KeyEvent e) {
    
        }
    
        public void keyPressed(KeyEvent e) {
            updateView( e );
            e.consume();
        }
    
        public void keyReleased(KeyEvent e) {
    
        }
    
        public void actionPerformed(ActionEvent e) {
    
        }
    
        //Update the view of the window based on which button is pressed
        protected void updateView( KeyEvent e ) {
            //if UP
            if ( e.getKeyCode() == 38 ) {
                if ( checkCollision( blockPositionX, blockPositionY - 1 ) == false ) {
                    blockPositionY = blockPositionY - 1;
                    moveBlock();
                    player.setLocation(blockPositionX *50, blockPositionY*50);
                }
            }
            //if DOWN
            if ( e.getKeyCode() == 40 ) {
                if ( checkCollision( blockPositionX, blockPositionY + 1 ) == false ) {
                    blockPositionY = blockPositionY + 1;
                    moveBlock();
                    player.setLocation(blockPositionX *50, blockPositionY*50);
                }
            }
            //if LEFT
            if ( e.getKeyCode() == 37 ) {
                if ( checkCollision( blockPositionX - 1, blockPositionY ) == false ) {
                    blockPositionX = blockPositionX - 1;
                    moveBlock();
                    player.setLocation(blockPositionX *50, blockPositionY*50);
                }
            }
            //if RIGHT
            if ( e.getKeyCode() == 39 ) {
                if ( checkCollision( blockPositionX + 1, blockPositionY ) == false ) {
                    blockPositionX  = blockPositionX + 1;
                    moveBlock();
                    player.setLocation(blockPositionX *50, blockPositionY*50);
                }
            }
        }
    
        private static void createAndShowGUI() {
    
            JFrame frame = new JFrame("SmallWorld");
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    
            JComponent newContentPane = new SmallWorld();
            newContentPane.setPreferredSize( new Dimension(1500, 1500) );
            JScrollPane scrollPane = new JScrollPane( newContentPane );
            scrollPane.setPreferredSize( new Dimension(568, 568) );
            frame.getContentPane().add( scrollPane );
    
            frame.pack();
            frame.setLocationRelativeTo( null );
            frame.setResizable( false );
            //frame.setSize(500,520);
            frame.setVisible( true );
        }
    
        public static void main(String[] args) {
            javax.swing.SwingUtilities.invokeLater( new Runnable() {
                public void run() {
                    createAndShowGUI();
                }
            });
        }
    }
    

    您将需要几个小图标来表示地板/墙壁。

    您还需要一个文件来表示迷宫。这是一个示例“world.dat”文件:

    111111111111111111111111111111
    100010001010001000101000100011
    100010001010001000101000100011
    100011101010000000001000000001
    100010000010000000001000000001
    100110000010000000001000000001
    100000000010000000001000000001
    111100011110000000001000000001
    100000000110001110111000111011
    100000000000001110111000111011
    100000000000000000000000000001
    100010001110000000000000000001
    100010001110001110111000111011
    100011101100000000000000000011
    100010000110001110111000111011
    100110000100000000000000000011
    100000000110000000001000000001
    111100011100000000000000000011
    100000000100000000000000000011
    100000000010000000000000000001
    100000000010000000000000000001
    100010000000000000000000000001
    100010000000001110111000111011
    100011101110000000011000000001
    100010000110000000011000000001
    100110000110000000001000000001
    100000000110001110111000111011
    111100011110000000011000000001
    100000000110000000011000000001
    111111111111111111111111111111
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-11-24
      • 2020-02-18
      • 1970-01-01
      • 1970-01-01
      • 2011-08-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多