ページ 11

C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 01:27
by 課題絶望
課題でオセロゲームをつくるんですが、とりあえず人対人をつくってみようと思い、以下のプログラムを書いたのですがどうしてもreverce(オセロの駒を反転させる)の関数のところでセグメントエラーが起きてしまいます。gdbと言う物を使ってどこがおかしいか調べてみたのですがどうやらreverceの引数であるcol,row(ボードの縦と横)の値が全く違う値になってしまいます。どこを直せばよいかわからないので教えてください。長かったので原因と思われる所の周辺を乗せたのですが全部見なければわからない場合はすべて載せます。

コード:

typedef struct board_node{
   int board[SIZE][SIZE];
}node;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
int main(void){
   node *board_list;
   int move_col[8] = {-1,-1,0,1,1,1,0,-1};
   int move_row[8] = {0,1,1,1,0,-1,-1,-1};
   board_list = set_board();
   print_board(board_list);
   board_list = white_turn(board_list,move_col,move_row);
   print_board(board_list); 
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node *white_turn(node *board_list,int move_col[],int move_row[]){
  int row,col,move;
  fprintf(stdout,"white turn");
  do{
     fprintf(stdout,"please put position column:");
     scanf("%d",&col);
     printf("\n");
     fprintf(stdout,"please put position row:");
     scanf("%d",&row);

     if(board_list->board[col-1][row-1]==NO && check_put(board_list,WHITE,col,row,move_col,move_row)==1){
             for(move=0; move < 8 ;move++){
              printf("%d",move);
              board_list = reverce(board_list,col,row,WHITE,move
                                                 ,move_col,move_row);
              }
              board_list->board[col-1][row-1]=WHITE;
              break;
     } if(board_list->board[col-1][row-1]==WHITE ||
              board_list->board[col-1][row-1]==BLACK){
                 fprintf(stdout,"This position already put\n");
     }else{
        fprintf(stdout,"error");
        printf("\n");
     }
    
  }while(1);
  return(board_list);
}


~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
node *reverce(node *board_list,int col,int row,int turn,int move
                                    ,int move_col[],int move_row[]){
    while(1){

      col += move_col[move];
      row += move_row[move];
      if(turn==BLACK){
          if(board_list->board[col-1][row-1] == BLACK){
                 break;
          }else if(board_list->board[col-1][row-1] == WHITE){
                 board_list->board[col-1][row-1] = BLACK;
          }
      }else if(turn==WHITE){
          if(board_list->board[col-1][row-1] == WHITE){
                 break;
          }else if(board_list->board[col-1][row-1] == BLACK){
                 board_list->board[col-1][row-1] = WHITE;
          }
      }
    }
    return(board_list);
}

Re: C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 08:21
by みけCAT
例えば〇●☆□□□□□という配置(☆と□は空きマス)があったとき、
☆の位置に〇を置こうとすると、右に見ていくときに無限ループになり、配列の確保された領域の範囲外へのアクセスが発生しそうです。
見ている位置が空マスでないか、および盤面の外に行っていないかの判定が必要だと思います。

Re: C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 13:45
by 課題絶望
質問投稿したものです。意見いただいた部分は伏せていたプログラムでした。

コード:

int checkrev(node *board_list,int move,int row,int col
                    ,int turn,int move_col[],int move_row[]){
    int flag = 0;
    while(1){
        col += move_col[move];
        row += move_row[move];

        if( row-1 < 0 || col-1 < 0 || row > SIZE-1 || col > SIZE-1){
           return(EXIT_SUCCESS);
        }

        if(board_list->board[col-1][row-1] == NO){
           return(EXIT_SUCCESS);
        }

        if(turn==BLACK){
           if(board_list->board[col-1][row-1] == WHITE){
              flag = 1;
              continue;
           }
        }else if(turn==WHITE){
           if(board_list->board[col-1][row-1] == BLACK){
              flag = 1;
              continue;
           }
        }
        if(flag == 1){ break;}
        return (EXIT_SUCCESS);
    }
    return (EXIT_FAILURE);
}


Re: C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 15:55
by みけCAT
課題絶望 さんが書きました:意見いただいた部分は伏せていたプログラムでした。
提示されたコード中にcheckrev関数を呼び出している場所は見当たらないですね。
課題絶望 さんが書きました:

コード:

if( row-1 < 0 || col-1 < 0 || row > SIZE-1 || col > SIZE-1){
右端や下端にコマがあっても無視するコードのような気がしますが、これで正しいのでしょうか?

Re: C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 23:02
by 課題絶望
課題だったのであまりすべて載せたくなくて回りくどいことになってしまいすいません。
checkrevはwhiteturnで呼び出しています。
右端はrow>SIZE-1で盤面の端より出ないようにしているつもりなのですが実際に裏返るか確認しかしていなかったのでそこまでのエラーは確認していません。
reverceのrowとcolの値がとんでしまうのをどうにかすれば動くと考えてました。

コード:

#include <stdlib.h>
#include <stdio.h>
#include <omp.h>
#define SIZE (4)
#define WHITE (1)
#define BLACK (-1)
#define NO (0)
#define MAX (13)
#define NUM_THREADS (4)


typedef struct board_node{
   int board[SIZE][SIZE];
}node;

node *set_board(void);
int print_board(node *board_list);
node *white_turn(node *board_list,int move_col[],int move_row[]);
int checkrev(node *board_list,int move,int row,int col
                    ,int turn,int move_col[],int move_row[]);
int check_put(node *board_list,int turn,int col,int row
                              ,int move_col[],int move_row[]);
node *reverce(node *board_list,int col,int row,int turn,int move
                                    ,int move_col[],int move_row[]);

int main(void){
   node *board_list;
   int move_col[8] = {-1,-1,0,1,1,1,0,-1};
   int move_row[8] = {0,1,1,1,0,-1,-1,-1};
   board_list = set_board();
   print_board(board_list);
   board_list = white_turn(board_list,move_col,move_row);
   print_board(board_list); 
}

int print_board(node *board_list){
    node *tmp;
    tmp = board_list;
    int i,j;
    for(i = 0;i < SIZE;i++ ){fprintf(stdout," %d",i+1);}
    printf("\n");
    for( i = 0; i < SIZE; i++){
        fprintf(stdout,"%d",i+1);
        for( j = 0; j< SIZE; j++){
            switch(board_list->board[i][j]){
             case NO:
                printf("「「");
                break;
             case BLACK:
                printf("。・);
                break;
             case WHITE:
                printf("。・);
                break;
             default:
                printf("E");
                return(EXIT_FAILURE);
            }
        }
        printf("\n");
    }
    return(EXIT_SUCCESS);
}

node *set_board(void){
    node *board_list;
    int i,j;
    if((board_list=(node *)malloc(sizeof(node)))==NULL){
       fprintf(stderr,"malloc\n");
       exit(1);
    }
    for(i = 0; i < SIZE ; ++i){
       for(j = 0; j < SIZE ; ++j){
          board_list->board[i][j] = NO;
       }
    }
    board_list->board[SIZE/2][SIZE/2] = BLACK;
    board_list->board[SIZE/2-1][SIZE/2-1] = BLACK;
    board_list->board[SIZE/2][SIZE/2-1] = WHITE;
    board_list->board[SIZE/2-1][SIZE/2] = WHITE;
    return (board_list);
}

node *white_turn(node *board_list,int move_col[],int move_row[]){
  int row,col,move;
 // node *tmp;
  fprintf(stdout,"white turn");
  do{
     fprintf(stdout,"please put position column:");
     scanf("%d",&col);
     printf("\n");
     fprintf(stdout,"please put position row:");
     scanf("%d",&row);

     if(board_list->board[col-1][row-1]==NO && check_put(board_list,WHITE,col,row,move_col,move_row)==1){
             for(move=0; move < 8 ;move++){
              printf("%d",move);
              board_list = reverce(board_list,col,row,WHITE,move
                                                 ,move_col,move_row);
              }
              board_list->board[col-1][row-1]=WHITE;
              break;
     } if(board_list->board[col-1][row-1]==WHITE ||
              board_list->board[col-1][row-1]==BLACK){
                 fprintf(stdout,"This position already put\n");
     }else{
        fprintf(stdout,"error");
        printf("\n");
     }
    
  }while(1);
//  board_list = tmp;

  return(board_list);
}

int checkrev(node *board_list,int move,int row,int col
                    ,int turn,int move_col[],int move_row[]){
    int flag = 0;
    while(1){
        col += move_col[move];
        row += move_row[move];

        if( row-1 < 0 || col-1 < 0 || row > SIZE-1 || col > SIZE-1){
           return(EXIT_SUCCESS);
        }

        if(board_list->board[col-1][row-1] == NO){
           return(EXIT_SUCCESS);
        }

        if(turn==BLACK){
           if(board_list->board[col-1][row-1] == WHITE){
              flag = 1;
              continue;
           }
        }else if(turn==WHITE){
           if(board_list->board[col-1][row-1] == BLACK){
              flag = 1;
              continue;
           }
        }
        if(flag == 1){ break;}
        return (EXIT_SUCCESS);
    }
    return (EXIT_FAILURE);
}

int check_put(node *board_list,int turn,int col,int row
                              ,int move_col[],int move_row[]){
    int move,i;
    for(move = 0; move < 8 ;move++){
         i=checkrev(board_list,move,row,col,turn,move_col,move_row);
         if(i==1){
               printf("return1");
               return (EXIT_FAILURE);
         }
    }
    return (EXIT_SUCCESS);
}

node *reverce(node *board_list,int col,int row,int turn,int move
                                    ,int move_col[],int move_row[]){
    while(1){

      col += move_col[move];
      row += move_row[move];
      if(turn==BLACK){
          if(board_list->board[col-1][row-1] == BLACK){
                 break;
          }else if(board_list->board[col-1][row-1] == WHITE){
                 board_list->board[col-1][row-1] = BLACK;
          }
      }else if(turn==WHITE){
          if(board_list->board[col-1][row-1] == WHITE){
                 break;
          }else if(board_list->board[col-1][row-1] == BLACK){
                 board_list->board[col-1][row-1] = WHITE;
          }
      }
    }
    return(board_list);
}



Re: C言語の課題でわからないエラー

Posted: 2015年2月07日(土) 23:19
by box
課題絶望 さんが書きました: reverceのrowとcolの値がとんでしまうのをどうにかすれば動くと考えてました。
reverseのことですか?
課題絶望 さんが書きました:

コード:

#define SIZE (4)
#define MAX (13)
#define NUM_THREADS (4)
これらの意味を日本語で説明してみてください。

コメントが全くないので、コードを追いかける気があまりしないです。
課題ということは、だれかに読んでもらうのでしょうから、
適切にコメントを入れておくことが必要ではないでしょうか。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 01:51
by 課題絶望
その通りです。実際の課題は多分木をつかって盤面データをいれてAIとやるものなのでこれは自分でどう作るか考えるために作ったものでしたのでいれてなかったです。
SIZEはオセロ盤面の大きさで今回つくるオセロは4×4なので4としてあります。MAXは今後オセロの終了を判断するために何手で終わるのかとして使うつもりです。NUM_THREADSは関数に関数を呼び出して処理が遅すぎる時があるので処理を分割する分割数です。オセロの白を1黒を-1空きを0としています。
reverseです。スペルミスしてました。reverseの引数として持っていくときにcol,rowが飛んで全く違う値になります。1と入れてもー358などになります。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 08:29
by box
そもそも、node型へのポインターを受け渡しする必要があるのでしょうか。
これがために、ややこしくなっているような気がします。

また、人対人のゲームですから、基本的な流れは

コード:

while (黒か白が置ける状態である間) {
    // 黒の番
    // 白の番
}
となるような気がします。であれば、
white_turn()だけがあってblack_turn()がないのはおかしいような気がします。
仮にblack_turn()も必要なのであれば、white_turn()とロジックは同じでしょうから
ひとまとめにして、どちらの番かは引数で渡すとか。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 09:42
by みけCAT
課題絶望 さんが書きました:reverseの引数として持っていくときにcol,rowが飛んで全く違う値になります。1と入れてもー358などになります。
本当ですか?思い込みではありませんか?デバッガやprintfデバッグなどで本当にその現象が起きていることを確認しましたか?
こちら(gcc 4.8.1)でNo: 5のコードの47, 50, 53行目の文字化けのみ別の文字列に置き換えたものをコンパイルし、
166行目にブレークポイントをおいて実行しました。
その結果、columnに2、rowに1を入力したところ、rowは1のまま変わらず、colが2, 1, 0, -1, -2, ... と遷移していく様子が観測できました。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 14:31
by 課題絶望
boxさん
その通りなんですがこれはまだ課題の問題ではないので今後付け加えたり参考にするためには構造体を使った方がいいと思ったのでそうしました。black_turnについては、このプログラムはまだ途中のプログラムでreverseがちゃんと動くか確認したところわからないエラーになったのでここに投稿したので完成形ではないです。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 14:35
by 課題絶望
みけcatさん
本当ですか?自分がそのままrunをしたときにはmoveが1か0の時にはおかしくなっていました。そこでcolやrowの値を確認したところ全く別の物になっていました。実際に動かして駒が変わりましたか?今日は少し時間がないのでできませんが明日確認してみます。

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 15:52
by みけCAT
課題絶望 さんが書きました:本当ですか?
本当です。
課題絶望 さんが書きました:実際に動かして駒が変わりましたか?
いいえ、駒が変わる前にアクセス違反になりました。

実行結果の例

コード:

YUKI.N>md5sum mod5.exe
6df1238c0cb67e5b3ee6ac9b032bf233 *mod5.exe

YUKI.N>gdb mod5.exe
GNU gdb (GDB) 7.6.1
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "mingw32".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from D:\MyData\Documents\programs\_対質問\cgengonokadaidewakaran
aitokorogaarimasu\mod5.exe...done.
(gdb) break 166
Breakpoint 1 at 0x401a29: file mod5.cpp, line 166.
(gdb) run
Starting program: D:\MyData\Documents\programs\_ホソ\cgengonokadaidewakaranaitokor
ogaarimasu/mod5.exe
[New Thread 1204.0x1830]
 1 2 3 4
1
2  B W
3  W B
4
white turnplease put position column:2

please put position row:1
return10
Breakpoint 1, reverce (board_list=0x7316c0, col=2, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=1, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=0, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-1, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-2, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-3, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-4, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-5, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-6, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-7, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-8, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-9, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) c
Continuing.

Breakpoint 1, reverce (board_list=0x7316c0, col=-10, row=1, turn=1, move=0,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:166
166           col += move_col[move];
(gdb) disable 1
(gdb) c
Continuing.
1234
Program received signal SIGSEGV, Segmentation fault.
0x00401acb in reverce (board_list=0x7316c0, col=661, row=1, turn=1, move=4,
    move_col=0x28fefc, move_row=0x28ff1c) at mod5.cpp:175
175               if(board_list->board[col-1][row-1] == WHITE){
(gdb) q
A debugging session is active.

        Inferior 1 [process 1204] will be killed.

Quit anyway? (y or n) y

YUKI.N>

Re: C言語の課題でわからないエラー

Posted: 2015年2月08日(日) 16:44
by 課題絶望
みけcatさんの実行結果をみるとcolが-3で止まりませんねそこで制限を加えないと抜け出せないということなのでしょうか。
プログラムを改変して確認してみます

Re: C言語の課題でわからないエラー

Posted: 2015年2月14日(土) 03:20
by 課題絶望
reverseに制限を加えた所うまく動きました。
reverseに制限がなかったので際限なく調べていました。
アドバイス、解答を下さったかたありがとうございました