如何检查玩家是否访问了演奏板的所有面板?

发布于 2025-02-11 04:28:12 字数 2165 浏览 1 评论 0原文

我正在MOOC.FI的Java第2部分,第10周进行一次练习。它被称为Dungeon。 基本上,您有一个弹奏板(使用字符串[]数组创建)和一个移动它的播放器。启动游戏时,可以设置板的大小(Lenght和高度)。

如果您通过包含字母“ WASD”的字符串,则播放器将相应地更改位置,并在板上重新出现,只要移动在范围内。如果没有,将忽略播放器的命令将被忽略,但其余的仍将执行。 因此,如果用户输入“ WASD”,并且S将播放器从界限中移出,则实际执行了“ WAD”。

如果已经处理了整个命令,则播放器只有在新位置上重新出现。

现在,如果您追捕了所有敌人,或者玩家去过董事会的所有pannels,您要么获胜。但是我不确定如何检查玩家去过董事会上的所有可能位置?

我认为我可以使用包含板上所有坐标的hashmap的列表,并将其与包含玩家所做的所有动作的类似列表进行比较,但这似乎不起作用。

这是设置板的方法。这也是我认为我可以从董事会中获得所有可能的坐标的地方,我将它们存储在名为“板”的列表中:

for(int i = 0; i < length; i++)
    {
        for(int j = 0; j < height; j++)
        {
            board[i][j] = ".";
            HashMap<Integer,Integer> values = new HashMap<Integer,Integer>();
            values.put(i,j);
            this.boardPlaces.add(values);
        }
    }

这是播放器方法,在该播放器中,处理了播放器移动的字符串并记录了播放器移动:

public void updatePosition(String m)
{
    
    char[] c = m.toCharArray();
    playerMoves = new String[c.length];
    for(int i = 0; i < c.length; i++)
    {
        playerMoves[i] = String.valueOf(c[i]);
    }
    
    for(String move : playerMoves)
    {
        if(move.equals("w") && y-1 >= 0)
        {
            this.y--;
        }
        if(move.equals("s") && y+1 <= height-1)
        {
            this.y++;
        }
        if(move.equals("a") && x-1 >= 0)
        {
            this.x--;
        }
        if(move.equals("d") && x+1 <= length-1)
        {
            this.x++;
        }
        HashMap<Integer,Integer> values = new HashMap<Integer,Integer>();
        values.put(x,y);
        movesRecorded.add(values);
    }
    moves--;
}

在这里,我检查了玩家是否实际访问了董事会的所有平板。

int counter1 = 0;
    int counter2 = 0;
    this.playerMovesRecorded = player.getMovesRecorded();
    for(HashMap map : boardPlaces)
    {
        counter1++;
    }
    for(HashMap map : playerMovesRecorded)
    {
        counter2++;
    }
    return (counter1 == counter2) /*and contents of lists are the same*/|| vamps.isEmpty();

我认为元素的数量是否正确,内容匹配,则应返回true - &gt;玩家访问了所有董事会。 但是我不确定如何比较两个列表的内容?

I am working on an exercise from Mooc.fi's java part 2, week 10. It is called Dungeon.
Basically you have a playing board(created with a String[][] array) and a player that moves on it. The size of the board(lenght and height) can be set when starting the game.

If you pass a string containing the letters "wasd" the player will change position accordingly and reappear on the board as long as the move is within the bounds. If not, the command that would set the player out of bounds is ignored but the rest is still executed.
So if the user enters "wasd" and s would carry the player out of bounds, only "wad" is actually executed.

The player will only reappear on the new position if the entire command entered has been processed.

Now, you either win if you hunted down all the enemies, or if the player has been to all the pannels of the board. But I'm not sure how I can check that the player has been to all possible positions on the board?

I figured I could use a List containing HashMaps with all the coordinates of the board and compare that with a similar list that contains all the moves the player made, but that does not seem to work.

Here is the method that sets up the board. This is also where I figured I could get all possible coordinates of the board from, I stored them in a list called boardPlaces:

for(int i = 0; i < length; i++)
    {
        for(int j = 0; j < height; j++)
        {
            board[i][j] = ".";
            HashMap<Integer,Integer> values = new HashMap<Integer,Integer>();
            values.put(i,j);
            this.boardPlaces.add(values);
        }
    }

And this is the player method where the string entered for the movement of the player is processed and the player moves are recorded:

public void updatePosition(String m)
{
    
    char[] c = m.toCharArray();
    playerMoves = new String[c.length];
    for(int i = 0; i < c.length; i++)
    {
        playerMoves[i] = String.valueOf(c[i]);
    }
    
    for(String move : playerMoves)
    {
        if(move.equals("w") && y-1 >= 0)
        {
            this.y--;
        }
        if(move.equals("s") && y+1 <= height-1)
        {
            this.y++;
        }
        if(move.equals("a") && x-1 >= 0)
        {
            this.x--;
        }
        if(move.equals("d") && x+1 <= length-1)
        {
            this.x++;
        }
        HashMap<Integer,Integer> values = new HashMap<Integer,Integer>();
        values.put(x,y);
        movesRecorded.add(values);
    }
    moves--;
}

And this here is where I check if all pannels of the board have actually been visited by the player.

int counter1 = 0;
    int counter2 = 0;
    this.playerMovesRecorded = player.getMovesRecorded();
    for(HashMap map : boardPlaces)
    {
        counter1++;
    }
    for(HashMap map : playerMovesRecorded)
    {
        counter2++;
    }
    return (counter1 == counter2) /*and contents of lists are the same*/|| vamps.isEmpty();

I figured if the number of elements is correct and the content matches it should return true -> player has visited all boards.
But I'm not sure how I should go about comparing the content of the two lists?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

萌︼了一个春 2025-02-18 04:28:12

您可以创建自定义类,也可以创建另一个数组来捕获信息,

public class BoardTile {
  String info;
  boolean visited;
}

然后使用boardtile [] [] []而不是string [] [] [] [] []

,另外您可以创建一个单独的2D布尔值

private boolean[][] visited = new boolean[widthOfBoard, heightOfBoard];

You can either create a custom class or create another array to capture the information, like

public class BoardTile {
  String info;
  boolean visited;
}

And then use a BoardTile[][] instead of a String[][]

Alternatively, you could create a separate 2D array of booleans

private boolean[][] visited = new boolean[widthOfBoard, heightOfBoard];
甲如呢乙后呢 2025-02-18 04:28:12

为什么您的地图不起作用:

您使用的是map&lt; integer,Integer&gt;。对于每个独特的整数,此映射可以存储另一个整数(it“ MAP” Integer to Integer

示例数据集您当前的地图

{
    1: 3
    2: 5
    4: -2
}

这显然不是您想要的。您可能想要这样的东西(映射2 Integer s到string

{
    "1/3": "WALL"
    "2/5": "WALL"
    "4/-2": "GROUND"
}

由于无法使用2个键,因此您需要包装程序类。 暂时):

public interface Vector {
    int getX();

    int getY();

    default Position add(Vector other) {
        return new Position(getX() + other.getX(), getY() + other.getY());
    }

    default Position subtract(Vector other) {
        return new Position(getX() - other.getX(), getY() - other.getY());
    }
}

public record Position(int x, int y) implements Vector {
}

记录只是仅包含最终属性的类的缩写,并实现了hashcodeequals

。 这样:

Map<Position, String> map = new HashMap<>();

或保存许多位置 s播放器已经输入的,请执行此操作:

Set<Position> list = new HashSet<>();

a set只能包含一个每个值,因此您可以添加 只会保存第一个。

相同的位置一遍又一遍地,但

它 //en.wikipedia.org/wiki/object-oriented_programming“ rel =” nofollow noreferrer“>面向对象的编程语言

。在这里的类使事物面向对象:

  1. 不使用字符串存储非文本数据,

因为无论如何您所拥有的不同tile s的数量是有限的,您可以创建一个枚举。我假设您有2个瓷砖 s(墙壁和地面)。

public enum Pattern {
    GROUND,
    WALL
}
  1. 捆绑有关tile的所有信息:
public class Tile {
    private final Pattern pattern; // The kind of Tile doesn't change.
    private final Position pos; // The pos doesn't change.
    private boolean visited; // Whether you entered the Tile can change.

    public Tile(Pattern pattern, Position pos) {
        this.pattern = pattern;
        this.pos = pos;
    }
    
    public Position getPos() {
        return pos;
    }

    public void markVisited() {
        visited = true;
    }

    public boolean isVisited() {
        return visited;
    }
}
  1. 捆绑有关董事会的所有信息。
  • 您可以将严格的边界应用于board(请参阅GetTile1),
  • 也可以使其包裹(比您想象的要容易)(请参阅GetTile2)。
public class Board {
    private final int width, heigth;
    private final Tile[][] tiles;

    public Board(int width, int height) {
        this.width = width;
        this.height = height;
        this.tiles = new Tile[width][height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                tiles[x][y] = new Tile(Pattern.GROUND);
            }
        }
    }

    public Tile getTile1(Position pos) {
        int x = Math.max(0, Math.min(width - 1, pos.getX()));
        int y = Math.max(0, Math.min(height - 1, pos.getY()));
        return tiles[x][y];
    }

    public Tile getTile2(Position pos) {
        int x = Math.floorMod(x, width);
        int y = Math.floorMod(y, height);
        return tiles[x][y];
    }
}
  1. 代替字符串 s,进行枚举Direction
public enum Direction implements Vector {
    UP(0, -1, 'w'), DOWN(0, 1, 's'), LEFT(-1, 0, 'a'), RIGHT(1, 0, 'd');

    private final int x, y;
    private final char keyChar;

    Direction(int x, int y, char keyChar) {
        this.x = x;
        this.y = y;
        this.keyChar = keyChar;
    }

    public static Direction forKeyChar(char keyChar) {
        for (Direction dir : values()) {
            if (dir.keyChar == keyChar) return dir;
        }
        throw new IllegalArgumentException("No Direction for keyChar " + keyChar);
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

强大的功能:

  1. 更新播放器位置(我假设您选择了> > getTile1getTile2已经称为getTile
private Board board = new Board();
private Tile playerTile = board.getTile(new Position(x, y));

代码要更新:

对于每个按键,您现在可以添加所有Direction s一起获得位置,它充当vector

String m = ...;
Position change = new Position(0, 0);
for (char c : m.toCharArray()) pos = pos.add(Direction.forKeyChar(c));
Tile newPlayerPos = board.getTile(playerTile.getPos().add(change));
  1. 解决您的问题

将此方法添加到board

public boolean allVisited() {
    for (int y = 0; y <= height; y++) {
        for (int x = 0; x <= height; x++) {
            if (!tiles[x][y].isVisited()) return false;
        }
    }
    return true;
}

注意:我t检查任何代码,希望它有效!

Why your Map doesn't work:

You are using a Map<Integer, Integer>. For each distinct Integer, this map can store another Integer (it "maps" Integer to Integer)

Example dataset of your current Map:

{
    1: 3
    2: 5
    4: -2
}

This is obviously not what you want. You likely want something like this (Mapping 2 Integers to a String:

{
    "1/3": "WALL"
    "2/5": "WALL"
    "4/-2": "GROUND"
}

Because having 2 keys isn't possible, you need a wrapper class. (Ignore Vector for now):

public interface Vector {
    int getX();

    int getY();

    default Position add(Vector other) {
        return new Position(getX() + other.getX(), getY() + other.getY());
    }

    default Position subtract(Vector other) {
        return new Position(getX() - other.getX(), getY() - other.getY());
    }
}

public record Position(int x, int y) implements Vector {
}

record is just an abbreviation for a class that only contains final attributes and implements hashCode and equals.

Now you can create your Map like this:

Map<Position, String> map = new HashMap<>();

Or to save a number of Positions the player already entered, do this:

Set<Position> list = new HashSet<>();

A Set can only contain each value once, so you can add the same Position over and over again, but it will only the first one will be saved.

Why I would not do that:

Java is an Object-oriented programming language. You can bundle information and simplify problems by using an object-oriented approach.

Let's create a few classes here to make things object-oriented:

  1. Not using String to store non-textual data

Because the amount of different Tiles you have is limited anyway, you can create an enum. I assume you have 2 Tiles (WALL and GROUND).

public enum Pattern {
    GROUND,
    WALL
}
  1. Bundling all information about a Tile:
public class Tile {
    private final Pattern pattern; // The kind of Tile doesn't change.
    private final Position pos; // The pos doesn't change.
    private boolean visited; // Whether you entered the Tile can change.

    public Tile(Pattern pattern, Position pos) {
        this.pattern = pattern;
        this.pos = pos;
    }
    
    public Position getPos() {
        return pos;
    }

    public void markVisited() {
        visited = true;
    }

    public boolean isVisited() {
        return visited;
    }
}
  1. Bundling all information about a board.
  • You can either apply strict boundaries to your Board (see getTile1),
  • or make it wrap (way easier than you probably think) (see getTile2).
public class Board {
    private final int width, heigth;
    private final Tile[][] tiles;

    public Board(int width, int height) {
        this.width = width;
        this.height = height;
        this.tiles = new Tile[width][height];
        for (int y = 0; y < height; y++) {
            for (int x = 0; x < width; x++) {
                tiles[x][y] = new Tile(Pattern.GROUND);
            }
        }
    }

    public Tile getTile1(Position pos) {
        int x = Math.max(0, Math.min(width - 1, pos.getX()));
        int y = Math.max(0, Math.min(height - 1, pos.getY()));
        return tiles[x][y];
    }

    public Tile getTile2(Position pos) {
        int x = Math.floorMod(x, width);
        int y = Math.floorMod(y, height);
        return tiles[x][y];
    }
}
  1. Instead of using Strings, make an enum Direction:
public enum Direction implements Vector {
    UP(0, -1, 'w'), DOWN(0, 1, 's'), LEFT(-1, 0, 'a'), RIGHT(1, 0, 'd');

    private final int x, y;
    private final char keyChar;

    Direction(int x, int y, char keyChar) {
        this.x = x;
        this.y = y;
        this.keyChar = keyChar;
    }

    public static Direction forKeyChar(char keyChar) {
        for (Direction dir : values()) {
            if (dir.keyChar == keyChar) return dir;
        }
        throw new IllegalArgumentException("No Direction for keyChar " + keyChar);
    }

    public int getX() {
        return x;
    }

    public int getY() {
        return y;
    }
}

How powerful this is:

  1. Updating the player position (I assume you chose either getTile1 or getTile2 already and called it simply getTile)
private Board board = new Board();
private Tile playerTile = board.getTile(new Position(x, y));

Code to update:

For each key pressed, you can now add all of the Directions together to obtain a Position, which acts as a Vector:

String m = ...;
Position change = new Position(0, 0);
for (char c : m.toCharArray()) pos = pos.add(Direction.forKeyChar(c));
Tile newPlayerPos = board.getTile(playerTile.getPos().add(change));
  1. Solve your problem

Add this method into Board:

public boolean allVisited() {
    for (int y = 0; y <= height; y++) {
        for (int x = 0; x <= height; x++) {
            if (!tiles[x][y].isVisited()) return false;
        }
    }
    return true;
}

Note: I didn't check any of the code, hope it works!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文