1. 기획동기
많은 학생들이’학창시절에 무슨 게임을 많이 해봤을까‘ 생각을 해보다가 중고등학
교 쉬는 시간에 친구들과 노트에 판을 그려서 동그라미와 X표로 오목을 하던 때가 생
각나서 처음 기획을 시작하게 되었습니다.
오목이라는 게임은 누구나 한 번쯤은 해봤을 게임이라고 생각해 자바로 구현을 해보
고 싶었습니다.
2. 프로그램 설명
총 5개의 클래스이며 각각의 설명은 다음과 같습니다.
- Player.java : 한 명의 플레이어를 설정하기 위한 클래스
- Board.java : 하나의 게임에 사용되는 하나의 보드판을 나타내는 클래스
- Game.java : 한 판의 게임을 진행하기 위해 사용되는 클래스
- Main.java : 전체적인 프로그램의 틀과 게임 진행을 위한 메인 클래스
- Restart.java : 한 게임이 끝났을 때 게임을 재시작하기 위한 클래스
이미지 파일
- black.png : 검은색 돌 이미지
- white.png : 하얀색 돌 이미지
- board.png : 바둑판
기본적으로 더블 버퍼링 기법을 사용하여 실시간으로 이미지를 처리한다.
이미지 폴더에는 바둑돌 이미지, 바둑판 이미지를 넣었다.
보드판에는 돌을 한 번 둘 때마다 draw()함수를 이용하여 바둑판에 그리게 된다.
3. 실행화면
[실행 첫 화면]
4. 코드
<board>
import java.awt.Graphics;
importjava.awt.Image;
import javax.swing.ImageIcon;
public class Board{
// 보드판 기본 변수 선언
private final int WIDTH = 480, HEIGHT = 510;
private final int BLACK = 1, WHITE = 2;
private int boardXSize = 15, boardYSize = 15;
private int[][] boardMap = new int[boardXSize][boardYSize];
private Player playerOne, playerTwo;
private Player Winner;
private Image boardImage;
private Image blackImage;
private Image whiteImage;
// 보드판 생성자 정의
public Board()
{
boardImage = new
ImageIcon(getClass().getResource("/image/board.png")).getImage();
blackImage = new
ImageIcon(getClass().getResource("/image/black.png")).getImage();
whiteImage = new
ImageIcon(getClass().getResource("/image/white.png")).getImage();
for(int i = 0; i < boardXSize; i++)
6.
{
for(int j =0; j < boardYSize; j++)
{
// 보드판 행렬 초기화
boardMap[i][j] = 0;
}
}
}
// 보드판을 그리는 함수
public void draw(Graphics g) {
g.drawImage(boardImage, 0, 30, null);
for(int i = 1; i <= boardXSize; i++)
g.drawLine(30 * i, 60, 30 * i, 480);
for(int i = 1; i <= boardYSize; i++)
g.drawLine(30, 30 + 30 * i, 450, 30 + 30 * i);
for(int i = 1; i <= boardXSize; i++)
{
for(int j = 1; j <= boardYSize; j++)
{
if(boardMap[i - 1][j - 1] != 0)
{
if(boardMap[i - 1][j - 1] == BLACK)
g.drawImage(blackImage, 30 * i - 15, 15
+ 30 * j, null);
if(boardMap[i - 1][j - 1] == WHITE)
g.drawImage(whiteImage, 30 * i - 15, 15
7.
+ 30 *j, null);
}
}
}
}
// 보드판에 돌을 놓는 함수
public boolean put(int x, int y, Player player)
{
if(boardMap[x][y] != 0)
return false;
boardMap[x][y] = player.getPlayerColor();
return true;
}
// 현재 보드판을 출력
public void show()
{
for(int i = 0; i < boardXSize; i++)
{
for(int j = 0; j < boardYSize; j++)
{
System.out.print(boardMap[i][j] + " ");
}
System.out.print("n");
}
8.
}
// 승리자를 반환
publicPlayer getWinner()
{
return Winner;
}
// 플레이어 승리 판정
public boolean win(int x, int y, Player player)
{
if(win1(x, y)||win2(x, y)||win3(x, y)||win4(x, y)||win5(x, y)||
win6(x, y)||win7(x, y)||win8(x, y)||win9(x, y)||win10(x,
y)||
win11(x, y)||win12(x, y)||win13(x, y)||win14(x,
y)||win15(x, y)||
win16(x, y)||win17(x, y)||win18(x, y)||win19(x,
y)||win20(x, y))
{
Winner = player;
return true;
}
return false;
}
/*------------- 한 번 돌을 놓을 때마다 총 20가지 승리 가능 경우의
수가 존재 -------------*/
9.
public boolean win1(intx, int y)
{
try
{
for(int i = y; i < y + 5; i++)
{
if(boardMap[x][i] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win2(int x, int y)
{
try
{
for(int i = x, j = y; i < x + 5; i++, j--)
{
if(boardMap[i][j] != boardMap[x][y])
return true;
}
public booleanwin8(int x, int y)
{
try
{
for(int i = x, j = y; i > x - 5; i--, j--)
{
if(boardMap[i][j] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win9(int x, int y)
{
try
{
15.
for(int i =y - 1; i < y + 4; i++)
{
if(boardMap[x][i] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win10(int x, int y)
{
try
{
for(int i = x - 1, j = y + 1; i < x + 4; i++, j--)
{
if(boardMap[i][j] != boardMap[x][y])
{
return false;
}
}
16.
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
returntrue;
}
public boolean win11(int x, int y)
{
try
{
for(int i = x - 1; i < x + 4; i++)
{
if(boardMap[i][y] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
17.
public boolean win12(intx, int y)
{
try
{
for(int i = x - 1, j = y - 1; i < x + 4; i++, j++)
{
if(boardMap[i][j] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win13(int x, int y)
{
try
{
for(int i = y + 1; i > y - 4; i--)
{
18.
if(boardMap[x][i] != boardMap[x][y])
{
returnfalse;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win14(int x, int y)
{
try
{
for(int i = x + 1, j = y - 1; i > x - 4; i--, j++)
{
if(boardMap[i][j] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
19.
{
return false;
}
return true;
}
publicboolean win15(int x, int y)
{
try
{
for(int i = x + 1; i > x - 4; i--)
{
if(boardMap[i][y] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win16(int x, int y)
20.
{
try
{
for(int i =x + 1, j = y + 1; i > x - 4; i--, j--)
{
if(boardMap[i][j] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win17(int x, int y)
{
try
{
for(int i = y - 2; i < y + 3; i++)
{
if(boardMap[x][i] != boardMap[x][y])
{
21.
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
returnfalse;
}
return true;
}
public boolean win18(int x, int y)
{
try
{
for(int i = x - 2; i < x + 3; i++)
{
if(boardMap[i][y] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
22.
}
return true;
}
public booleanwin19(int x, int y)
{
try
{
for(int i = y + 2; i > y - 3; i--)
{
if(boardMap[x][i] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
public boolean win20(int x, int y)
{
try
23.
{
for(int i =x + 2; i > x - 3; i--)
{
if(boardMap[i][y] != boardMap[x][y])
{
return false;
}
}
}
catch(ArrayIndexOutOfBoundsException e)
{
return false;
}
return true;
}
}
<Game>
import java.awt.Graphics;
import java.util.Random;
import java.util.Scanner;
public class Game{
Board board = new Board();
private static int BLACK = 1;
24.
private static intWHITE = 2;
public static Player attacker;
Player playerOne = new Player("안병건", "안병건입니다.");
Player playerTwo = new Player("황창윤", "황창윤입니다.");
public boolean ready = true;
public Game()
{
playerSetting(playerOne, playerTwo);
if(playerOne.getPlayerColor() == BLACK)
attacker = playerOne;
else
attacker = playerTwo;
}
public boolean attack(int x, int y)
{
Main.textArea.requestFocus();
if(!board.put(x, y, attacker))
{
Main.textArea.append("놓을 수 없는 자리입니다.n");
Main.textArea.append("둘 위치를 다시 선택하세요n");
return false;
}
if(board.win(x, y, attacker))
25.
{
Main.textArea.append("승리자는 " +
board.getWinner().getPlayerName()+ "입니다.n");
ready = false;
return true;
}
else
{
if(playerOne == attacker)
attacker = playerTwo;
else
attacker = playerOne;
Main.textArea.append(attacker.getPlayerName() + " 플레이어가
둘 차례입니다.n");
}
return false;
}
public void draw(Graphics g)
{
board.draw(g);
}
// 플레이어 순서 결정
public static void playerSetting(Player playerOne, Player playerTwo)
{
public class Mainextends JFrame{
private final int BLACK = 1, WHITE = 2;
private int boardXSize = 15, boardYSize = 15;
private final int WIDTH = 480, HEIGHT = 510;
private static Game game = new Game();
public static Main main;
Image dbImage;
Graphics dbG;
public static JTextArea textArea = new JTextArea(10, 20);
public static JScrollPane scrollPane = new JScrollPane(textArea,
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
public Main() {
setSize(WIDTH + 500, HEIGHT);
setResizable(false);
setVisible(true);
setTitle("오목 게임");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
addMouseListener(new MouseHandler());
setLocationRelativeTo(null);
setLayout(null);
28.
scrollPane.setBounds(WIDTH + 20,25, 455, 430);
add(scrollPane);
scrollPane.setVisible(true);
}
public void paint(Graphics g) {
super.paint(g);
dbImage = createImage(WIDTH, HEIGHT);
dbG = dbImage.getGraphics();
draw(dbG);
g.drawImage(dbImage, 0, 0, null);
}
public void draw(Graphics g) {
game.draw(g);
}
public static void main(String[] args) {
main = new Main();
textArea.append(game.attacker.getPlayerName() + " 플레이어가 둘
차례입니다.n");
}
public static void restart() {
game = new Game();
textArea.append("게임이 재시작되었습니다.n");
main.repaint();
29.
}
public class MouseHandlerextends MouseAdapter {
@Override
public void mousePressed(MouseEvent e) {
repaint();
int mx = e.getX();
int my = e.getY();
if(game.ready)
{
for(int i = 0; i < boardXSize; i++)
{
for(int j = 0; j < boardYSize; j++)
{
if(mx > 30 * i + 15 && mx < 30 * i + 45
&& my > 30 * j + 45 && my < 30 * j + 75)
{
if(game.attack(i, j))
{
textArea.append("3초 후에
게임이 재시작됩니다.n");
Restart restart = new
Restart();
Thread restartThread = new
Thread(restart);
30.
restartThread.start();
}
}
}
}
}
}
}
}
<Player>
public class Player{
// 플레이어 기본 변수 선언
private String playerName;
private String playerInfo;
private int playerColor;
// 플레이어 생성자 정의
public Player(String playerName, String playerInfo) {
this.playerName = playerName;
this.playerInfo = playerInfo;
}
// 플레이어의 돌 색깔을 반환
int getPlayerColor()
31.
{
return playerColor;
}
// 플레이어의돌 색깔을 설정
void setPlayerColor(int playerColor)
{
this.playerColor = playerColor;
}
// 플레이어 이름을 반환
public String getPlayerName() {
return playerName;
}
// 플레이어 이름을 설정
public void setPlayerName(String playerName) {
this.playerName = playerName;
}
// 플레이어 정보를 반환
public String getPlayerInfo() {
return playerInfo;
}
// 플레이어 정보를 설정
32.
public void setPlayerInfo(StringplayerInfo) {
this.playerInfo = playerInfo;
}
}
<Restart>
public class Restart implements Runnable{
@Override
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Main.restart();
}