Skip to content

Instantly share code, notes, and snippets.

@arahansa
Created July 31, 2020 01:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save arahansa/7834a0a648f8c4ff3dbe2f81cebbd0c3 to your computer and use it in GitHub Desktop.
Save arahansa/7834a0a648f8c4ff3dbe2f81cebbd0c3 to your computer and use it in GitHub Desktop.
코딩도장용 지뢰찾기
import javax.validation.constraints.Max;
import javax.validation.constraints.Min;
import javax.validation.constraints.NotEmpty;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
public class CodingDojangMineSweeper {
static class Block {
private static Block OUTOFGAME = new Block(-1, null);
private final int index;
private int count;
private final Game game;
private boolean mine;
public Block(int number, Game game) {
this.index = number;
this.game = game;
}
public int getIndex() {
return index;
}
public int getWidth() {
return this.game.getWidth();
}
public Block getBlock(int index) {
if (this == Block.OUTOFGAME) return this;
return this.game.getBlock(index);
}
public void plusCount() {
this.count++;
}
public Block layMine() {
if (this == OUTOFGAME) throw new IllegalStateException("OUTOFGAME Block can't set mine.");
this.mine = true;
return this;
}
public boolean isInGameBlock() {
return this != OUTOFGAME;
}
@Override
public String toString() {
return String.valueOf(this.mine ? "*" : this.count);
}
public Set<Block> getAdjacentBlock(MovingStrategy[] strategies) {
if (this == OUTOFGAME) throw new IllegalStateException("OUTOFGAME Block can't getAdjacentBlock.");
Set<Block> l = new HashSet<>();
for (MovingStrategy s : strategies)
l.add(s.apply(this));
return l;
}
}
enum MovingStrategy {
UP(b -> b.getBlock(b.getIndex() - b.getWidth())),
DOWN(b -> b.getBlock(b.getIndex() + b.getWidth())),
LEFT(b -> {
if (!b.isInGameBlock()) return b;
int index = b.getIndex();
if (index % b.getWidth() == 0)
return Block.OUTOFGAME;
return b.getBlock(index - 1);
}),
RIGHT(b -> {
if (!b.isInGameBlock()) return b;
int width = b.getWidth();
int index = b.getIndex();
if (index % width == (width - 1)) {
return Block.OUTOFGAME;
}
return b.getBlock(index + 1);
}),
UPLEFT(UP.strategy.andThen(LEFT.strategy)),
UPRIGHT(UP.strategy.andThen(RIGHT.strategy)),
DOWNLEFT(DOWN.strategy.andThen(LEFT.strategy)),
DOWNRIGHT(DOWN.strategy.andThen(RIGHT.strategy));
private Function<Block, Block> strategy;
MovingStrategy(Function<Block, Block> strategy) {
this.strategy = strategy;
}
public Block apply(Block block) {
return this.strategy.apply(block);
}
static MovingStrategy[] getEasyStrategy() {
return new MovingStrategy[]{UP, DOWN, LEFT, RIGHT};
}
}
static class Game {
private int width;
private int height;
private final List<Block> blocks;
public Game(GameOption gameOption) {
this.width = gameOption.getWidth();
this.height = gameOption.getHeight();
int size = width * height;
// set blocks
this.blocks = new ArrayList<>(size);
for (int i = 0; i < size; i++) {
this.blocks.add(i, new Block(i, this));
}
// mines
Set<Integer> mines = gameOption.getMineNums();
mines.stream()
.map(this::layMine)
.map(block -> block.getAdjacentBlock(MovingStrategy.values()))
.flatMap(Collection::stream)
.filter(Block::isInGameBlock)
.forEach(Block::plusCount);
// .flatMap(block -> Arrays.stream(MovingStrategy.values()).map(s-> s.apply(block)))
}
public String toString() {
String res = "";
for (int i = 0; i < width * height; i++) {
res += getBlock(i).toString();
if (i % getWidth() == (width - 1)) {
res += System.getProperty("line.separator");
}
}
return res;
}
public void print() {
System.out.print(toString());
System.out.println("======================");
}
public int getWidth() {
return this.width;
}
Block getBlock(int index) {
if (index < 0 || index >= width * height) {
return Block.OUTOFGAME;
}
return this.blocks.get(index);
}
private Block layMine(int index) {
return getBlock(index).layMine();
}
}
static class GameOption {
int width;
int height;
Set<Integer> mineNums;
public GameOption(int width, int height, Set<Integer> mine) {
this.width = width;
this.height = height;
this.mineNums = mine;
}
public GameOption(String input) {
String[] split = input.split("\n");
String[] s = split[0].split(" ");
this.width = Integer.parseInt(s[1]);
this.height = Integer.parseInt(s[0]);
this.mineNums = new HashSet<>();
List<String> strings = new ArrayList<>(Arrays.asList(split));
strings.remove(0);
String collected = strings.stream().collect(Collectors.joining());
for (int i = 0; i < collected.length(); i++) {
if (collected.charAt(i) == '*') {
mineNums.add(i);
}
}
}
public int getWidth() {
return width;
}
public int getHeight() {
return height;
}
public Set<Integer> getMineNums() {
return mineNums;
}
}
public static Set<Integer> getRandomNumbers(int max) {
Set<Integer> mine = new HashSet<>();
int randomSize = (int) (max * 0.2);
while (mine.size() < randomSize) {
int i = (int) (Math.random() * (max - 1));
mine.add(i);
}
return mine;
}
public static void main(String[] args) {
String input = """
4 4
*...
....
.*..
....
""";
new Game(new GameOption(input)).print();
input = """
3 5
**...
.....
.*...
""";
new Game(new GameOption(input)).print();
System.out.println("25 칸 짜리");
new Game(new GameOption(5, 5, getRandomNumbers(25))).print();
System.out.println("49 칸 짜리");
new Game(new GameOption(7, 7, getRandomNumbers(49))).print();
System.out.println("100 칸 짜리");
new Game(new GameOption(10, 10, getRandomNumbers(100))).print();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment