[백준7682_자바스크립트(javascript)] - 틱택토

경이·2025년 2월 20일

𝑩𝑶𝑱 (𝒋𝒔)

목록 보기
282/325

🔴 문제

틱택토


🟡 Sol

const fs = require('fs');
const path = process.platform === 'linux' ? '/dev/stdin' : 'input.txt';
const inputs = fs.readFileSync(path).toString().trim().split('\n');

const getBingo = (map) => {
  const ansPiece = [];

  if (new Set([map[0], map[1], map[2]]).size === 1) ansPiece.push(map[0]);
  if (new Set([map[3], map[4], map[5]]).size === 1) ansPiece.push(map[3]);
  if (new Set([map[6], map[7], map[8]]).size === 1) ansPiece.push(map[6]);

  if (new Set([map[0], map[3], map[6]]).size === 1) ansPiece.push(map[0]);
  if (new Set([map[1], map[4], map[7]]).size === 1) ansPiece.push(map[1]);
  if (new Set([map[2], map[5], map[8]]).size === 1) ansPiece.push(map[2]);

  if (new Set([map[0], map[4], map[8]]).size === 1) ansPiece.push(map[0]);
  if (new Set([map[2], map[4], map[6]]).size === 1) ansPiece.push(map[2]);

  return ansPiece.filter((it) => it !== '.');
};


for (const input of inputs) {
  if (input === 'end') break;
  let xCnt = 0;
  let oCnt = 0;
  let dotCnt = 0;

  for (const piece of input) {
    if (piece === 'O') oCnt += 1;
    else if (piece === 'X') xCnt += 1;
    else dotCnt += 1;
  }

  const ansPiece = getBingo(input);

  if (dotCnt === 0) {
    if (xCnt !== 5 || oCnt !== 4) console.log('invalid');
    else if (new Set(ansPiece).size === 2) console.log('invalid');
    else if (ansPiece === 0) console.log('valid');
    else if (ansPiece.length === 2) console.log('valid');
    else {
      if (ansPiece[0] === 'O') console.log('invalid');
      else console.log('valid');
    }
  } //
  else {
    if (ansPiece.length === 2) console.log('invalid');
    else if (ansPiece.length === 1) {
      if (ansPiece[0] === 'O' && xCnt === oCnt) console.log('valid');
      else if (ansPiece[0] === 'X' && xCnt - oCnt === 1) console.log('valid');
      else console.log('invalid');
    } else console.log('invalid');
  }
}

또 다른 풀이

const fs = require('fs');
const path = process.platform === 'linux' ? '/dev/stdin' : 'input.txt';
const inputs = fs.readFileSync(path).toString().trim().split('\n');

const bingoLines = [
  [
    [0, 0],
    [0, 1],
    [0, 2],
  ],
  [
    [1, 0],
    [1, 1],
    [1, 2],
  ],
  [
    [2, 0],
    [2, 1],
    [2, 2],
  ],
  [
    [0, 0],
    [1, 0],
    [2, 0],
  ],
  [
    [0, 1],
    [1, 1],
    [2, 1],
  ],
  [
    [0, 2],
    [1, 2],
    [2, 2],
  ],
  [
    [0, 0],
    [1, 1],
    [2, 2],
  ],
[
    [0, 2],
    [1, 1],
    [2, 0],
  ],
];

const getBingoCnt = (map, target) => {
  let cnt = 0;

  for (const bingoLine of bingoLines) {
    let isBingo = true;

    for (const [x, y] of bingoLine) {
      if (map[x][y] !== target) isBingo = false;
    }

    if (isBingo) cnt += 1;
  }

  return cnt;
};

for (const input of inputs) {
  if (input === 'end') continue;

  const oCnt = input.split('O').length - 1;
  const xCnt = input.split('X').length - 1;
  const map = [input.slice(0, 3).split(''), input.slice(3, 6).split(''), input.slice(6, 9).split('')];

  const xBingoCnt = getBingoCnt(map, 'X');
  const oBingoCnt = getBingoCnt(map, 'O');

  // 게임이 종료된 상태 : 반드시 x가 1줄이거나 0줄 달성, o는 0줄 달성
  if (oCnt === 4 && xCnt === 5 && oBingoCnt === 0) console.log('valid');
  // x가 이김 -> 반드시 x가 한줄로 이겨야 함
  else if (xCnt - oCnt === 1 && oBingoCnt === 0 && xBingoCnt === 1) console.log('valid');
  // console.log('반드시 o가 한줄로 이겨야 하고 x는 이길 수 없는 상태여야 함');
  else if (oCnt === xCnt && xBingoCnt === 0 && oBingoCnt === 1) console.log('valid');
  else console.log('invalid');
}

🟢 풀이

⏰ 소요한 시간 : -

풀어볼법한 시뮬레이션 문제라서 두번 풀이했다.

첫 번째 풀이는 빙고를 세는 과정이 깔끔하고
두번째 풀이는 정답을 내는 과정이 깔끔해서… 둘다 가져왔음

중요한점만 뽑아보자면

이 문제는 1. 빙고의 개수를 세고, 2. 빙고의 개수에 따라 valid 한지, invalid 한지를 출력하면 된다.

  1. 빙고의 개수 세기

    3x3 빙고기 때문에 모든 빙고의 경우의 수를 좌표로 기억할 수 있다. 따라서 아래와 같이 빙고가 될 수 있는 8가지 경우를 하드코딩해서 확인해줄 수 있다.

    지금은 O, X 둘을 구분짓지 않고 리턴하지만 객체형태로 다루는 것이 다음 로직을 설계하는데에 편리하다.

    const getBingo = (map) => {
      const ansPiece = [];
      // const ansPiece = { oCnt : 0, xCnt : 0}
    
      if (new Set([map[0], map[1], map[2]]).size === 1) ansPiece.push(map[0]);
      if (new Set([map[3], map[4], map[5]]).size === 1) ansPiece.push(map[3]);
      if (new Set([map[6], map[7], map[8]]).size === 1) ansPiece.push(map[6]);
    
      if (new Set([map[0], map[3], map[6]]).size === 1) ansPiece.push(map[0]);
      if (new Set([map[1], map[4], map[7]]).size === 1) ansPiece.push(map[1]);
      if (new Set([map[2], map[5], map[8]]).size === 1) ansPiece.push(map[2]);
    
      if (new Set([map[0], map[4], map[8]]).size === 1) ansPiece.push(map[0]);
      if (new Set([map[2], map[4], map[6]]).size === 1) ansPiece.push(map[2]);
    
      return ansPiece.filter((it) => it !== '.');
    };
  2. 빙고의 개수에 따라 valid, invalid 판별하기

    틱택토 게임의 valid 조건은 다음과 같다.

    • 승부가 나지 않고 게임이 종료됨 : X가 5개, O가 4개이며, 반드시 X와 O 모두 0줄을 달성해야 함
    • X가 이김 : O가 X보다 하나가 적으며, 반드시 X가 한줄로 이겨야 하고 O는 이길 수 없는 상태여야 함
    • O가 이김 : O와 X의 개수가 같으며, 반드시 O가 한줄로 이겨야 하고, X는 이길 수 없는 상태여야 함

해당 벨리데이션만 잘 지켜주면된다.


🔵 Ref

profile
록타르오가르

0개의 댓글