0

I am relatively new to java and I have been assigned a project. I need to make a rather complicated(for a newbie) battleship game.

Here, I try to call switch cases in class Player from class Tile. Since I've read that one can't directly have access to a switch case, I have made the methods caseSea(), caseShip() e.t.c.

When trying to call them in class Player I get a 'void' type not allowed here error, which I understand but have no idea how to fix! Any help would be appreciated thanks!

Here is class Tile created to represent one block of a 2D array that will become the battleground board:

public class Tile
{
    private int x,y;
    static boolean hidden;
    public Action tile_action;


    public enum Action
    {
        Sea,
        Ship,
        Hit,
        Miss
    }
    Action action;
    public Tile(Action action)
    {
        this.action=action;
        this.x = x;
        this.y = y;
        this.tile_action = action;
    }
    public static void caseSea()
    {
        System.out.println("~");
    }
    public static void caseShip()
    {
        if(hidden == true)
                    System.out.println("~");
                else
                    System.out.println("s");
    }
    public static void caseHit()
    {
        System.out.println("X");
    }
    public static void caseMiss()
    {
        System.out.println("O");
    }
    public static void draw(Action action)
    {
        switch(action)
        {
            case Sea:
                caseSea();
                break;
            case Ship:
                caseShip();
                break;
            case Hit:
                caseHit();
                break;
            case Miss:
                caseMiss();
                break;            
        }

    }

}

Also here is class Player which contains the call to the switch case:

import java.util.Scanner;

public class Player
{
    String username; //Variable declaration
    static int shotcount;
    static int misscount;
    static int hitcount;
    static int repeatshot;
    private int HitPosition[][] = new int[10][10];


    public Player(String username)
    {
        this.username = username;
    }
    private void placeAllShips()
    {
        //super.placeAllShips();
    }

    public void fire(int pos[],int board,boolean hit)
    {
        if(hit == true)
        {
            HitPosition[pos[0]][pos[1]] = Tile.draw(Tile.caseHit());
            shotcount++;
            hitcount++;
        }

        else
        {
            HitPosition[pos[0]][pos[1]] = Tile.draw(Tile.caseMiss());               
            shotcount++;
            misscount++;
        }        
    }
}

I get the error that I mention above, in Tile.draw(Tile.caseHit()) and Tile.draw(Tile.caseMiss())

khelwood
  • 55,782
  • 14
  • 81
  • 108
vaskar
  • 35
  • 8
  • 1
    You are calling the draw method with the return value of `caseHit()` which is void. You probably want to use `Tile.Action.Hit`, the enum-value. – Ben May 22 '18 at 09:37
  • Also sidenote: It's considered good design to always have a `default` branch in your switch-statements throwing an Exception, etc.. This way, when you e.g. add another type to your enum you will immediately notice you need to update your statement. – Ben May 22 '18 at 09:38
  • Exactly as @Ben said. Your method takes a parameter of type Action, so you must pass one of the enum values. What you are passing now is void (as the method you call returns void). Also what do you mean by "one can't directly have access to a switch case"? – Jan Ossowski May 22 '18 at 09:39
  • @Ben When i make the change you suggested I get the following error in the same spot as before: incompatible types : Tile.Action cannot be converted to int.... Just to be clears the ONLY change I made in my code was changing `Tile.draw(Tile.caseMiss())` to `Tile.draw(Tile.Action.Miss)` – vaskar May 22 '18 at 10:00
  • @Jan Ossowski Check the first answers to this question in Stack Overflow : https://stackoverflow.com/questions/31498571/can-we-call-a-case-inside-another-case-in-the-same-switch-statement-in-java – vaskar May 22 '18 at 10:02
  • @vaskar, I think you misunderstood what it says. Having a switch statement, there is no direct way to "call one of the cases", the case to be called is resolved based on the switch value, but it's not like you cant execute code inside. The methods you wrote is indeed a good practice (increases readability) but all it does is "when the `action` has value `Sea`, execute method `caseSea()`. Nothing more. What u pass as `action` is an enum value, nothing fancier – Jan Ossowski May 22 '18 at 10:08

2 Answers2

0

Heh, since this is a relatively simple issue I wanted to stick to comments, but I feel I need to make my voice since the other answers are simply wrong. What the other guys are suggesting is changing the return type of the methods, and that indeed can work but not with the code you have. They would ultimately be called twice, and thats not what you want. The call order would be

  1. caseHit()

  2. pass the caseHit()'s value to draw()

  3. enter a switch inside the draw() method with the Hit enum value and ultimately call caseHit() again.

This is not what you want to do. All you wanna do is call the draw() method with the right argument, which in this case is one of the Action enum values.

So ultimately there is a very easy way to fix your code without much changes and this is changing Tile.draw(Tile.caseHit()); to Tile.draw(Tile.Action.Hit);

(and by analogy the other calls of this method)

Jan Ossowski
  • 328
  • 1
  • 2
  • 18
  • As I answered to Ben in the comments if I call the `draw()` method like you said , i get an : Tile.Action cannot be converted to int error. – vaskar May 22 '18 at 10:38
  • Your code definitely has more problems, your `draw()` method returns void and you are trying to assign it to an `int` here `HitPosition[pos[0]][pos[1]] = Tile.draw(Tile.caseHit());`. I do not understand what this is supposed, so it's hard to make an improvement suggestion. I can only suggest starting with simpler exercises if you have so basic problems. However, the problem you mention can't be an effect of the changes I suggested, as I don't suggest ever returning 'Tile.Action'. – Jan Ossowski May 22 '18 at 12:45
-1

With Tile.draw(Tile.caseHit()) you are trying to call the caseHit() method and sending the return value of that method as a parameter to the draw() method. The problem is that the caseHit() method isn't returning anything as it has a void return type.

You could fix this by making the caseHit() method return an Action:

public static Action caseHit() {
   return Action.Hit;
}
Pepijn Compaan
  • 64
  • 1
  • 1
  • 5