首页 > 解决方案 > 战舰坐标输入(带字母)Java

问题描述

我是新来的(stackoverflow 和一般编程),我正在尝试用 Java 创建一个战舰游戏。我对我所拥有的非常满意,并且知道代码可能不是最有效的,但这不是我想在这里解决的问题。

在输入你的船在哪里放置或在哪里攻击时,在我拥有它之前它会询问该列是什么,然后分别询问该行是什么。现在我正在尝试创建一个方法(称为坐标,它是最后一个),允许您一起输入坐标(格式为“A1”)。它工作得很好,直到输入错误(有两个字母,两个数字,里面什么都没有,等等......)

另一件事是,在坐标方法中,我不得不在 catch 中输入 return 20,因为它表示缺少 return 语句,但实际上我不需要返回任何内容,因为这是在 do-while 循环中。我该怎么做才能把它拿走?

这是我在这个网站上的第一个问题,所以我不知道是否有人需要这个(我不知道是否有任何针对不必要代码的规则),但我将把整个程序留在这里,以及一个例子输出。

public static int firing(String[][] board, int hits, int torpedoes, int shipSize, int shipAmount, int whatPlayer)
{
    Scanner userInput = new Scanner(System.in);
    System.out.println("What coordinate do you want?");
    String coordinate = userInput.nextLine();
    int col = coordinates(coordinate, "col");
    int row = coordinates(coordinate, "row");
    while (col > 8 || col < 1 || row > 8 || row < 1)
    {
        System.out.println("That is not a valid coordinate.");
        Scanner input = new Scanner(System.in);
        System.out.println("What coordinate do you want?");
        coordinate = input.nextLine();
        col = coordinates(coordinate, "col");
        row = coordinates(coordinate, "row");
    }

}

public static int letterToNumber(String colLet)
//colLet = column in letter
//This method is to change the column letters to numbers
{
    int num = 1;
    while (!colLet.equalsIgnoreCase("A")&&
           !colLet.equalsIgnoreCase("B")&&
           !colLet.equalsIgnoreCase("C")&&
           !colLet.equalsIgnoreCase("D")&&
           !colLet.equalsIgnoreCase("E")&&
           !colLet.equalsIgnoreCase("F")&&
           !colLet.equalsIgnoreCase("G")&&
           !colLet.equalsIgnoreCase("H"))
    {
        System.out.println("That is not a valid coordinate (not one of the letters)");
        Scanner input = new Scanner(System.in);
        System.out.println("Please enter a valid coordinate: "
                + "\nIt should be in the format 'A1' (column then row)");
        String coordinate = input.nextLine();
        colLet = "" + coordinate.charAt(0);
    }
    switch (colLet.toLowerCase())
    {
        case "a": num = 1; break;
        case "b": num = 2; break;
        case "c": num = 3; break;
        case "d": num = 4; break;
        case "e": num = 5; break;
        case "f": num = 6; break;
        case "g": num = 7; break;
        case "h": num = 8; break;
        default: System.out.println("That wasn't a letter!");
    }
    return num;
}


public static int coordinates(String coordinate, String RorC)
// RorC is for Row or column
{
    boolean isValid;
    if (RorC.equals("row"))
    {
        do
        {
            try
            {
                String rowStr = "" + coordinate.charAt(1);
                int row = Integer.parseInt(rowStr);
                isValid = true;
                return row;
            }
            catch(Exception e)
            {
                System.out.println("Error");
                Scanner userInput = new Scanner(System.in);
                System.out.println("That is an invalid coordinate (row probably only had one character)"
                        + "\nPlease enter a valid coordinate."
                        + "\nIt should be in the format 'A1' (column then row)");
                coordinate = userInput.nextLine();
                isValid = false;
                return 20;
            }
        }while(isValid = false);
    }
    else if (RorC.equals("col"))
    {
        do
        {
            try
            {
                String colLet = "" + coordinate.charAt(0);
                int col = letterToNumber(colLet);
                isValid = true;
                return col;
            }
            catch (Exception e)
            {
                System.out.println("Error");
                Scanner userInput = new Scanner(System.in);
                System.out.println(""
                        + "That is an invalid coordinate (col probably had nothing inside it)"
                        + "\nPlease enter a valid coordinate."
                        + "\nIt should be in the format 'A1' (column then row)");
                coordinate = userInput.nextLine();
                isValid = false;
                return 20;
            }
        }while(isValid=false);
    }
    else
    {
        return 0;
    }
}
}

我知道我的代码效率不高,但我会在完成后清理它。这是一个输出的例子(我不知道如何把它放在一个没有代码格式的盒子里)

It is now player 1's turn to choose where to place their ships.
Can the other player please turn around.

You will now be placing ship number 1.
Please write 'H' if you want to create a horizontal ship,
or 'V' if you want it to be vertical.
h
________________________________

   A  B  C  D  E  F  G  H  
1  -  -  -  -  -  -  -  -
2  -  -  -  -  -  -  -  -
3  -  -  -  -  -  -  -  -
4  -  -  -  -  -  -  -  -
5  -  -  -  -  -  -  -  -
6  -  -  -  -  -  -  -  -
7  -  -  -  -  -  -  -  -
8  -  -  -  -  -  -  -  -
________________________________

What coordinates do you want your ship to start on?
If it is horizontal, it will go right from there,
and if it is vertical, it will go down from there.
Please enter the coordinates in the format 'A1' (column then row).
If you enter anything after that, it will be ignored.
u9
That is not a valid coordinate (not one of the letters)
Please enter a valid coordinate: 
It should be in the format 'A1' (column then row)
a1
That is not a valid coordinate (addship).
What coordinates do you want your ship to start on?
Please enter them in the format 'A1' (column then row).
If you enter anything after that, it will be ignored.
d7
________________________________

   A  B  C  D  E  F  G  H  
1  -  -  -  -  -  -  -  -
2  -  -  -  -  -  -  -  -
3  -  -  -  -  -  -  -  -
4  -  -  -  -  -  -  -  -
5  -  -  -  -  -  -  -  -
6  -  -  -  -  -  -  -  -
7  -  -  -  S  S  S  -  -
8  -  -  -  -  -  -  -  -
________________________________

This is your board.

将不胜感激任何帮助,即使它是关于不同的东西(不是我要解决的问题)。

标签: javatext-based

解决方案


我写了一个小程序,输入一个字符串并将其转换为行和列。它会不断询问用户是否输入了无效的字符串。

样品运行:

Provide a coordinate:
hello?
That is not a valid coordinate! Try again.
X4
That is not a valid coordinate! Try again.
C4
Coordinate{col=3, row=4}

我创建了一个辅助类来存储坐标。

请注意所有读/写操作都在一个函数中(readCoordinate),而所有字符串操作都在另一个函数中(parseCoordinate)。

如果用户字符串无效,您也可以抛出异常,为简单起见,我返回了 null。

package com.company;

import java.util.Scanner;

class Coordinate {
    private final int col, row;

    public Coordinate(int col, int row) {
        this.col = col;
        this.row = row;
    }

    @Override
    public String toString() {
        return "Coordinate{" +
                "col=" + col +
                ", row=" + row +
                '}';
    }
}


public class Main {
    private final Scanner input;

    public static void main(String[] args) {
        Main m = new Main();
        System.out.println(m.readCoordinate());
    }

    Main() {
        input = new Scanner(System.in);
    }

    private Coordinate readCoordinate() {
        System.out.println("Provide a coordinate:");

        while (true) {
            String line = input.nextLine();
            Coordinate c = parseCoordinate(line);

            if (c != null)
                return c;

            System.out.println("That is not a valid coordinate! Try again.");
        }
    }

    /**
     * Converts a string like A2 into a Coordinate object. Returns null if string is invalid.
     */
    public Coordinate parseCoordinate(String line) {
        line = line.trim().toLowerCase();

        if (line.length() != 2)
            return null;

        char letter = line.charAt(0);

        if (letter > 'h' || letter < 'a')
            return null;
        int col = letter - 'a' + 1;

        char number = line.charAt(1);
        if (number > '8' || number < '1')
            return null;
        int row = number - '1' + 1;

        return new Coordinate(col, row);
    }
}

回答问题:

什么是@Override?

它是一个可选的装饰器,标志着我正在覆盖一个方法,而不是创建一个新方法。如果我拼写错误toString,就像tostring我的 IDE 会警告我我实际上并没有覆盖某些东西。你可以忽略它。

为什么 col 和 row 是最终的?这是否意味着您以后无法更改它们?

这意味着您不能在第一次分配(在构造函数中)之后分配给它们。创建不可变(不可变 == 无法更改)数据类是一种很好的做法。例如,您确定如果将 a 传递Coordinate给方法,该方法将无法修改您的实例,并且您不会弄乱Coordinate.

什么是修剪?

Trim 从字符串的两端删除空格(空格、制表符、...)。" hello world! ".trim()"hello world!"

在 main 方法之后带有 Scanner(System.in) 的 Main() 是什么?

我创建了一次扫描仪并多次使用它。每次要读取字符串时,您都会创建一个新的扫描仪。我认为这对扫描仪并不重要,但在某些情况下,您可能会因重新创建对象而丢失东西。

在 readCoordinate 中,while 条件中的 true 是什么?

while (true)意味着永远循环。有一个 return 语句打破了原本无限循环。

在 parseCoordinate 中,定义 col 时,如何将字符添加到 int 中?

字符使用数字表示,因此字符是引擎盖下的数字。在 Javachar中就像一个 16 位无符号整数,您可以对它们进行正常的整数计算。

为什么 readCoordinate 是 Coordinate 类型的,为什么它是私有的?

在您对编程有更好的了解之前,不要使用访问修饰符。在小程序中没有多大意义。您可以标记哪些方法应该从外部调用,哪些方法不应该。


推荐阅读