我在为此作业生成正确的输出时遇到了一些麻烦,并且不确定我做错了什么。
N x N棋盘上有K个骑士,你要确定他们守卫的方格数。如果一个正方形被一个占用,则一个正方形被保护 骑士或骑士可以通过一次动作到达骑士。 编写一个程序,读取正整数N和K,然后写入骑士的K个位置,并打印出 由这些K骑士守卫的方格数量。
输入示例:8 2 c 1 e 2
对应输出:10
输入示例:8 6 c 1 e 2 d 4 c 7 f 7 h 6
对应输出:30
当我输入第一个例子时,它可以工作,但是当我输入第二个例子时它给了我34
package knightguard;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Scanner;
import java.util.Set;
public class KnightGuard {
static class Position {
int x;
int y;
public Position(int x, int y) {
this.x = x;
this.y = y;
}
public boolean equals(Position p) {
if (p.x == x && p.y == y) {
return true;
}
return false;
}
@Override
public String toString() {
return x + "," + y;
}
}
ArrayList<Position> knightPositions;
int size;
int no_of_knights;
public KnightGuard(int size, int k, ArrayList<Position> knightPositions) {
this.knightPositions = knightPositions;
no_of_knights = k;
this.size = size;
}
public int getSafePositions() {
Set<Position> safePos = new HashSet<>();
for (Position p : knightPositions) {
if (isValid(p.x - 2, p.y - 1)) {
safePos.add(new Position(p.x - 2, p.y - 1));
}
if (isValid(p.x - 2, p.y + 1)) {
safePos.add(new Position(p.x - 2, p.y + 1));
}
if (isValid(p.x + 2, p.y - 1)) {
safePos.add(new Position(p.x + 2, p.y - 1));
}
if (isValid(p.x + 2, p.y + 1)) {
safePos.add(new Position(p.x + 2, p.y + 1));
}
if (isValid(p.x - 1, p.y - 2)) {
safePos.add(new Position(p.x - 1, p.y - 2));
}
if (isValid(p.x - 1, p.y + 2)) {
safePos.add(new Position(p.x - 1, p.y + 2));
}
if (isValid(p.x + 1, p.y - 2)) {
safePos.add(new Position(p.x + 1, p.y - 2));
}
if (isValid(p.x + 1, p.y + 2)) {
safePos.add(new Position(p.x + 1, p.y + 2));
}
}
return safePos.size();
}
private boolean isValid(int x, int y) {
if (x < 0 || x >= size || y < 0 || y >= size) {
return false;
}
if (knightPositions.contains(new Position(x, y))) {
return false;
}
return true;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
int size = s.nextInt();
int knights = s.nextInt();
ArrayList<Position> knightPos = new ArrayList<>();
for (int i = 0; i < knights; i++) {
int x = s.next().charAt(0) - 'a';
int y = s.nextInt() - 1;
knightPos.add(new Position(x, y));
}
KnightGuard knightGuard = new KnightGuard(size, knights, knightPos);
System.out.println(knightGuard.getSafePositions());
s.close();
}
}
答案 0 :(得分:1)
使用这种方法的一个问题是可能为不同的骑士生成可能的重复位置。例;使用帖子中的图片,位置D4和H6的两个骑士可以在F5处移动到正方形。因此,发布的代码将计算此位置TWICE。理论上,在八个不同的位置可能有八(8)名骑士,所有骑士都可以移动到同一个方格。必须进行检查以消除这些可能的“重复”位置。
我对KnightGuard
类和getSafePositions
方法感到有些困惑。 KnightGuard
类有一个位置列表,这是给定骑士的位置列表。然而,getSafePositions
方法只返回所有骑士可以从各自位置移动的不同移动的数量。此方法没有考虑到前一个骑士也可以移动到第一段所述的相同位置。
为了简化事情......我觉得一个名为Knight
的课程会更好。骑士会有一个Position
变量来指示“这个”骑士在棋盘上的位置。另外,Knight
类将包含ArrayList
个Position
个对象,以指示此骑士在其位置可以做出的所有可能移动。 Knight
不应该知道任何其他Knights
,并且它可以移动到的位置列表是它可以移动到的所有位置,无论该位置是否有另一块。该列表至少包含两(2)个位置,最多包含八(8)个不同的位置。
当创建一个新的Knight
对象时,可能会在实例化时自动生成可能的移动列表以及它在板上的位置,我们将在稍后使用。
以下是此Knight
课程的示例。应该注意的是,在这个类和main方法中,我改变了板的索引,从左边的1(a)不是零(0)开始向右移动,也在y底部y索引的y索引处开始是1并向上移动。此外,还创建了SetValidMoves
方法,以允许此骑士可以移动的位置列表进行更改。如果另一位骑士占据这个骑士的守卫位置列表中的一个位置,则可能需要这样做。这段代码没有利用这个优势,因为我们只对守卫方格的数量感兴趣。
public class Knight {
Position knightPosition;
ArrayList<Position> validMoves;
int boardSize;
public Knight(Position position, int inBoardSize) {
knightPosition = position;
validMoves = new ArrayList<Position>();
boardSize = inBoardSize;
SetValidMoves();
}
public Position GetKnightPosition() {
return knightPosition;
}
public ArrayList<Position> GetValidMoves() {
return validMoves;
}
public void SetValidMoves(ArrayList<Position> newMoves) {
validMoves = newMoves;
}
private void SetValidMoves() {
int thisX = knightPosition.x;
int thisY = knightPosition.y;
// check for bottom moves 2 down 1 left - right
if (thisY - 2 >= 1) {
if (thisX + 1 <= boardSize) {
validMoves.add(new Position(thisX + 1, thisY - 2));
}
if (thisX - 1 >= 1) {
validMoves.add(new Position(thisX - 1, thisY - 2));
}
}
// check for bottom moves 1 down 2 left - right
if (thisY - 1 >= 1) {
if (thisX + 2 <= boardSize) {
validMoves.add(new Position(thisX + 2, thisY - 1));
}
if (thisX - 2 >= 1) {
validMoves.add(new Position(thisX - 2, thisY - 1));
}
}
// check for top moves 2 up 1 left - right
if (thisY + 2 <= boardSize) {
if (thisX + 1 <= boardSize) {
validMoves.add(new Position(thisX + 1, thisY + 2));
}
if (thisX - 1 >= 1) {
validMoves.add(new Position(thisX - 1, thisY + 2));
}
}
// check for top moves 1 up 2 left - right
if (thisY + 1 <= boardSize) {
if (thisX + 2 <= boardSize) {
validMoves.add(new Position(thisX + 2, thisY + 1));
}
if (thisX - 2 >= 1) {
validMoves.add(new Position(thisX - 2, thisY + 1));
}
}
}
}
使用ArrayList
个Knight
个对象(knightsOnBoard
),可以循环思考此列表并创建ArrayList
个Position
个对象({{ 1}})每个validMoves
表示一个或多个骑士守卫的位置。由于不需要重复,我们只是忽略已经在Position
列表中的位置。
validMoves
是knightsOnBoard
个对象的全局列表
Knight
由于上述代码使用private static ArrayList<Position> GetAllDifferentPositions() {
ArrayList<Position> validMoves = new ArrayList<Position>();
for (Knight curKnight : knightsOnBoard) {
for (Position curPos : curKnight.validMoves) {
if (!validMoves.contains(curPos)) {
validMoves.add(curPos);
}
}
}
return validMoves;
}
属性检查位置是否已在列表contains
中,因此需要在validMoves
类中进行更改以公开公开{{1}使用Object参数的方法。
Position
现在我们有equals
个@Override
public boolean equals(Object obj) {
if (obj instanceof Position) {
Position other = (Position)obj;
if (this.x == other.x && this.y == other.y)
return true;
}
return false;
}
个没有重复项的对象。不幸的是,还有最后一个障碍需要明确。需要检查ArrayList
是否可以移动到正方形但是已经被另一个骑士占用了。因此,我们需要移除骑士可以移动到的位置列表中的所有“骑士”位置。
必须这样做的原因是我们需要将所有给定Position
的位置添加到计数中,因为骑士坐在的方格也是一个“守卫”的方格。由于这个位置可能已经在列表中...我们需要删除它们。换句话说,我们知道Knight
在其移动列表中不会有“其”自己的位置,但是在移动列表中可能有另一个Knight
位置。
Knight
现在位置列表(下面的Knight
)没有重复,此外,我们知道列表中没有任何骑士所在的位置。因此,守卫方格的数量将是位置列表中private static void RemoveAllKnightPositions(ArrayList<Position> allPositions) {
for (Knight curKnight : knightsOnBoard) {
if (allPositions.contains(curKnight.knightPosition)) {
allPositions.remove(curKnight.knightPosition);
}
}
}
加上骑士数量的位置数。
最后,将这些全部放在下面的主要方法中。请注意,代码会更改索引顺序,因此BOTH x和y从一(1)开始,到finalResults
结束。我希望这是有道理和有帮助的。
finalResults