요즘 취업 준비로 한창 바쁘긴 하지만! 잠깐 시간이 나서 3인용 오목을 만들기로 하였다.
온라인 강의로 자바를 학습하긴 했어도 GUI에 익숙하지 않은 비전공자들은 구현이 조금 힘들지 않을까 싶다.
사실 나도 학교 다니면서 Swing을 이용한 과제를 해봤다만 딱 한번뿐이라 다른 블로그를 참조하여 완성했다.
자바 오목게임 만들기
이번에는 오목게임을 만들어보도록 하겠다. 룰은 한번씩 돌아가며 돌을 놓고 먼저 5개를 놓는 사람이 이기는 게임이다. GUI는 JFrame과 JPane으로 그렸다. 지정된 판에 선을 그리고 마우스프레스드를 통해 마우가..
message0412.tistory.com
오목의 룰은 그대로 유지하되, 3인용 오목까지 구현하는 것이 목표이다!
GUI는 지식이 많이 없고 학습이 필요한 상황이라 다음과 같은 순서로 개발하였다.
1. 오목돌 클래스, 게임 진행 클래스 구현
2. GUI 개발 이전 이클립스 Console로 오목게임 테스트 및 구현
3. GUI 개발 후 적용
4. 완성
다음은 word (오목돌) 클래스이다.
package 오목;
public class Word {
private int y;
private int x;
private int color;
public Word(int y,int x,int color) {
this.y=y;
this.x=x;
this.color=color;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getColor() {
return color;
}
public void setColor(int color) {
this.color = color;
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
}
y, x 변수를 int 형으로 설정하였고 색 구별을 위해 int color 변수를 추가하였다.
------------------------------------------------------------------------------------------------
-GameMethod class-
package 오목;
import java.util.Scanner;
public class GameMethod {
private int MaxSize = 20;
private int Map[][] = new int[MaxSize][MaxSize];
private int GamePlay_cnt = 2; // 게임플레이어 숫자
private int cun_GamePlayer = 1; // 게임플레이어 현재 순서
public void init() {
for (int i = 0; i < MaxSize; i++) {
for (int j = 0; j < MaxSize; j++) {
Map[i][j] = 0;
}
}
}
public void nextPlayer(int cun_p) {
cun_p++;
if (GamePlay_cnt < cun_p) {
cun_GamePlayer = 1;
} else {
cun_GamePlayer = cun_p;
}
}
public boolean endGame(Word w) {
int nowColor = w.getColor();
int dir[][] = { { 1, 0 }, { -1, 0 }, { 0, 1 }, { 0, -1 }, { -1, 1 }, { 1, -1 }, { -1, -1 }, { 1, 1 } };
for (int i = 0; i < 8; i = i + 2) {
int same_cnt = 1;
int cunY = w.getY();
int cunX = w.getX();
for (int j = 0; j < 5; j++) {
cunY = cunY + dir[i][0];
cunX = cunX + dir[i][1];
if (cunY < 0 || cunY >= MaxSize || cunX < 0 || cunX >= MaxSize)
break;
if (nowColor != Map[cunY][cunX])
break;
same_cnt++;
}
cunY = w.getY();
cunX = w.getX();
for (int j = 0; j < 5; j++) {
cunY = cunY + dir[i + 1][0];
cunX = cunX + dir[i + 1][1];
if (cunY < 0 || cunY >= MaxSize || cunX < 0 || cunX >= MaxSize)
break;
if (nowColor != Map[cunY][cunX])
break;
same_cnt++;
}
if (same_cnt >= 5) {
return true;
}
}
return false;
}
public void inputWord(Word w) {
Map[w.getY()][w.getX()] = w.getColor();
}
public boolean checkInput(int y, int x) {
if (Map[y][x] != 0 || y < 0 || y >= MaxSize || x < 0 || x >= MaxSize) {
return false;
}
return true;
}
public void setGameMode(int max) {
this.GamePlay_cnt = max;
}
public int[][] getMap() {
return Map;
}
public int getCun_GamePlayer() {
return cun_GamePlayer;
}
}
GameMethod 클래스는 게임 전반의 세팅과 오목 달성 조건을 검사해준다.
마우스 이벤트를 통해 y, x 값을 받으면 Map [][] 변수에 현재 플레이어의 돌(1,2,3)을 입력해주는 방식이다.
----------------------------------------------------------------------------------------------------
-RunGame class-
package 오목;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
public class RunGame extends JFrame {
private Container c;
MapSize size = new MapSize();
GameMethod gm = new GameMethod();
public RunGame(String title) {
setTitle(title);
createMenu();
setBounds(200, 20, 650, 750);
c = getContentPane();
c.setLayout(null);
ShowMap m = new ShowMap(size, gm);
setContentPane(m);
MouseAction Mc = new MouseAction(gm, size, m, this);
addMouseListener(Mc);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
class MenuActionListener implements ActionListener {
public void actionPerformed(ActionEvent e) {
String cmd = e.getActionCommand();
switch (cmd) { // 메뉴 아이템의 종류 구분
case "2인":
gm.setGameMode(2);
gm.init();
break;
case "3인":
gm.setGameMode(3);
gm.init();
break;
}
}
}
public void createMenu() {
JMenuBar mb = new JMenuBar(); // 메뉴바 생성
JMenuItem[] menuItem = new JMenuItem[2];
String[] itemTitle = { "2인", "3인" };
JMenu screenMenu = new JMenu("게임모드선택");
MenuActionListener listener = new MenuActionListener();
for (int i = 0; i < menuItem.length; i++) {
menuItem[i] = new JMenuItem(itemTitle[i]);
menuItem[i].addActionListener(listener);
screenMenu.add(menuItem[i]);
}
mb.add(screenMenu);
setJMenuBar(mb);
}
}
Swing의 메뉴바를 이용하여 3인 , 2인 모드를 선택할 수 있게 하였다.
----------------------------------------------------------------------------------------------------
-MouseAction class-
package 오목;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import javax.swing.JOptionPane;
public class MouseAction extends MouseAdapter{
private GameMethod gm;
private MapSize m;
private ShowMap sm;
private RunGame g;
public MouseAction(GameMethod gm,MapSize m, ShowMap mm,RunGame g) {
this.gm=gm;
this.m=m;
this.sm=mm;
this.g=g;
}
@Override
public void mousePressed(MouseEvent me) {
int x = (int)Math.round(me.getX()/(double) m.getCell())-1;
int y = (int)Math.round(me.getY()/(double) m.getCell())-2;
if(gm.checkInput(y, x) == false) {
return;
}
Word w = new Word(y,x,gm.getCun_GamePlayer());
gm.inputWord(w);
gm.nextPlayer(gm.getCun_GamePlayer());
sm.repaint();
if(gm.endGame(w)==true) {
String ms;
if(w.getColor()==1) {
ms="검돌승리!";
}
else if(w.getColor()==2) {
ms="백돌승리!";
}
else {
ms="적돌승리!";
}
showWin(ms);
gm.init();
}
}
public void showWin(String msg) {
JOptionPane.showMessageDialog(g, msg, "",JOptionPane.INFORMATION_MESSAGE);
}
}
----------------------------------------------------------------------------------------------------
-ShowMap class-
package 오목;
import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
public class ShowMap extends JPanel{
private MapSize size;
private GameMethod gm;
private final int STONE_SIZE=28; //돌 사이즈
public ShowMap(MapSize m,GameMethod gm) {
setBackground(new Color(206,167,61));
size=m;
setLayout(null);
this.gm =gm;
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(Color.BLACK);
board(g);
drawStone(g);
}
public void board(Graphics g) {
for(int i=1;i<=size.getSize();i++){
g.drawLine(size.getCell(), i*size.getCell(), size.getCell()*size.getSize(), i*size.getCell());
g.drawLine(i*size.getCell(), size.getCell(), i*size.getCell() , size.getCell()*size.getSize());
}
}
public void drawStone(Graphics g) {
for(int y=0;y<size.getSize();y++){
for(int x=0;x<size.getSize();x++){
if(gm.getMap()[y][x]==1)
drawBlack(g,x,y);
else if(gm.getMap()[y][x]==2)
drawWhite(g, x, y);
else if(gm.getMap()[y][x]==3)
drawRed(g, x, y);
}
}
}
public void drawRed(Graphics g,int x,int y){
g.setColor(Color.RED);
g.fillOval(x*size.getCell()+15, y*size.getCell()-15, STONE_SIZE, STONE_SIZE);
}
public void drawBlack(Graphics g,int x,int y){
g.setColor(Color.BLACK);
g.fillOval(x*size.getCell()+15, y*size.getCell()-15, STONE_SIZE, STONE_SIZE);
}
public void drawWhite(Graphics g,int x,int y){
g.setColor(Color.WHITE);
g.fillOval(x*size.getCell()+15, y*size.getCell()-15, STONE_SIZE, STONE_SIZE);
}
}
Swing 부분은 타 블로그를 많이 참고하였다. 간단히 설명하자면 마우스를 클릭하면 좌표값을
GameMethod에 전달하는 방식이다.
----------------------------------------------------------------------------------------------------
-Main class-
package 오목;
public class Run {
public static void main(String[] args) {
new RunGame("헤헿 뭐하누 핳하");
}
}
+
-Mapsize class-
package 오목;
public class MapSize {
private final int CELL =30;
private final int SIZE =20;
public int getCell() {
return CELL;
}
public int getSize() {
return SIZE;
}
}

오목게임을 구현한 다른 글들은 자세히 살펴보진 않았지만, 개인적으로 GUI를 생각하기보다는 오목의 승리 조건을
조금 더 쉽게 만들기 위해 고민했던 시간이 많았던거 같다.
댓글