https://shinyunha.tistory.com/20
[마피아] Join Sequence
Tag: "Join:" 1. 사용자는 Test 파일을 실행시켜서 Lobby를 생성한다. 2. 생성된 Lobby는 자신의 ClientManager를 생성한다. 3. 모든 사용자가 자신의 Lobby를 생성하고 서버 연결이 완료되면 화면에 각자 닉네
shinyunha.tistory.com
https://shinyunha.tistory.com/21
[마피아] Start Sequence
Tag: "Start:" 1. 사용자가 "시작하기" 버튼 클릭2. Lobby가 "Start:" 메시지를 ClientManager에게 전달//시작하기 버튼 누르면startButton.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent e) {
shinyunha.tistory.com
https://shinyunha.tistory.com/23
[마피아] Role
직업 배정 문제를 해결했다.2주쯤 걸렸다. 정말 별 걸 다 시도해봤다.결국 처음으로 돌아와서 Join,Start와 같은 방식으로 직업 배정 결과를 View에 적용하기로 했다. 원래는 사회자가 lobby.getView().set
shinyunha.tistory.com
https://shinyunha.tistory.com/24
[마피아] Message
채팅 기능은 걱정과 달리 수월하게 구현되었다. 아마 Server/Client가 이미 구조를 잘 짜뒀기 때문일 것이다. 1. View에서 message를 입력받아 Client로 보낸다. inputField.addActionListener(new ActionListener() { @Over
shinyunha.tistory.com
https://shinyunha.tistory.com/25
[마피아] 밤
사회자가 게임을 시작하면 가장 먼저 실행되는 state가 '밤'이다 public void start() { init_game(); while(true) { this.set_state(new 밤()); this.gameState.execute(매니저); checkEnd(); this.set_state(new 토론()); this.gameState.exec
shinyunha.tistory.com
https://shinyunha.tistory.com/26
[마피아] 투표
투표는 밤과 유사하게 진행된다. Tag도 똑같이 "Target:"을 사용한다. 1. 투표 제한시간은 30초이다@Overridepublic void execute(사회자 매니저) { // TODO Auto-generated method stub 매니저.getCommandManager().broadcastAll("
shinyunha.tistory.com
게임 결과 계산 - 밤과 투표 state가 끝날 때마다 호출한다
public void checkEnd() {
int 생존마피아 = 0;
int 생존시민 = 0;
for(Player p : players) {
if(p.is_alive == false) continue; //죽은 사람 넘어가기
if("mafia".equals(p.getRole())) 생존마피아++;
else 생존시민++;
}
if(생존마피아==0) {
commandManager.broadcastAll("System:"+"마피아가 모두 검거됐습니다. 시민 승리!");
System.exit(0);
}
if(생존마피아>=생존시민) {
commandManager.broadcastAll("System:"+"마피아와 시민의 수가 같아졌습니다. 마피아 승리!");
System.exit(0);
}
}
사회자
Mafia Chat - ClientManager가 직업을 감지하여 띄운다. logic은 AllChat과 같은데 밤에만 채팅이 가능하다
// 직업이 마피아면 마피아 채팅창 따로 또 띄우기
if ("mafia".equals(role)) { // 문자열 비교 주의 ("mafia"인지 "MAFIA"인지 서버랑 맞추세요)
if (mafiaChatView == null) {
mafiaChatView = new MafiaChatView(this);
mafiaChatView.setVisible(true);
}
}
ClientManager
ActionListener sendAction = new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String msg = mafiaInputField.getText();
// 빈 값 전송 방지
if(msg.trim().isEmpty()) return;
// 서버로 "Mafia_message:내용" 보냄
clientManager.sendMessage("Mafia_message:" + msg);
// 입력창 비우기
mafiaInputField.setText("");
mafiaInputField.requestFocus();
}
};
mafiaInputField.addActionListener(sendAction);
MafiaChatView
public class MafiaChatCommand implements ICommand {
private CommandManager networkBrain;
private 사회자 logicBrain;
public MafiaChatCommand(CommandManager cm, 사회자 logic) {
this.networkBrain = cm;
this.logicBrain = logic;
}
@Override
public void execute(ServerThread sender, String payload, IState currentState) {
// TODO Auto-generated method stub
// 밤 상태에만 채팅 가능
if (currentState instanceof 밤) {
if (sender.getPlayer().getRole().equals("mafia")) {
networkBrain.broadcastToMafia(sender.getPlayer().nickname + ": " + payload);
}
}
}
}
MafiaChatCommand
서버 IP 사용자가 입력하기
//ip 입력받기
ipField.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
JTextField ipField = (JTextField) e.getSource();
String ip = ipField.getText();
clientManager.setIp(ip);
ipField.setText("");
ipField.setEnabled(false);
}
});
Lobby
public void setIp(String ip) {
// 서버 연결
try {
clientThread = new ClientThread(ip, 50023, this);
clientThread.start();
} catch (IOException e) {
System.err.println("서버 연결 실패: " + e.getMessage());
}
}
ClientManager
발전 가능성
- 로그인 기능 / 레벨업, 퀘스트 추가
- 고유번호 입력으로 능력사용/투표를 하는 것이 아니라 버튼을 이용하여 구현
- 사망자 채팅 기능 및 사망자의 마피아 채팅 관전
- 더 다양한 직업 추가 (ex. 기자, 군인 등)
- 투표 이후 최후의 변론 시간을 추가해 투표 결과에 대한 찬성/반대 최종 결정
- 웹으로 구현하여 배포
- 마피아 채팅 기록 및 시간 db 저장
- 구조 개선(dto와 common 패키지로 모델 객체를 분리)
GitHub 링크
실행방법
1. 한 명이 ServerManager을 먼저 실행한다.
2. 사용자들은 Test 파일을 실행하고 IP를 입력한 후 엔터를 친다.
3. 모든 사용자들이 서버와 연결된 후 각자 닉네임을 입력하고 엔터를 친다.
4. 아무나 시작하기 버튼을 클릭하여 system 메세지에 따라 게임을 진행한다.
프로젝트 소감
일단 완성했다는 사실이 믿기지가 않는다. 심지어 게임을 해봤는데 꽤 재밌어서 더 믿을 수가 없다. 첫 프로젝트가 잘 끝나서 너무 뿌듯하다.
배운 점이 정말 많은데, 가장 많이 느낀 건 구조의 중요성이다. 한 번 잘 잡아둔 구조 하나가 뒤에 이어지는 모든 일을 쉽게 만든다는 것을 실제로 느꼈다. 실제로 TargetID 문제를 해결하고 하루만에 프로그램이 완성되었다. 비슷한 로직으로 동작하니, 나머지 기능을 구현하는 것이 정말 쉬웠다.
그리고 정말 다양한 오류를 겪었다. 사소하게 오타나 변수 이름 불일치부터, 객체 생성이나, Socket 통신, Multi Thread와 관련된 오류까지 직접 겪고 해결하는 과정에서 어떤 부분을 주의하여 코드를 작성해야하는지, 문제가 발생했을 때는 어딜 확인해봐야하는지 배울 수 있었다. 정말 많은 디버그용 출력문을 찍었다. 오류를 해결하는 과정에서 모든 팀원이 전체 코드를 보고 또 보고 로직을 따라가면서 우리 프로젝트가 어떻게 작동하는지 깊이 이해하게 되었다.
이제 Git 써 본 사람이 되었다. 프로젝트 초반에는 Git 왜 쓰는 건데!!! 그냥 구글 공유 문서 쓰자 하며 울부짖었지만, 프로젝트 마무리할 때 즈음에는 Git에 올려뒀으니 내 코드 마음대로 바꿔보지 뭐 하는 마음도 들었다. Git 오류도 엄청 다양하게 경험해서 대략 해결하는 방법도 이제는 알고있다.
그리고 팀프로젝트의 덕을 정말 많이 봤다. 난 프로젝트 완전 처음이었는데, 오류 다 해결해준 남규 언니, Git 문제 다 해결해준 현경이, 기깔나게 영상 만들어준 은서가 있어서 완성할 수 있었다.
다음에는 Spring boot 사용해서 프로젝트를 해보고 싶다. 얼마나 쉬워지는지 궁금하다.
'JAVA' 카테고리의 다른 글
| [마피아] 투표 (0) | 2025.12.02 |
|---|---|
| [마피아] 밤 (0) | 2025.12.02 |
| [마피아] Message (0) | 2025.12.02 |
| [마피아] Role (0) | 2025.12.01 |
| [JAVA] Spring Boot - 2 (0) | 2025.11.25 |