简体   繁体   中英

Scan and replace specific character with random position in text file in Java

I am trying to build a mini game and having problem with generating random stars in the map/maze. I have a method that will replace existing "**" to "0" , and I want it to replace any 5 random "0" with "*" again so that every time I run the program those stars will be generated randomly, but I can't figure out the algorithm. For example:

before
1111111111
1000*00001
1000000*01
10*0000*01
10000*0001
1111111111

after
1111111111
100*00*001
1*00000001
100000*001
100*000001
1111111111

Methods that im using currently,

 public static void main(String[] args) {
    cheeseReset("maze.txt", "*", "0");     
}

static void cheeseReset(String filePath, String oldString, String newString)
{
    File fileToBeModified = new File(filePath);
    String oldContent = "";
    BufferedReader reader = null;
    FileWriter writer = null;

    try
    {
        reader = new BufferedReader(new FileReader(fileToBeModified));
        String line = reader.readLine();
        while (line != null) 
        {
            oldContent = oldContent + line + System.lineSeparator();
            line = reader.readLine();
        }

        String newContent = oldContent.replace(oldString, newString); 
        //replace 5 random  "0" with "*"
        writer = new FileWriter(fileToBeModified);
        writer.write(newContent);      
    }

    catch (IOException e)
    {
        e.printStackTrace();
    }
    finally
    {
        try
        {
            reader.close();
            writer.close();
        } 
        catch (IOException e) 
        {
            e.printStackTrace();
        }
    }
}

You can use Math.random() or an instance of Random to generate random numbers, but you cannot control its output to cause exactly 5 of your map points to be stars with equal probability.

However, you can chose exactly 5 with equal probability if you randomly re-order the points then use the first 5 after re-ordering.

In pseudo code:

  • represent each point on your map with a single object (that has two points)
  • create a List and populate it with all points that can be a star
  • randomly reorder the list by calling Collections.shuffle(list)
  • place a star at the first 5 points of the list

As you seem to know how to deal with files, I just show a way for the placement only, inspired by @Bohemian's answer, but a bit different:

public class RandoMaze {
    public static final String ORGMAZE=
              "11111111111111111  Stay\n"
            + "1*****@@@@0000001   'n'\n"
            + "1000000000000000111 Die\n"
            + "1000000000000000001\n"
            + "11111111111100000011111\n"
            + "           111000000001\n"
            + "Monsters     1110000001\n"
            + "everywhere     11111111\n";
    public static final Set<Character> SHUFFLEPIECES=new HashSet<>(Arrays.asList('0','@','*'));
    public static void main(String[] args) {
        System.out.println("Before:");
        System.out.println(ORGMAZE);
        char maze[]=ORGMAZE.toCharArray();
        List<Character> shuffleme=new ArrayList<>();
        for(int i=0;i<maze.length;i++)
            if(SHUFFLEPIECES.contains(maze[i]))
                shuffleme.add(maze[i]);
        Collections.shuffle(shuffleme);
        for(int i=0;i<maze.length;i++)
            if(SHUFFLEPIECES.contains(maze[i]))
                maze[i]=shuffleme.remove(0);
        System.out.println("After:");
        System.out.println(new String(maze));
    }
}

The idea is to have a representation of the playfield, built from a combination of items which are supposed to stay put (walls, 'decoration'), and items which are supposed to be randomized ('empty' fields, and objects).
Then a loop extract the to-be-randomized objects only, shuffles them, and another loop puts them back (again working on the to-be-randomized fields only, leaving everything else intact).

Note: that Set thing is particularly horrible, in real-life code it would be better to pick a continuous range of numbers/characters for representing 'movable' items, and check with a pair of <= and >= .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM