(c)도경구 1.0 (2022/10/14) 실습 완성코드
(2022/11/22) 숙제 완성코드
public class PuzzlePiece {
private int face;
public int face() {
return face;
}
public PuzzlePiece(int n) {
face = n;
}
}
public class SlidePuzzleBoard {
private PuzzlePiece[][] board;
private int empty_row;
private int empty_col;
public PuzzlePiece[][] board() { return board; }
public SlidePuzzleBoard() {
board = new PuzzlePiece[4][4];
int number = 15;
for (int i = 0; i < 4; i++)
for (int j = 0; j < 4; j++) {
board[i][j] = new PuzzlePiece(number);
number -= 1;
}
board[3][3] = null;
empty_row = 3;
empty_col = 3;
}
public boolean move(int n) {
int row, col;
if (found(n,empty_row-1, empty_col)) {
row = empty_row-1;
col = empty_col;
}
else if (found(n,empty_row+1, empty_col)) {
row = empty_row+1;
col = empty_col;
}
else if (found(n,empty_row, empty_col-1)) {
row = empty_row;
col = empty_col-1;
}
else if (found(n,empty_row, empty_col+1)) {
row = empty_row;
col = empty_col+1;
}
else
return false;
board[empty_row][empty_col] = board[row][col];
board[row][col] = null;
empty_row = row;
empty_col = col;
return true;
}
private boolean found(int n, int r, int c) {
if (r >= 0 && r <= 3 && c >= 0 && c <= 3)
return board[r][c].face() == n;
else
return false;
}
}
import java.awt.*;
import javax.swing.*;
public class PuzzleWriter extends JPanel {
private SlidePuzzleBoard puzzle;
private final int SIZE; // the size of a puzzle piece in pixel
public PuzzleWriter(SlidePuzzleBoard p) {
puzzle = p;
SIZE = 30;
JFrame f = new JFrame();
f.getContentPane().add(this);
f.setLocation(550,100);
f.setTitle("Slide Puzzle");
f.setSize(SIZE*6, SIZE*6+28);
f.setVisible(true);
f.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
}
public void paintComponent(Graphics g) {
g.setColor(Color.YELLOW);
g.fillRect(0, 0, SIZE*6, SIZE*6);
PuzzlePiece[][] r = puzzle.board();
for (int i = 0; i < 4; i = i + 1) {
for (int j = 0; j < 4; j = j + 1) {
paintPiece(g, r[i][j], i, j);
}
}
}
private void paintPiece(Graphics g, PuzzlePiece p, int i, int j) {
int x = SIZE + (SIZE * j);
int y = SIZE + (SIZE * i);
if (p != null) {
g.setColor(Color.WHITE);
g.fillRect(x, y, SIZE, SIZE);
g.setColor(Color.BLACK);
g.drawRect(x, y, SIZE, SIZE);
int face_value = p.face();
if (face_value < 10)
g.drawString(face_value + "", x+11, y+20);
else
g.drawString(face_value + "", x+7, y+20);
}
else {
g.setColor(Color.BLACK);
g.fillRect(x, y, SIZE, SIZE);
}
}
public void displayPuzzleBoard() {
this.repaint();
}
public void showNoMove(String s) {
JOptionPane.showMessageDialog(null, "Error: " + s );
}
}
import javax.swing.*;
public class PuzzleController {
private SlidePuzzleBoard puzzle;
private PuzzleWriter writer;
public PuzzleController(SlidePuzzleBoard p, PuzzleWriter w) {
puzzle = p;
writer = w;
}
public void play() {
while (true) {
writer.displayPuzzleBoard();
String input = JOptionPane.showInputDialog("Your move:");
int n = Integer.parseInt(input);
if (! puzzle.move(n))
writer.showNoMove("Cannot move.");
}
}
}
public class PuzzleStarter {
public static void main(String[] args) {
SlidePuzzleBoard puzzle = new SlidePuzzleBoard();
PuzzleWriter writer = new PuzzleWriter(puzzle);
new PuzzleController(puzzle,writer).play();
}
}
import java.util.*;
public class Sudoku {
private int[][] solution = new int[9][9];
private int hole_count;
private int[][] puzzle_board = new int[9][9];
/** 객체 초기화 메소드
*
* @param count - 빈칸의 개수
*/
public Sudoku(int count) {
createSolutionBoard();
hole_count = count;
createPuzzleBoard(count);
}
/** 퍼즐 보드 배열을 리턴 한다.
*
* @return 퍼즐 보드 배열
*/
public int[][] getPuzzleBoard() {
return puzzle_board;
}
/** 빈칸의 개수를 리턴 한다.
*
* @return 빈칸의 개수
*/
public int countHoles() {
return hole_count;
}
/** 해답 보드를 만든다. */
private void createSolutionBoard() {
int[] random_sequence = generateRandomPermutation(9);
for (int i = 0; i < 9; i++)
random_sequence[i] += 1;
for (int i = 0; i < 3; i++)
for (int j = 0; j < 9; j++)
solution[i][j] = random_sequence[(j+3*i+i/3)%9];
for (int k = 0; k < 2; k++)
for (int i = 0; i < 3; i++)
for (int j = 0; j < 9; j++)
if (j % 3 != 2)
solution[i+3*(k+1)][j] = solution[i+3*k][j+1];
else
solution[i+3*(k+1)][j] = solution[i+3*k][j-2];
shuffleRibbons();
transpose();
shuffleRibbons();
transpose();
showBoard(solution);
}
/** 0~n-1 범위의 정수 수열을 무작위로 섞은 배열을 리턴 한다.
*
* @param n - 수열의 길이
* @return 0~n-1 범위의 정수를 무작위로 섞어 만든 배열
*/
private int[] generateRandomPermutation(int n) {
Random random = new Random();
int[] permutation = new int[n];
for (int i = 0; i < n; i++) {
int d = random.nextInt(i+1);
permutation[i] = permutation[d];
permutation[d] = i;
}
return permutation;
}
/** 스도쿠 퍼즐 보드를 망가트리지 않는 한도 내에서 solution 배열의 가로줄을 무작위로 섞는다. */
private void shuffleRibbons() {
int[][] shuffled = new int[9][9];
int[] random_index;
for (int i = 0; i < 3; i++) {
random_index = generateRandomPermutation(3);
for (int j = 0; j < 3; j++)
shuffled[i*3+random_index[j]] = solution[i*3+j];
}
solution = shuffled;
}
/** solution 배열의 행과 열을 바꾼다. */
private void transpose() {
int[][] transposed = new int[9][9];
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
transposed[i][j] = solution[j][i];
solution = transposed;
}
/** 2차원 배열 b를 콘솔 윈도우에 보여준다.
*
* @param b - 2차원 배열
*/
private void showBoard(int[][] b) {
System.out.println("스도쿠 보드");
for (int i = 0; i < 9; i++) {
for (int j = 0; j < 9; j++)
System.out.print(b[i][j] + " ");
System.out.println();
}
}
/** solution 배열을 puzzle_board 배열에 카피한 뒤, count 개수만큼 무작위로 빈칸(0)으로 만든다.
*
* @param count - 비울 빈칸의 개수
*/
private void createPuzzleBoard(int count) {
// copy solution board to puzzle board
for (int i = 0; i < 9; i++)
for (int j = 0; j < 9; j++)
puzzle_board[i][j] = solution[i][j];
// make holes randomly
Random random = new Random();
int count_down = count;
while (count_down > 0) {
int i = random.nextInt(9);
int j = random.nextInt(9);
if (puzzle_board[i][j] != 0) {
puzzle_board[i][j] = 0;
count_down -= 1;
}
}
}
/** row번 가로줄, col번 세로줄에 digit을 채울 수 있는지 검사하여,
* 가능하면 채우고 true를 리턴하고, 불가능하면 false를 리턴 한다.
*
* @param digit - 빈칸에 채울 수 (1~9 중 하나)
* @param row - 가로줄 번호
* @param col - 세로줄 번호
* @return 퍼즐 보드 조건에 만족하여 빈칸을 채웠으면 true, 만족하지 않으면 false
*/
public boolean check(int digit, int row, int col) {
if (puzzle_board[row][col] == 0 && solution[row][col] == digit) {
puzzle_board[row][col] = digit;
hole_count -= 1;
return true;
}
else
return false;
}
}
public class SudokuController {
private Sudoku sudoku;
private PlayerInput reader;
private SudokuWriter writer;
/** Sudoku, PlayerInput, SudokuWriter 객체를 생성하여 필드 변수에 지정한다. */
public SudokuController() {
reader = new PlayerInput();
int hole_count = reader.selectLevel();
sudoku = new Sudoku(hole_count);
writer = new SudokuWriter(sudoku);
}
/** 스도쿠 퍼즐 게임을 진행한다. */
public void playSudokuPuzzle() {
int i, j, d;
while (sudoku.countHoles() > 0) {
i = reader.selectNumber("가로줄 번호를 넣어주세요.") - 1;
j = reader.selectNumber("세로줄 번호를 넣어주세요.") - 1;
d = reader.selectNumber("숫자를 넣어주세요.");
if (sudoku.check(d,i,j))
writer.repaint();
}
}
}