Board 클래스
getSameFileNum() : 같은 세로줄에 있는 폰의 개수
deletedSamePositionNum : 폰의 개수에서 중복된걸 뺀 값
pawn 에서 deletedSamePositionNum 을 빼고 두배를 하면 같은 세로줄에 있는 폰의 개수
너무 복잡한가..
public double getSameFileNum(double pawnNum, Piece.Color color) {
Piece piece =
color == Piece.Color.WHITE ? Piece.createWhitePawn() : Piece.createBlackPawn();
String[] positions = getPosition(piece);
long deletedSamePositionNum = Arrays.stream(positions)
.map(x -> x.charAt(0))
.distinct()
.count();
return (pawnNum - deletedSamePositionNum) * 2;
}
처음에 이렇게 했다가, positions 배열을 hashSet으로 바꿔주면 중복되는 요소가 사라지니깐 코드가 더 간결해질거같아서 hashSet으로 변경하고 컬렉션의 크기를 비교해주도록 코드 변경
public double getSameFileNum(double pawnNum, Piece.Color color) {
Piece piece =
color == Piece.Color.WHITE ? Piece.createWhitePawn() : Piece.createBlackPawn();
String[] positions = getPosition(piece);
Set<String> deletedSamePositions = new HashSet<>(Arrays.asList(positions));
return (pawnNum - deletedSamePositions.size()) * 2
}
그래도 좀 복잡해보이지만 이게 제일 나은거같다
근데 보는 사람 입장에서는 갑자기 HashSet이 왜나왔지? 라는 생각이 들수도 있을거같다.
내일 다른분들 pr보고 어떻게 구현했는지 봐야겠다
보드에 있는 랭크 스트림으로 만들기
→ 랭크에 있는 기물 리스트들 flatMap으로 합치기
→ 타입 스트림으로 바꾸기
→ 점수 순서대로 정렬하기
Board 클래스가 너무 많은 일을 하는것 같다.
요구사항에서 제안한대로 위치와 관련된 작업을 하는 클래스를 하나 더 생성하면 코드를 다시 수정하는 작업이 힘들거 같아서 일단 Board 에서 처리하도록 했다. 여기까지 구현하는것도 오래걸려서 빨리 pr보내고 싶었다...ㅠㅠ
요구사항에 나와있는대로 createWhite(type)과 createBlack(type)메소드를 생성하고, 각각의 기물들의 팩토리메소드에서 이를 호출하도록 구현
그런데 각각 기물을 생성하는 메소드가 굳이 필요한가? 기물생성시 createWhite()나 createBlack()을 써서 생성하면 안되나 라는 생각이 듦
→ 팩토리메소드의 특징상 메소드명에 기물도 포함되어야할거 같다는 생각도 든다.
아래 블로그 참고
Maven 의존성 설정
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<!-- use 2.6.0 for Java 7 projects -->
<version>3.6.2</version>
<scope>test</scope>
</dependency>
Gradle 의존성 설정
testCompile 'org.assertj:assertj-core:3.6.2'
AssertJ 메소드 임포트
import static org.assertj.core.api.Assertions.*;
메소드 (assertThat()에 연쇄적으로 사용)
자바의 정석 831p에 해당내용 있음
스트림의 스트림을 스트림으로 변환
예시 : Stream<T[]>을 Stream으로 변환
내가 체스프로젝트에 flatMap적용한 코드
public List<Type> sortPiece(Color color) {
return board.stream()
.map(x -> x.getPieceList())
.flatMap(List::stream)
.filter(s -> s.getColor() == color)
.map(x -> x.getType())
.sorted(Comparator.comparing(Type::getDefaultPoint).reversed())
.collect(Collectors.toList());
}
언제 for loop대신 stream API를 사용하면 좋을까 (출처: 이노의 pr 중 리뷰어의 코멘트, 로치가 공유해주심)
다음과 같은 상황에서는 stream API의 사용이 적절합니다.
Iterable
객체에 담긴 요소를 일괄 변환할때for loop
외부에 index
나 count
같은 변수를 두고 하나씩 올려가는 것보다, 리스트를 직접 변환하고 걸러내서 결과값을 도출하는 것이 훨씬 안전하고 깔끔한 코드가 됩니다.
이코테 탐색알고리즘 DFS/BFS 파트
너비 우선 탐색
가장 가까운 노드부터 탐색
동작 방식
BFS 예제
public class BFSExam {
public static boolean[] visited = new boolean[9];
public static ArrayList<ArrayList<Integer>> graph = new ArrayList<>();
// BFS 함수 정의
public static void bfs(int start){
Queue<Integer> q = new LinkedList<>();
q.offer(start);
// 현재 노드 방문처리
visited[start] = true;
// 큐가 빌때까지 반복
while (!q.isEmpty()){
int x = q.poll();
System.out.print(x + " ");
// 해당 원소와 연결되고 아직 방문하지 않은 원소들을 큐에 삽입
for(int i = 0; i < graph.get(x).size(); i++){
int y = graph.get(x).get(i);
if(!visited[y]){
q.offer(y);
visited[y] = true;
}
}
}
}
public static void main(String[] args) {
// 그래프 초기화
for (int i = 0; i < 9; i++) {
graph.add(new ArrayList<Integer>());
}
graph.get(1).add(2);
graph.get(1).add(3);
graph.get(1).add(8);
graph.get(2).add(1);
graph.get(2).add(7);
graph.get(3).add(1);
graph.get(3).add(4);
graph.get(3).add(5);
graph.get(4).add(3);
graph.get(4).add(5);
graph.get(5).add(3);
graph.get(5).add(4);
graph.get(6).add(7);
graph.get(7).add(2);
graph.get(7).add(6);
graph.get(7).add(8);
graph.get(8).add(1);
graph.get(8).add(7);
bfs(1);
}
}
DFS와 BFS 구현방법과 동작원리
DFS : 스택 자료구조로 동작, 재귀함수로 구현
BFS : 큐 자료구조, 큐를 이용해서 구현
코딩테스트에서 탐색 문제가 나오면 그래프형태로 표현하고 풀기
(내일)