2013-08-04 5 views
0

우선, 여기서 디버깅 도움을 요청할 수 있기를 바랍니다. 그 말로, 나는이 간단한 tic tac toe 프로그램을 만들었고 기본적으로 끝났지 만,이 의미 론적 오류로 인해 나를 죽였다. ,Java에서 기본 Tictactoe 프로그램의 의미 오류

는 물론, 난 내 자신의 문제를 알아 내려고 시간을 소비했지만, 그래서 여기에 지금입니다 :) 몇 가지 간단한 개요를

당신은 내가 그 포기했다고 말할 수 있습니다 보드는 char ttt [3] [3] 타입의 배열로 표현된다. 플레이어는 char 형의 변수, 그래서 그들은 문자로 입력되는 'X'또는 'O'와 보드의 좌표 중 하나입니다 :

샘플 실행은 다음과 같이 표시됩니다

******************************** 
    ---a------b------c--- 
    |  |  |  | 
    ---d------e------f--- 
    |  |  |  | 
    ---g------h------i--- 
    |  |  |  | 
    --------------------- 
player1: O, it is your turn. 
Select a cell [a, b, c, ... i] 
a 
******************************** 
    ---a------b------c--- 
    | O |  |  | 
    ---d------e------f--- 
    |  |  |  | 
    ---g------h------i--- 
    |  |  |  | 
    --------------------- 
player2: X, it is your turn. 
Select a cell [a, b, c, ... i] 

array ttt [3] [3]은 모든 원소가 단지 ''가되도록 초기화됩니다.

대부분 프로그램이 제대로 실행됩니다. 너희들을위한 시간을 절약하려고, 나는 다음과 같은 방법

  • 부울 승자 (문자 플레이어)
  • 부울 gameIsDraw()
  • 무효 displayBoard()
  • 완벽하게 실행되고 있는지 확신 문자열 playerID (문자 플레이어)
  • 및 주요 방법 나는 문제를보고 할

은 대부분 내,536에 포함되어getPlayerInput (char player) 메서드 :

void getPlayerInput(char player) 
{  
    int row = 0; 
    int col = 0; 

    System.out.println(playerID(player) + ", it is your turn."); 
    System.out.println("Select a cell [a, b, c, ... i]"); 

    char answer; 
    answer = scan.next().charAt(0); 

    switch(answer) 
    { 
    case 'a': 
     row = 0; 
     col = 0; 
     break;   
    case 'b': 
     row = 0; 
     col = 1; 
     break;   
    case 'c': 
     row = 0; 
     col = 2; 
     break;   
    case 'd': 
     row = 1; 
     col = 0; 
     break;   
    case 'e': 
     row = 1; 
     col = 1; 
     break;   
    case 'f': 
     row = 1; 
     col = 2; 
     break; 
    case 'g': 
     row = 2; 
     col = 0; 
     break; 
    case 'h': 
     row = 2; 
     col = 1; 
     break; 
    case 'i': 
     row = 2; 
     col = 2; 
     break; 

    default: 
     System.out.println("Invalid location, try again."); 
     getPlayerInput(player);    
    } 

    if(ttt[row][col] != ' ') 
    { 
     System.out.println("This square is taken. Try again."); 
     getPlayerInput(player); 
    } 
    else 
    { 
     ttt[row][col] = player; 
    }    
} 

내게는 괜찮은 것처럼 보이지만 출력 결과는 그렇지 않다는 것을 나타냅니다. 이 방법은 두 failsafes,

  1. 를 포함하는 경우, 기판 영역 외부의 사용자 입력의 일 ("A"내지 "I"의 외부 문자)

  2. 또는

    사용자가 문자/위치를 선택하면 이미 다른 'X'또는 'O'에 의해 채택 된 보드에.

두 경우 모두 잘못된 입력이 입력되었다는 것을 인쇄하고 getPlayerInput()을 다시 호출합니다.

디버깅을 통해주의해야 할 것은 유효한 입력 만 입력하면 프로그램이 정상적으로 실행되는 것입니다. 그러나 잘못된 입력 (두 유형 모두)이 입력 된 후 유효한 입력이 입력되면, 때때로이 메소드는 잘못된 입력이 여전히 입력되었음을 인쇄합니다. 예를 들어

, I는 문자 입력

******************************** 
    ---a------b------c--- 
    |  |  |  | 
    ---d------e------f--- 
    |  |  |  | 
    ---g------h------i--- 
    |  |  |  | 
    --------------------- 
player1: O, it is your turn. 
Select a cell [a, b, c, ... i] 
a 
******************************** 
    ---a------b------c--- 
    | O |  |  | 
    ---d------e------f--- 
    |  |  |  | 
    ---g------h------i--- 
    |  |  |  | 
    --------------------- 
player2: X, it is your turn. 
Select a cell [a, b, c, ... i] 
z 
Invalid location, try again. 
player2: X, it is your turn. 
Select a cell [a, b, c, ... i] 
e 
This square is taken. Try again. 
player2: X, it is your turn. 
Select a cell [a, b, c, ... i] 
f 
******************************** 
    ---a------b------c--- 
    | O |  |  | 
    ---d------e------f--- 
    |  | X | X | 
    ---g------h------i--- 
    |  |  |  | 
    --------------------- 
player1: O, it is your turn. 
Select a cell [a, b, c, ... i] 

공지 A-Z-E-F이다. 'z'는 분명히 유효하지 않은 문자이므로 메서드가 의도 한대로 작동하고 (지금까지) 유효하지 않은 입력으로 인쇄 된 다음 메서드가 다시 실행되어 입력을 요청합니다. 분명히 유효한 위치 인 'e'가 입력되었지만, 분명히 그렇지 않은 경우에는 "사각형이 이미 찍혔다"는 방법이 인쇄되었습니다. 그러나 다른 숯불 'f'를 입력하면 나에게 그것을 허용했다.

최종 결과는 플레이어 'X'가 2 회전하고 'e'와 'f'두 칸을 채 웁니다.

사용자가 지속적으로 잘못된 입력을 입력하면 유효한 입력이 입력 될 때까지 해당 방법을 고수해야하지만 이는 잘못된 입력이 잘못된 입력으로 잘못 해석 된 경우와 분명히 다릅니다. 좋은 입력의 다른 인스턴스가 입력되지 않으면 루프를 종료 할 수 없습니다.

그래서 모든 것이 도움이되었습니다.

import java.util.*; 

class TicTacToe 
{ 
    char ttt[][] = new char[3][3]; 
    static final char player1 = 'O'; 
    static final char player2 = 'X'; 
    Scanner scan =new Scanner(System.in); 


    String playerID(char player) 
    {  
     if (player == player1) 
      return "player1: "+player; 
     else 
      return "player2: "+ player; 
    } 

    void getPlayerInput(char player) 
    {  
     int row = 0; 
     int col = 0; 

     System.out.println(playerID(player) + ", it is your turn."); 
     System.out.println("Select a cell [a, b, c, ... i]"); 

     char answer; 
     answer = scan.next().charAt(0); 

     switch(answer) 
     { 
     case 'a': 
      row = 0; 
      col = 0; 
      break;   
     case 'b': 
      row = 0; 
      col = 1; 
      break;   
     case 'c': 
      row = 0; 
      col = 2; 
      break;   
     case 'd': 
      row = 1; 
      col = 0; 
      break;   
     case 'e': 
      row = 1; 
      col = 1; 
      break;   
     case 'f': 
      row = 1; 
      col = 2; 
      break; 
     case 'g': 
      row = 2; 
      col = 0; 
      break; 
     case 'h': 
      row = 2; 
      col = 1; 
      break; 
     case 'i': 
      row = 2; 
      col = 2; 
      break; 

     default: 
      System.out.println("Invalid location, try again."); 
      getPlayerInput(player);    
     } 

     if(ttt[row][col] != ' ') 
     { 
      System.out.println("This square is taken. Try again."); 
      getPlayerInput(player); 
     } 
     else 
     { 
      ttt[row][col] = player; 
     }    
    } 

    boolean gameIsDraw() 
    {  
     boolean isDraw = true; 
     for(int i = 0; i < 3; i++) 
     { 
      for(int j = 0; j < 3; j++) 
      { 
       if(ttt[i][j] == ' ') 
       { 
        isDraw = false; 
       } 
      } 
     } 

     return isDraw; 
    } 

    boolean winner(char player) 
    { 
     boolean hasWon = false; 

     // possible horizontal wins 
     for(int i = 0; i < 3; i++) 
     { 
      if(ttt[i][0] == player && ttt[i][1] == player && ttt[i][2] == player) 
      { 
       hasWon = true; 
      } 
     } 

     // possible vertical wins 
     for(int i = 0; i < 3; i++) 
     { 
      if(ttt[0][i] == player && ttt[1][i] == player && ttt[2][i] == player) 
      { 
       hasWon = true; 
      } 
     } 

     // one diagonal win  
     if(ttt[0][0] == player && ttt[1][1] == player && ttt[2][2] == player) 
     { 
      hasWon = true; 
     } 

     // other diagonal win 
     if(ttt[0][2] == player && ttt[1][1] == player && ttt[2][0] == player) 
     { 
      hasWon = true; 
     } 

     return hasWon; 
    } 


void displayBoard() 
    { 
     System.out.println("********************************");   
     System.out.println("  ---a------b------c---"); 

     for (int i=0; i<3; i++) 
     { 
      for (int j=0; j< 3; j++) 
      { 
       if (j == 0) System.out.print("  | "); 
       System.out.print(ttt[i][j]); 
       if (j < 2) System.out.print(" | "); 
       if (j==2) System.out.print(" |"); 
      } 
      System.out.println(); 
      switch (i) 
      { 
      case 0: 
       System.out.println("  ---d------e------f---"); 
       break; 
      case 1: 
       System.out.println("  ---g------h------i---"); 
       break; 
      case 2: 
       System.out.println("  ---------------------"); 
       break; 
      } 
     } 
    } 


void newgame() 
{ 
    char currPlayer = player1; 
    for(int i=0; i<3; i++) 
     for(int j=0; j<3; j++) 
      ttt[i][j] =' '; 

    boolean continueFlag = true;   
    while (continueFlag) 
    { 
     displayBoard(); 
     if (gameIsDraw()) 
     { 
      System.out.println("Game Ends in Draw"); 
      continueFlag = false; 
     } 
     else 
     { 
      getPlayerInput(currPlayer); 
      if (winner(currPlayer)) 
      { 
       System.out.println("We have a winner: " + playerID(currPlayer)); 
       displayBoard(); 
       continueFlag = false; 
      } 
      else 
      { 
       if (currPlayer == player1) currPlayer = player2; 
        else currPlayer = player1; 
      } 
     } 
    } 

} 


public static void main(String[] args) 
{ 
    TicTacToe game = new TicTacToe(); 
    String str; 
    do 
    { 
     game.newgame(); 

     System.out.println("Do you want to play Tic-Tac-Toe (y/n)?"); 
     str= game.scan.next(); 
    } while ("y".equals(str)); 

    System.out.println("Bye"); 
}  
} 

답변

1

진짜 문제는 getPlayerInput가 호출하는 것입니다 :에 관계없이, 나는 매우 인내심을 가지고있어 사람이 지금까지 ...

당신이 코드를 직접 실행하는 데 좋아 하는가 이것을 읽어 주셔서 감사합니다, 여기에 소스 자체적으로 재귀 적으로. rowcolumn이 실제 값 대신 나쁜 값으로 초기화 된 경우이 문제가 더욱 분명 해졌을 것입니다. int row = -1;. 재귀는 일반적으로 더 작은 동일한 문제로 분할 될 때보다 쉽게 ​​처리 될 수있는 큰 문제에 적합합니다. 이 경우 문제는 단순한 단일 입력을 얻는 것입니다.이 입력은 간단한 작업으로 나눌 수 없습니다.

재귀 대신 입력 유효성 검사에 반복을 사용해야합니다. 예 :

void getPlayerInput(char player) {  
    int row = -1; 
    int col = -1; 

    System.out.println(playerID(player) + ", it is your turn."); 

    while(row==-1) { 
     System.out.println("Select a cell [a, b, c, ... i]"); 

     char answer; 
     answer = scan.next().charAt(0); 

     switch(answer) { 
     case 'a': 
      row = 0; 
      col = 0; 
      break;   
     // <snip> 
     default: 
      System.out.println("Invalid location, try again."); 
     } 
     if(row !- -1 && ttt[row][col] != ' ') { 
      System.out.println("This square is taken. Try again."); 
      row = -1; 
     } 
    } 
    ttt[row][col] = player; 
} 
+0

감사합니다! 당신의 도움 외에도, 나는 그것에 잠을 자고 그것을 알아 냈습니다. 불행히도 당신의 제안은 불행하게도 잘못된 입력이 입력되면 if-statement가 범위를 벗어난 위치를 검사하기 때문에 런타임 오류가 발생하지만 다른 while 루프에서는 쉽게 해결할 수 있습니다. 재귀 대신에 반복을 사용하는 것이 핵심 아이디어였습니다. 재귀가 왜 유효한 전략이 아닌지에 대한 설명을 제공 할 수 있다면 여전히 가능합니까? – HelloMyNameIsRay

+0

더 많은 설명을 추가하고 코드를 수정했습니다. 어쨌든 RuntimeException은 당신이 원하는 것입니다! 뭔가 잘못되어 열심히 실패했습니다. 원래 코드에서 row, column은 처음에는 0,0으로 설정되었으므로 잘못된 입력은 항상 0,0 제곱에서 재생하려고 시도합니다. 그 사각형이 잡히면 재귀 호출은 사용자에게 두 번째 재귀 호출 (다시 스위치의 기본 블록에서 첫 번째 호출이 발생 함)이있는 다른 기회를 사용자에게 제공합니다. 기본적으로 사용자가 입력 시도를 두 배로 늘립니다. –