I like the Answer by Aleksa and the Answer by Pshemo.
Here are three variations on their themes. No big breakthroughs here, but perhaps interesting.
record
Java 16 offers the new records feature. A record is a brief way to write a class whose main purpose is to communicate data, transparently and immutably. The compiler implicitly creates the constructor, getters, equals
& hashCode
, and toString
.
We can use a record to mate the pairs of inputs, the emoji character being used as an icon along with the number of occurrences we want to see of that character. This makes our intent more clear and explicit than using two separate arrays as inputs.
Note that a record can be defined locally, within a method. (So too with interfaces and enums, as of Java 16, by the way.)
record EmojiCount ( String emoji , int count ) {}
Define your inputs as a unmodifiable list.
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
Use a stream to get a count of all the emoji characters to be generated.
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count ).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
Collections.nCopies
Generate all the emoji characters we need, repetitively. We can make a List
for each kind of emoji, using Collections.nCopies
to fill each list. We join those lists into a master list. Then shake them up randomly by calling Collections.shuffle
.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
We take those generated emojis and distribute them across the rows and columns of our village grid, our two-dimensional array. All we need is pair of for
loops nested, to access each row, then each column. As we go, we increment an index number to move through our list of emojis to be placed in the grid.
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
For each row in two-dimensional array
Lastly, dump to console. Note the compact for
loop to dump a two-dimensional array, using this for-each syntax: for ( String[] row : village )
.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
Full code example
Pull all that code together.
package work.basil.demo.village;
import java.util.*;
public class App
{
public static void main ( String[] args )
{
// Define the emoji characters we use as icons.
record EmojiCount( String emoji , int count ) {} // New record feature in Java 16. Compact way to write an immutable data-carrier class.
final List < EmojiCount > emojiCounts =
List.of(
new EmojiCount( "" , 2 ) ,
new EmojiCount( "" , 3 ) ,
new EmojiCount( "" , 4 )
);
final int countEmoji = emojiCounts.stream().mapToInt( emojiCount -> emojiCount.count ).sum();
// Define the village.
final int width = 3, height = 3;
if ( countEmoji > ( width * height ) ) throw new IllegalStateException( "The village is not large enough to contain all your desired emoji icons. Message # 1348468a-1102-4ad4-bc39-426fbe9c86a3." );
final String[][] village = new String[ width ][ height ];
// Populate the village.
// Generate all the emoji icons.
List < String > emojis = new ArrayList <>( countEmoji );
for ( EmojiCount emojiCount : emojiCounts )
{
emojis.addAll( Collections.nCopies( emojiCount.count , emojiCount.emoji ) );
}
Collections.shuffle( emojis );
// Lay out the terrain.
int index = 0;
for ( int x = 0 ; x < width ; x++ )
{
for ( int y = 0 ; y < height ; y++ )
{
village[ x ][ y ] = emojis.get( index );
index++;
}
}
// Dump to console.
System.out.println( "emojis = " + emojis );
String output = Arrays.toString( village );
for ( String[] row : village ) System.out.println( Arrays.toString( row ) );
}
}
When run.
emojis = [, , , , , , , , ]
[, , ]
[, , ]
[, , ]