当前位置: 首页 > 知识库问答 >
问题:

在Java中绘制线条以创建单元格

曾元忠
2023-03-14

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

这是我的单元格,我在这里创建行:

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是高度。

这是我的MazeViewJBoard,我在其中画线:

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);
            }
        }
    }
}

我很感激能得到的任何帮助。

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

共有2个答案

屈星腾
2023-03-14

嗯,这还不是一个迷宫。Im从绘制每个单元格开始

不要完全理解你在尝试什么,但是我认为一个单元格需要不同的颜色,而不是线条。例如,白色单元格是玩家可以移动的地方。黑色单元格是一堵墙。我不确定绘制单独的线会如何形成迷宫?

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

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

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

  1. a层
  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
白智
2023-03-14

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

  • 对于从0/0到0/0的单元格0/0
  • 对于从1/0到w/0的单元格1/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=3和y=j*h=2*3=6

 类似资料:
  • 所以我在只用线绘制形状时遇到了一个大问题。假设我从屏幕中间的一个点开始画一条线,然后以100个像素的距离向前画,角度为0,然后我用角度72度画另一条相同长度的线,以此类推,直到360度。它应该给我一个完美的五边形,一条线结束,另一条线从那个点开始,但是线在末端不相交,它非常适合角度为0/90/180/270的正方形,但我需要让它适用于每个形状,甚至是圆。我用这个东西来计算: 其中_cosinuse

  • 问题内容: 我试图在bufferedimage上绘制水平和垂直线。它最终应该看起来像一个网格单元。但是,当我运行代码时,我只看到两行:最左边的行和最上面的行(即,从0,0到0,图像的高度和从0,0到图像的宽度,0的一行),这里是代码段: 和覆盖的绘制方法: 所有这些都在扩展了JPanel的名为RobotMaze的类中。任何帮助表示赞赏。 问题答案:

  • 我正在尝试使用swing制作一个rpg(是的,这是愚蠢的,我同意,但我这样做是为了学习,而不是实际的工作产品)。目前我正在研究每个角色的统计。 我有一个JPanel,我想画一条线。 左侧是一个JPanel,它有两个组件:表1和JLabel。右侧也是JPanel,它有自己的元素,但那是另一回事了。 我的问题是,我想创建一个只有一个图像的jpanel,该图像将是两行,与表中选定的元素相关。 但不幸的是

  • 主要内容:示例可以使用类的方法在图像上绘制一条线。以下是此方法的语法。 该方法接受以下参数 - mat - 表示要在其上绘制线条的图像的Mat对象。 pt1和pt2 - 表示要绘制线条的点的两个点对象。 scalar - 表示圆的颜色的标量对象(BGR)。 thickness - 表示线条粗细的整数; 默认情况下,厚度值为。 示例 以下程序演示如何在图像上绘制线条并使用JavaFX窗口显示。 在执行上述程序时,

  • 我正在为wordpress做一个菜单,我正在尝试在不同的菜单项周围画一个类似“绘制”的边框。 至于现在,我有一个“画”圈的背景。(我们就叫它BG.PNG吧)。 我可以得到一个菜单项周围的圆圈,并将其正确放置。当然,我的一些菜单项的单词比其他的要长。 这就是我现在如何使用菜单的活动部分: 这显示了当悬停菜单项时的圆圈,但在某些单词上它太大或太小。这与我正在使用的png类似:http://instan

  • 我想创建一个包含三条线(男性、女性、未知)的折线图。这是我的数据示例: 是否有一个选项,在图中自动创建三行或我需要循环通过数据和创建三个跟踪自己?到目前为止,这是我的代码: