2012-10-13 2 views
3

야 트지 (Yatzy) 봇을 개발할 때 '보류'기능이 작동하지 않습니다. 다른 모든 것은 작동하지만이 기능의 논리가 실패하는 것처럼 보입니다. 기본적으로 아이디어는 주어진 모든 숫자를 유지 한 다음 주어진 숫자와 일치하지 않는 주사위를 굴리는 것입니다.야 트리 (Yatzy) 로봇에서 홀드 기능 관련 문제

[00:04] @Dessimat0r: .roll 
[00:04] YatzyBot: #1: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ] 
[00:04] @Dessimat0r: .hold 2 1 
[00:04] YatzyBot: #2: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ] 
[00:04] @Dessimat0r: .hold 2 1 
[00:04] YatzyBot: #3: dice: [2, 5, 3, 4, 1], scores: [ 1 2 3 4 5 6 1P 2P 3K 4K SS LS H Y C ] 

에서 볼 수있는 바와 같이 은, 모든 숫자가 (이 주사위 롤에서 우연이 아니다) 대신 선택된 소수의 개최되고있다. 코드는 다음과 같습니다 :

} else if (event.getMessage().startsWith(".hold")) { 
    if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) { 
     String[] tokens = event.getMessage().split(" "); 
     if (tokens[0].equals(".hold")) { 
      boolean failed = false; 
      try { 
       if (tokens.length == 1) { 
        bot.sendMessage(CHANNEL, "Must choose some dice to hold!"); 
        return; 
       } 
       ArrayList<Integer> dice = new ArrayList<Integer>(); 
       ArrayList<Integer> holdnums = new ArrayList<Integer>(); 
       ArrayList<Integer> rollnums = new ArrayList<Integer>(); 

       for (Die d : y.getDice()) { 
        dice.add(d.getFaceValue()); 
       } 

       // parse other numbers 
       for (int i = 1; i < tokens.length; i++) { 
        int num = Integer.parseInt(tokens[i]); 
        holdnums.add(num); 
       } 
       ListIterator<Integer> diter = dice.listIterator(); 
       dice: while (diter.hasNext()) { 
        Integer d = diter.next(); 

        if (holdnums.isEmpty()) { 
         rollnums.add(d); 
         diter.remove(); 
         continue; 
        } 
        ListIterator<Integer> iter = holdnums.listIterator(); 
        while (iter.hasNext()) { 
         int holdnum = iter.next().intValue(); 
         if (holdnum == d) { 
          iter.remove(); 
          diter.remove(); 
          continue dice; 
         } 
        } 

       } 

       if (!holdnums.isEmpty()) { 
        bot.sendMessage(CHANNEL, "Hold nums not found: " + holdnums); 
        failed = true; 
       } 

       if (!failed) { 
        y.getTurn().rollNumbers(convertIntegers(rollnums)); 

        Map<Scoring, Integer> scores = y.getRollScores(); 

        Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class); 
        Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class); 

        for (Entry<Scoring, Integer> entry : scores.entrySet()) { 
         if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) { 
          unchosen.put(entry.getKey(), entry.getValue()); 
         } else { 
          chosen.put(entry.getKey(), entry.getValue()); 
         } 
        } 
        bot.sendMessage(CHANNEL, "#" + y.getTurn().getRolls() + ": dice: " + y.getDiceStr() + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores)); 
       } 
      } catch (TurnException e1) { 
       bot.sendMessage(CHANNEL, e1.getMessage()); 
      } catch (RollException e2) { 
       bot.sendMessage(CHANNEL, e2.getMessage()); 
      } catch (YahtzyException e3) { 
       bot.sendMessage(CHANNEL, e3.getMessage()); 
      } catch (NumberFormatException e4) { 
       bot.sendMessage(CHANNEL, e4.getMessage()); 
      } 
     } 
    } 
} 

편집 : 모든 수정되었습니다. 업데이트 된 코드 :

} else if (event.getMessage().startsWith(".hold")) { 
    if (y.getTurn() != null && event.getUser().getNick().equals(y.getTurn().getPlayer().getName())) { 
     String[] tokens = event.getMessage().split(" "); 
     if (tokens[0].equals(".hold")) { 
      boolean failed = false; 
      try { 
       if (tokens.length == 1) { 
        bot.sendMessage(channel, "Must choose some dice to hold!"); 
        return; 
       } 
       ArrayList<Integer> holdnums = new ArrayList<Integer>(); 
       ArrayList<Integer> rollnums = new ArrayList<Integer>(); 

       // parse other numbers 
       for (int i = 1; i < tokens.length; i++) { 
        int num = Integer.parseInt(tokens[i]); 
        holdnums.add(num); 
       } 
       for (int i = 0; i < y.getDice().length; i++) { 
        int d = y.getDice()[i].getFaceValue(); 

        if (holdnums.isEmpty()) { 
         rollnums.add(d); 
         continue; 
        } 

        ListIterator<Integer> iter = holdnums.listIterator(); 

        boolean found = false; 
        while (iter.hasNext()) { 
         int holdnum = iter.next().intValue(); 
         if (holdnum == d) { 
          iter.remove(); 
          found = true; 
          break; 
         } 
        } 
        if (!found) { 
         rollnums.add(d); 
        } 
       } 

       if (!holdnums.isEmpty()) { 
        bot.sendMessage(channel, "Hold nums not found: " + holdnums); 
        failed = true; 
       } 

       if (!failed) { 
        boolean[] rolled = y.getTurn().rollNumbers(convertIntegers(rollnums)); 

        Map<Scoring, Integer> scores = y.getRollScores(); 

        Map<Scoring, Integer> unchosen = new EnumMap<Scoring, Integer>(Scoring.class); 
        Map<Scoring, Integer> chosen = new EnumMap<Scoring, Integer>(Scoring.class); 

        for (Entry<Scoring, Integer> entry : scores.entrySet()) { 
         if (y.getTurn().getPlayer().getTotals().get(entry.getKey()) == -1) { 
          unchosen.put(entry.getKey(), entry.getValue()); 
         } else { 
          chosen.put(entry.getKey(), entry.getValue()); 
         } 
        } 
        bot.sendMessage(channel, "#" + y.getTurn().getRolls() + ": dice: " + diceToString(rolled) + ", scores: " + getDiceStr(y.getTurn().getPlayer().getTotals(), scores)); 
       } 
      } catch (TurnException e1) { 
       bot.sendMessage(channel, e1.getMessage()); 
      } catch (RollException e2) { 
       bot.sendMessage(channel, e2.getMessage()); 
      } catch (YahtzyException e3) { 
       bot.sendMessage(channel, e3.getMessage()); 
      } catch (NumberFormatException e4) { 
       bot.sendMessage(channel, e4.getMessage()); 
      } 
     } 
    } 
} 

답변

2

모든 것이 OK 보이지만, holdnum이 검사가 올바른 위치에 있지 :

if (absent) { 
     bot.sendMessage(CHANNEL, "Hold num not found: " + holdnum); 
     failed = true; 
     break dice; 
    } 

그래서 주어진 대기 번호가 오른쪽 또는 잘못되면 여기에 말을 너무 일찍입니다 이 코드를 제거하는 것이 좋습니다. holdnums의 유효성을 확인하려면 "주사위"루프가 끝난 후이 목록을 볼 수 있습니다. holdnums이 비어 있지 않으면 발견되지 않은 일부 항목이 포함되어 있습니다. 업데이트 된 질문에 대한


: rollnums.add(d)가 같은 값을 여러 번 추가 피하기 위해 중첩 된 while에서 호출 할 수 없습니다 :

내가 한 가지 문제를 참조하십시오. 대신이 루프가 완료된 후 한 번 호출해야합니다.

+0

감사합니다. 그것은 정확하게 문제는 아니지만 어쨌든 도움이되었습니다. 주사위가 다시 반복되고 있으므로 처리 된 후 제거 할 수 있도록 다른 목록에 넣었습니다. 이것은 트릭을하는 것처럼 보였다. 수정 사항을 반영하도록 위 코드를 업데이트하겠습니다. 최적화 제안이 있다면 환영 할 것입니다. :) –

+0

아직도 문제가 있습니다. 새 코드를 확인해 주시겠습니까? :) –

+1

@ChrisDennett : 답변을 업데이트했습니다. 최적화에 관해서는, 내가 아는 한 Yatzy에는 5 개의 주사위 만 있기 때문에 코드의이 부분을 최적화하는 것이 효과가 없습니다. 당신은'dice'와'holdnums'리스트를 모두 정렬 할 수 있고, 작은 값으로 반복자를 앞 당김으로써 하나의 루프에서 둘 다 반복 할 수 있습니다. –