3

The method public boolean mergesWith(Tile moving) returns true if this and moving tiles have the same value. But when I check if they are the same by doing the following:

if(this.value == temp.value){
    return true;
}

then it shows me error on temp.value saying that value cannot be resolved or is not a field.

How can I fix that?

Class TwoNTile:

package Game2048;

// Concrete implementation of a Tile. TwoNTiles merge with each other
// but only if they have the same value.

public class TwoNTile extends Tile {

    private int value;

    // Create a tile with the given value of n; should be a power of 2
    // though no error checking is done
    public TwoNTile(int n){
        value = n;
    }

    // Returns true if this tile merges with the given tile. "this"
    // (calling tile) is assumed to be the stationary tile while moving
    // is presumed to be the moving tile. TwoNTiles only merge with
    // other TwoNTiles with the same internal value.
    public boolean mergesWith(Tile moving){
        Tile temp = moving;
        if(this.value == temp.value){
            return true;
        }
        else{
            return false;
        }
    }

    // Produce a new tile which is the result of merging this tile with
    // the other. For TwoNTiles, the new Tile will be another TwoNTile
    // and will have the sum of the two merged tiles for its value.
    // Throw a runtime exception with a useful error message if this
    // tile and other cannot be merged.
    public Tile merge(Tile moving){

        return null;
    }

    // Get the score for this tile. The score for TwoNTiles are its face
    // value.
    public int getScore(){

        return -1;
    }

    // Return a string representation of the tile
    public String toString(){

        return "";
    }
}

Class Tile:

package Game2048;

// Abstract notion of a game tile.
public abstract class Tile{
  // Returns true if this tile merges with the given tile. 
  public abstract boolean mergesWith(Tile other);

  // Produce a new tile which is the result of merging this tile with
  // the other. May throw an exception if merging is illegal
  public abstract Tile merge(Tile other);

  // Get the score for this tile.
  public abstract int getScore();

  // Return a string representation of the tile
  public abstract String toString();

}
Enamul Hassan
  • 5,266
  • 23
  • 39
  • 56
  • There's no field called `value` in the class `Tile` and you're passing a `Tile` to the method, not a `TwoNTile` – xp500 Jul 14 '15 at 00:14
  • But if `Tile` class is `abstract` and cannot create objects, is it the only way to that, i.e. declare a `int value` in `Tile` class? @xp500 –  Jul 14 '15 at 00:17
  • You can still call constructors of the abstract class from the subclasses. So you can move the `value` field to the abstract class, and then the `TwoNTile` constructor can call `super(value)` – xp500 Jul 14 '15 at 00:18

3 Answers3

3

First: You can do this:

public boolean mergesWith(Tile moving){
    return this.value == temp.value;
}

to get more elegant solution.

Second: You need to add value variable to Tile class.

public abstract class Tile{
   // ...
   // add a value to Tile
   protected int value; 
   // ...
}

You have extended Tile and added new field. That field is not Tile's field and Tile doesn't contain (doesn't see) it.

Based on the comment below:

When you declare value in Tile, you don't need to declare it in TwoNTile again. You can make Tile objects, just not by using constructors.

Tile t = new TwoNTile(...);

is a valid Tile object. This way, you can implement logic you have already tried to use.

Look at static and dynamic binding in Java on SO, or google it.

Community
  • 1
  • 1
Aleksandar
  • 1,163
  • 22
  • 41
  • but how can I know what the value of `value` is in `Tile` class if I cannot create objects from it? @Aleksandar –  Jul 14 '15 at 00:23
  • Based on your edited comments, @Aleksandar, should I only declare `protected int value` only in `Tile` class, that's it ? –  Jul 14 '15 at 00:35
  • @John Yes. Try it. :) You assign a value to that field in TwoNTile (and other that extends Tile), but declaration is in Tile class. – Aleksandar Jul 14 '15 at 00:35
2

You are trying to access the property from the abstract class that does not have it.

You need to cut it at higher level e.g.

TwoNTile temp = (TwoNTile) moving;

I realize that there might be more than one extensions of this abstract class but you need to cut it to the highest level in class hierarchy such that the casted class or it's decedents can answer this.

Updated method:

public boolean mergesWith(Tile moving){
    TwoNTile temp = (TwoNTile) moving;
    if(this.value == temp.value){
        return true;
    }
    else{
        return false;
    }
}
Enamul Hassan
  • 5,266
  • 23
  • 39
  • 56
Shahzeb
  • 4,745
  • 4
  • 27
  • 40
1

In your Tile class, you need to add the class variable value, like so:

package Game2048;

// Abstract notion of a game tile.
public abstract class Tile{

   //need to add instance variable
   int value; 

  // Returns true if this tile merges with the given tile. 
  public abstract boolean mergesWith(Tile other);

  // Produce a new tile which is the result of merging this tile with
  // the other. May throw an exception if merging is illegal
  public abstract Tile merge(Tile other);

  // Get the score for this tile.
  public abstract int getScore();

  // Return a string representation of the tile
  public abstract String toString();

}
BlackHatSamurai
  • 23,275
  • 22
  • 95
  • 156
  • But why do I have to do that if `TwoNTile` extends `Tile`? Is there any other way also? @BlackHatSamurai –  Jul 14 '15 at 00:15