본문 바로가기
Projects/Socket Omok

[Socket Omok] 9. 게임 승리 조건 만들기

by DevJaewoo 2022. 6. 13.
반응형

게임 승리 조건 만들기

게임 승리 조건도 별거 없다. 그냥 알고리즘만 짜면 되기 때문에 별로 어렵지 않다.

우선 코드부터 보자.

function checkOmokCompleted(coord, takes) {
  //(0, 1), (1, 1), (1, 0), (1, -1)
  const offset = [
    { x: 1, y: 0 }, //가로
    { x: 1, y: 1 }, //대각선1
    { x: 0, y: 1 }, //세로
    { x: -1, y: 1 }, //대각선2
  ];

  return offset.some((dir) => {
    let streak = 1;
    const type = (takes.length - 1) % 2;

    //정방향
    for (
      let x = coord.x + dir.x, y = coord.y + dir.y;
      x > 0 && x < 19 && y > 0 && y < 19;
      x += dir.x, y += dir.y
    ) {
      if (takes.some((t, index) => t.x == x && t.y == y && index % 2 == type))
        streak++;
      else break;
    }

    //반대방향
    for (
      let x = coord.x - dir.x, y = coord.y - dir.y;
      x > 0 && x < 19 && y > 0 && y < 19;
      x -= dir.x, y -= dir.y
    ) {
      if (takes.some((t, index) => t.x == x && t.y == y && index % 2 == type))
        streak++;
      else break;
    }

    if (streak === 5) {
      return true;
    }
  });
}

wsServer.on("connection", (socket) => {
  ...
  
  socket.on("player_selected", (coord) => {
    ...

    if (checkOmokCompleted(coord, room.takes)) {
      console.log("Omok completed!");
      wsServer.in(name).emit("game_end", isBlackTurn ? "black" : "white");
      wsServer.in(name).emit("message", `${socket.id}님이 승리하셨습니다!`);
      room.blackPlayer = "";
      room.whitePlayer = "";
      emitPlayerChange(room);
      return;
    }
    
    ...
  });
});

 

주석을 보면 알 수 있겠지만 오목은 고려해야 할 방향이 가로, 세로, 양쪽 대각선 총 4개이다.

그 방향에 대한 X, Y 좌표 변동을 미리 배열로 만들어놓고, 현재 착수 위치를 기준으로 해당 방향으로 이동하며 같은 색의 돌을 더하고, 반대 방향으로 이동하며 같은 색의 돌을 더한다.

 

만약 다 더한 값이 정확히 5가 되면, 오목이 완성되었다는 뜻이고, 만약 아니라면 5개가 되지 않았거나 육목 이상이 되었다는 뜻이다.

 

오목이 완성되면 true를 반환할거고, 그럼 서버에서 해당 방의 플레이어들에게 "game_end" 메시지를 전송한다.

게임이 종료되고 팀을 바꿔서 플레이하고 싶을수도 있기 때문에 검은돌, 흰돌 플레이어를 초기화했다.

 

클라이언트에선 "game_end" 메시지가 수신되면 승리한 플레이어를 GameEndScreen에 표시하도록 했다.

const GamingRoom = ({ publicRoom }) => {
  const [roomName, setRoomName] = React.useState(publicRoom.name);
  const [blackPlayer, setBlackPlayer] = React.useState(publicRoom.blackPlayer);
  const [whitePlayer, setWhitePlayer] = React.useState(publicRoom.whitePlayer);
  const [takes, setTakes] = React.useState(publicRoom.takes);

  const [winner, setWinner] = React.useState("");

  console.log(publicRoom);
  document.title = `공개방: ${roomName}`;

  const onGameEnd = () => {
    setWinner("");
  };

  const GameEndScreen = ({ winner }) => {
    const text = `${winner === "black" ? "흑돌" : "백돌"} 승리!`;
    return (
      <div className="endscreen">
        <div className="endscreen__main">
          <h3 className="endscreen__text">{text}</h3>
          <button className="endscreen__button" onClick={onGameEnd}>
            확인
          </button>
        </div>
      </div>
    );
  };

  React.useEffect(() => {
    ...
    socket.on("game_end", (winner) => {
      setWinner(winner);
    });
  }, []);

  return (
    <div className="gaming-room">
      ...
      {winner !== "" ? <GameEndScreen winner={winner} /> : null}
    </div>
  );
};

 

승리 버튼은 지금은 화면 아래쪽에 뜬다.

승리조건 결과
잘 된다.

 

반응형