当日のOHP資料です。
Download : sample-001.c ( SJIS 版 )
/* * 2013/11/15 sample-001.c */ /* * グローバル(大域)変数の利用 * * 利用方法 * コンパイル * cc -Ic:\usr\c\include -o sample-001.exe sample-001.c * 実行 * sample-001 */ #include <stdio.h> /* * 大域変数 (call_count) の宣言 */ int call_count = 0; /* 関数を何度呼出したか ? */ /* * 関数 print_message * void print_message ( char *string ) * 指定された文字列を表示する * 呼び出された回数を記録するために、大域変数 (call_count) を変更する * 返り値 : なし */ void print_message ( char *string ) { call_count++; /* 1 度呼出し度に、1 増やす */ printf ( "(call %d times) 文字列 : %s\n", call_count, string ); } /* * 関数 print_three_times_message * void print_three_times_message ( char *string ) * 指定された文字列を 3 度表示する * print_message を 3 度呼び出す事で実現 * 返り値 : なし */ void print_three_times_message ( char *string ) { print_message ( string ); print_message ( string ); print_message ( string ); } /* * main (関数を呼ぶだけ) */ int main( int argc, char *argv[] ) { printf ( "最初 : %d\n", call_count ); print_message ( "最初の呼出し" ); printf ( "呼出し回数が増えている : %d\n", call_count ); print_message ( "もう一度" ); printf ( "呼出し回数が更に増えている : %d\n", call_count ); print_three_times_message ( "間接的な呼出し" ); printf ( "間接的でも呼出し回数の増加が確認できる : %d\n", call_count ); return 0; }
C:\usr\c>sample-001 最初 : 0 (call 1 times) 文字列 : 最初の呼出し 呼出し回数が増えている : 1 (call 2 times) 文字列 : もう一度 呼出し回数が更に増えている : 2 (call 3 times) 文字列 : 間接的な呼出し (call 4 times) 文字列 : 間接的な呼出し (call 5 times) 文字列 : 間接的な呼出し 間接的でも呼出し回数の増加が確認できる : 5 C:\usr\c>
Download : sample-002.c ( SJIS 版 )
/* * 2013/11/15 sample-002.c */ /* * グローバル(大域)変数とローカル変数の違い * * 利用方法 * コンパイル * cc -Ic:\usr\c\include -o sample-002.exe sample-002.c * 実行 * sample-002 */ #include <stdio.h> /* * 大域変数 (call_count) の宣言 */ int call_count = 0; /* 関数を何度呼出したか ? */ /* * 関数 print_message * void print_message ( char *string ) * 指定された文字列を表示する * 呼び出された回数を記録するために、大域変数 (call_count) を変更する * 返り値 : なし */ void print_message ( char *string ) { call_count++; /* 1 度呼出し度に、1 増やす */ printf ( "(call %d times) 文字列 : %s\n", call_count, string ); } /* * 関数 print_three_times_message * void print_three_times_message ( char *string ) * 指定された文字列を 3 度表示する * print_message を 3 度呼び出す事で実現 * 返り値 : なし */ void print_three_times_message ( char *string ) { print_message ( string ); print_message ( string ); print_message ( string ); } /* * main (関数を呼ぶだけ) */ int main( int argc, char *argv[] ) { printf ( "最初 : %d\n", call_count ); print_message ( "最初の呼出し" ); printf ( "呼出し回数が増えている : %d\n", call_count ); print_message ( "もう一度" ); printf ( "呼出し回数が更に増えている : %d\n", call_count ); print_three_times_message ( "間接的な呼出し" ); printf ( "間接的でも呼出し回数の増加が確認できる : %d\n", call_count ); return 0; }
C:\usr\c>sample-002 最初 : 0 (call 1 times) 文字列 : 最初の呼出し 呼出し回数が増えている : 1 (call 2 times) 文字列 : もう一度 呼出し回数が更に増えている : 2 (call 3 times) 文字列 : 間接的な呼出し (call 4 times) 文字列 : 間接的な呼出し (call 5 times) 文字列 : 間接的な呼出し 間接的でも呼出し回数の増加が確認できる : 5 C:\usr\c>
[仕様] その場所に黒をおいてよいかどうかの判定 0. 盤内でなければならない (次の 0.1 & 0.2 が成立) 0.1 x が 0 〜 7 0.2 y が 0 〜 7 1. その場所は空でなければならない 2. その場所は、いずれかの方向(8方向)で相手のコマを挟む ( 8 方向の条件は or (論理和) の条件 : いずれか一つでよい ) 2.1 その場所の隣りには、敵のコマがある 2.2 その方向の敵のコマの並びの先に味方のコマがある # 2.1, 2.2 の条件は and (論理積 : どれも成立する) 条件 [右方向だけを考える] BW...WB <= この状態が「おいて良い」 1. B| 右端の右には W がくることはない だめ ( 更に右をみたいのに右があるかをまず調べている) 2. (1.をパスしたので右があるので..) 右のコマが相手のコマかどうかを判定する 相手のコマなら OK リファルタリング (refactoring) # re : 再び # factor : 構成要素を考える # ing : 作業(名詞化) プログラムの内容は変更しないが、表現を変更する プログラムの機能は変更しないが、構成を変更する 目的;プログラムの変更をしやすするために わかりやすくプログラムの構成を整理する == オセロのゲーム盤をつくりたい 実物と同じ(コマを指定すればおいてくれる) ただし、自動的にひっくりかえしたりはしない コマがおけるかどうかの判定と 自動的なコマの反転を行うようにしたい 判定部分としては、横の右方向だけかんがえてみた # 前回まで 今回 これを、8 方向にしたい プログラムの変更をするが、そのまえに リファクタリング(関数の切出し)をした if の条件部分 if ( 条件 ) { 条件が真(0以外)の時に実行する文 } else { 条件が偽(0)の時に実行する文 } 条件部分に && 論理積 条件1 && 条件2 : 条件1と条件2の両方が成立した場合に 1(真) になる。その他の場合は 0(偽) になる。 || 論理和 条件1 || 条件2 : 条件1と条件2のどちらか一方が成立した場合に 1(真) になる。その他の場合は 0(偽) になる。 が使える 端 右端 x==7 右方向 +1 左端 x==0 左方向 -1 [案 1] 関数 f : { -1, 1 } --> { 0, 7 } f(1) = 7 f(-1) = 0 f(x) = (x+1)/2*7 f(1) = (1+1)/2*7 = 7 f(-1) = (1-1)/2*7 = 0 [案 2] int table[3] = { 0,-1 /*なんでもよい*/, 7 }; f(x) = table[x+1]; 右端の条件判定 xx <= 7; dir * xx <= 7; ∵ dir = +1 左端の条件判定 xx >= 0; -xx <= -0; dir * xx <= 0; ∵ dir = -1 共通の条件 dir * xx <= f(dir) if ( ( dir == DIR_RIGHT && xx <= 7 ) || ( dir == DIR_LEFT && xx >= 0 ) ) 7 => f(DIR_RIGHT)=f(+1)=table[1+1]=table[1+dir] 0 => f(DIR_LEFT)=f(-1)=table[1-1]=table[1+dir] xx <= f(dir) +xx <= +f(dir) dir*xx <= dir*f(dir) xx >= f(dir) -xx <= -f(dir) dir*xx <= dir*f(dir)
v5
#include <stdio.h> #define EMPTY ' ' #define WHITE 'o' #define BLACK '*' #define YOI 1 #define WARUI 0 #define BOARD_SIZE 8 typedef char BInfo; typedef struct { BInfo info[BOARD_SIZE][BOARD_SIZE]; } Board; /* * */ typedef struct { int check_result; int xx; } CheckResult; CheckResult check_migi_yoko ( Board board, int x, int y, int color ) { CheckResult result; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ int oc; int xx; /* 打った手の右がひっくり返れば OK とする */ checkResult = YOI; /* とりあえず、チェック前なので、正しいとする */ if ( color == WHITE ) { oc = BLACK; } else { oc = WHITE; } /* x の正の方向 しかみない */ /* 本当ならば 8 方向をみる必要がある */ /* いきなり8 方向は大変なので、右方向だけやってみた */ if ( x < 0 || BOARD_SIZE <= x ) { /* 盤外なのでダメ */ checkResult = WARUI; } else if ( y < 0 || BOARD_SIZE <= y ) { checkResult = WARUI; } else if ( board.info[x][y] != EMPTY ) { /* すでにコマがある */ /* これは打てない */ checkResult = WARUI; } else if ( BOARD_SIZE - 1 <= x ) { /* 右端なので、その右はない */ checkResult = WARUI; } else if ( board.info[x+1][y+0] != oc ) { /* 打った右のコマが相手コマでなかった */ /* この場合も右のコマはひっくりかえらない */ checkResult = WARUI; } else { xx = x + 2; /* この位置に自分のコマがほしい */ /* yy = y + 0; */ while ( xx < BOARD_SIZE ) { if ( board.info[xx][y] == color ) { break; /* ここで while 終了 */ /* はさめたので OK */ } else if ( board.info[xx][y] == EMPTY ) { checkResult = WARUI; break; /* ダメ */ } else if ( board.info[xx][y] == oc ) { /* さらに次を見るまでワカラナイ*/ xx = xx + 1; } } /* while を抜けた時点で、 抜けた理由が3通りある 端まできた => checkState を 0(ダメ) にする必要がある はさめた => checkState を 1(ヨイ) のままで良い はさめなかった => checkState は 0(ダメ)になっている */ if ( xx >= BOARD_SIZE ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } } result.check_result = checkResult; result.xx = xx; return result; } int main(int argc, char *argv[] ) { CheckResult result; Board board; int x; int y; int color; int input_color; int xx; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ printf ( "Othello Version 5\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { for ( x = 0; x < BOARD_SIZE; x++ ) { board.info[x][y] = EMPTY; } } x = BOARD_SIZE/2; y = BOARD_SIZE/2; board.info[x][y] = WHITE; board.info[x-1][y-1] = WHITE; board.info[x][y-1] = BLACK; board.info[x-1][y] = BLACK; while ( 1 == 1 ) { /* 1==1 は常に成立するのでずっと続く */ printf ( "コマを入力してください : \n" ); printf ( "x=" ); scanf ( "%d", &x ); printf ( "y=" ); scanf ( "%d", &y ); printf ( "color(B=0/W=1)=" ); scanf ( "%d", &input_color ); /* 入力(0/1) から、色(BLOCK/WHITE)への変換 */ if ( input_color == 0 ) { color = BLACK; } else { color = WHITE; } result = check_migi_yoko ( board, x, y, color ); checkResult = result.check_result; xx = result.xx; /* 指定された指し手が正しい場合だけ、 盤面を変化させる 具体的ははさんだコマはひっくり返す そうでない(正しくない指して)の場合は、 誤りであることを提示し、再入力させる */ if ( checkResult == WARUI ) { printf ( "そこには打てません\n" ); } else { int xxx; /* 引っくり返す場所 */ board.info[x][y] = color; /* うった場所 */ xxx = x + 1; /* 引っくり返す場所はその隣りから */ while ( xxx < xx ) { /* xx の直前迄 */ board.info[xxx][y] = color; /* はさんだコマをひっくり返す */ xxx = xxx + 1; /* 次の場所に進む */ } } printf ( " A B C D E F G H\n" ); printf ( " +--+--+--+--+--+--+--+--+\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { printf ( "%d|", y+1 ); for ( x = 0; x < BOARD_SIZE; x++ ) { if ( board.info[x][y] == EMPTY ) { printf ( " " ); } else if ( board.info[x][y] == BLACK ) { printf ( "●" ); } else if ( board.info[x][y] == WHITE ) { printf ( "○" ); } /* putchar ( board.info[x][y] ); */ putchar ( '|' ); } putchar ( '\n' ); printf ( " +--+--+--+--+--+--+--+--+\n" ); } } return 0; }
v6
#include <stdio.h> #define EMPTY ' ' #define WHITE 'o' #define BLACK '*' #define YOI 1 #define WARUI 0 #define BOARD_SIZE 8 typedef char BInfo; typedef struct { BInfo info[BOARD_SIZE][BOARD_SIZE]; } Board; /* * */ typedef struct { int check_result; int xx; } CheckResult; CheckResult check_hidari_yoko ( Board board, int x, int y, int color ) { CheckResult result; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ int oc; int xx; /* 打った手の左がひっくり返れば OK とする */ checkResult = YOI; /* とりあえず、チェック前なので、正しいとする */ if ( color == WHITE ) { oc = BLACK; } else { oc = WHITE; } /* x の負の方向 しかみない */ if ( x < 0 || BOARD_SIZE <= x ) { /* 盤外なのでダメ */ checkResult = WARUI; } else if ( y < 0 || BOARD_SIZE <= y ) { checkResult = WARUI; } else if ( board.info[x][y] != EMPTY ) { /* すでにコマがある */ /* これは打てない */ checkResult = WARUI; } else if ( x <= 0 ) { /* <左> */ /* 左端なので、その左はない */ checkResult = WARUI; } else if ( board.info[x-1][y+0] != oc ) { /* <左> */ /* x -> x-1 : 左 */ /* x -> x+1 : 右 */ /* 打った左のコマが相手コマでなかった */ /* この場合も左のコマはひっくりかえらない */ checkResult = WARUI; } else { xx = x - 2; /* この位置に自分のコマがほしい */ /* yy = y + 0; */ while ( 0 <= xx ) { /* <左> */ if ( board.info[xx][y] == color ) { break; /* ここで while 終了 */ /* はさめたので OK */ } else if ( board.info[xx][y] == EMPTY ) { checkResult = WARUI; break; /* ダメ */ } else if ( board.info[xx][y] == oc ) { /* さらに次を見るまでワカラナイ*/ xx = xx - 1; /* <左> */ /* x -> x+1 右へ */ /* x -> x-1 左へ */ } } /* while を抜けた時点で、 抜けた理由が3通りある 端まできた => checkState を 0(ダメ) にする必要がある はさめた => checkState を 1(ヨイ) のままで良い はさめなかった => checkState は 0(ダメ)になっている */ if ( 0 < xx ) { /* 端までしらべた <左> */ checkResult = WARUI; /* はさめなかった */ } } result.check_result = checkResult; result.xx = xx; return result; } CheckResult check_migi_yoko ( Board board, int x, int y, int color ) { CheckResult result; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ int oc; int xx; /* 打った手の右がひっくり返れば OK とする */ checkResult = YOI; /* とりあえず、チェック前なので、正しいとする */ if ( color == WHITE ) { oc = BLACK; } else { oc = WHITE; } /* x の正の方向 しかみない */ /* 本当ならば 8 方向をみる必要がある */ /* いきなり8 方向は大変なので、右方向だけやってみた */ if ( x < 0 || BOARD_SIZE <= x ) { /* 盤外なのでダメ */ checkResult = WARUI; } else if ( y < 0 || BOARD_SIZE <= y ) { checkResult = WARUI; } else if ( board.info[x][y] != EMPTY ) { /* すでにコマがある */ /* これは打てない */ checkResult = WARUI; } else if ( BOARD_SIZE - 1 <= x ) { /* 右端なので、その右はない */ checkResult = WARUI; } else if ( board.info[x+1][y+0] != oc ) { /* 打った右のコマが相手コマでなかった */ /* この場合も右のコマはひっくりかえらない */ checkResult = WARUI; } else { xx = x + 2; /* この位置に自分のコマがほしい */ /* yy = y + 0; */ while ( xx < BOARD_SIZE ) { if ( board.info[xx][y] == color ) { break; /* ここで while 終了 */ /* はさめたので OK */ } else if ( board.info[xx][y] == EMPTY ) { checkResult = WARUI; break; /* ダメ */ } else if ( board.info[xx][y] == oc ) { /* さらに次を見るまでワカラナイ*/ xx = xx + 1; } } /* while を抜けた時点で、 抜けた理由が3通りある 端まできた => checkState を 0(ダメ) にする必要がある はさめた => checkState を 1(ヨイ) のままで良い はさめなかった => checkState は 0(ダメ)になっている */ if ( xx >= BOARD_SIZE ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } } result.check_result = checkResult; result.xx = xx; return result; } int main(int argc, char *argv[] ) { CheckResult result; Board board; int x; int y; int color; int input_color; int xx; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ printf ( "Othello Version 6\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { for ( x = 0; x < BOARD_SIZE; x++ ) { board.info[x][y] = EMPTY; } } x = BOARD_SIZE/2; y = BOARD_SIZE/2; board.info[x][y] = WHITE; board.info[x-1][y-1] = WHITE; board.info[x][y-1] = BLACK; board.info[x-1][y] = BLACK; while ( 1 == 1 ) { /* 1==1 は常に成立するのでずっと続く */ printf ( "コマを入力してください : \n" ); printf ( "x=" ); scanf ( "%d", &x ); printf ( "y=" ); scanf ( "%d", &y ); printf ( "color(B=0/W=1)=" ); scanf ( "%d", &input_color ); /* 入力(0/1) から、色(BLOCK/WHITE)への変換 */ if ( input_color == 0 ) { color = BLACK; } else { color = WHITE; } result = check_hidari_yoko ( board, x, y, color ); checkResult = result.check_result; xx = result.xx; /* 指定された指し手が正しい場合だけ、 盤面を変化させる 具体的ははさんだコマはひっくり返す そうでない(正しくない指して)の場合は、 誤りであることを提示し、再入力させる */ if ( checkResult == WARUI ) { printf ( "そこには打てません\n" ); } else { int xxx; /* 引っくり返す場所 */ board.info[x][y] = color; /* うった場所 */ xxx = x + 1; /* 引っくり返す場所はその隣りから */ while ( xxx < xx ) { /* xx の直前迄 */ board.info[xxx][y] = color; /* はさんだコマをひっくり返す */ xxx = xxx + 1; /* 次の場所に進む */ } } printf ( " A B C D E F G H\n" ); printf ( " +--+--+--+--+--+--+--+--+\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { printf ( "%d|", y+1 ); for ( x = 0; x < BOARD_SIZE; x++ ) { if ( board.info[x][y] == EMPTY ) { printf ( " " ); } else if ( board.info[x][y] == BLACK ) { printf ( "●" ); } else if ( board.info[x][y] == WHITE ) { printf ( "○" ); } /* putchar ( board.info[x][y] ); */ putchar ( '|' ); } putchar ( '\n' ); printf ( " +--+--+--+--+--+--+--+--+\n" ); } } return 0; }
v7
#include <stdio.h> #define VERSION 7 /* Version 番号 */ #define EMPTY ' ' #define WHITE 'o' #define BLACK '*' #define YOI 1 #define WARUI 0 #define BOARD_SIZE 8 typedef char BInfo; typedef struct { BInfo info[BOARD_SIZE][BOARD_SIZE]; } Board; /* * */ typedef struct { int check_result; int xx; } CheckResult; #define DIR_RIGHT 1 /* 右方向は +1 */ #define DIR_LEFT -1 /* 左方向は -1 */ CheckResult check_yoko ( Board board, int x, int y, int color, int dir ) { CheckResult result; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ int oc; int xx; /* 打った手の右がひっくり返れば OK とする */ checkResult = YOI; /* とりあえず、チェック前なので、正しいとする */ if ( color == WHITE ) { oc = BLACK; } else { oc = WHITE; } /* x の正の方向 しかみない */ /* 本当ならば 8 方向をみる必要がある */ /* いきなり8 方向は大変なので、右方向だけやってみた */ if ( x < 0 || BOARD_SIZE <= x ) { /* 盤外なのでダメ */ checkResult = WARUI; } else if ( y < 0 || BOARD_SIZE <= y ) { checkResult = WARUI; } else if ( board.info[x][y] != EMPTY ) { /* すでにコマがある */ /* これは打てない */ checkResult = WARUI; } else if ( dir == DIR_RIGHT && BOARD_SIZE - 1 <= x ) { /* 方向が右で、右端ならだめ */ checkResult = WARUI; } else if ( dir == DIR_LEFT && x <= 0 ) { /* 方向が左で、左端ならだめ */ checkResult = WARUI; } else if ( board.info[x+dir][y+0] != oc ) { /* 打った右のコマが相手コマでなかった */ /* この場合も右のコマはひっくりかえらない */ checkResult = WARUI; } else { xx = x + dir * 2; /* この位置に自分のコマがほしい */ /* yy = y + 0; */ while ( (dir == DIR_RIGHT && xx < BOARD_SIZE) || (dir == DIR_LEFT && 0 <= xx ) ) { if ( board.info[xx][y] == color ) { break; /* ここで while 終了 */ /* はさめたので OK */ } else if ( board.info[xx][y] == EMPTY ) { checkResult = WARUI; break; /* ダメ */ } else if ( board.info[xx][y] == oc ) { /* さらに次を見るまでワカラナイ*/ xx = xx + dir; } } /* while を抜けた時点で、 抜けた理由が3通りある 端まできた => checkState を 0(ダメ) にする必要がある はさめた => checkState を 1(ヨイ) のままで良い はさめなかった => checkState は 0(ダメ)になっている */ if ( dir == DIR_RIGHT && xx >= BOARD_SIZE ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } else if ( dir == DIR_LEFT && xx < 0 ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } } result.check_result = checkResult; result.xx = xx; return result; } CheckResult check_hidari_yoko ( Board board, int x, int y, int color ) { return check_yoko ( board, x, y, color, DIR_LEFT ); } CheckResult check_migi_yoko ( Board board, int x, int y, int color ) { return check_yoko ( board, x, y, color, DIR_RIGHT ); } Board hikkurikaesu_yoko ( Board board, int x, int y, int color, int dir, \ int xx ) { int xxx; /* 引っくり返す場所 */ /* 指定された指し手が正しい場合だけ、 盤面を変化させる 具体的ははさんだコマはひっくり返す そうでない(正しくない指して)の場合は、 誤りであることを提示し、再入力させる */ board.info[x][y] = color; /* うった場所 */ xxx = x + dir; /* 引っくり返す場所はその隣りから */ while ( (dir == DIR_RIGHT && xxx < xx) || (dir == DIR_LEFT && xxx > xx) ) { /* xx の直前(後)迄 */ board.info[xxx][y] = color; /* はさんだコマをひっくり返す */ xxx = xxx + dir; /* 次の場所に進む */ } return board; } Board hikkurikaesu_migi_yoko ( Board board, int x, int y, int color, int xx \ ) { return hikkurikaesu_yoko ( board, x, y, color, DIR_RIGHT, xx ); } Board hikkurikaesu_hidari_yoko ( Board board, int x, int y, int color, int \ xx ) { return hikkurikaesu_yoko ( board, x, y, color, DIR_LEFT, xx ); } int main(int argc, char *argv[] ) { CheckResult resultMigi; CheckResult resultHidari; Board board; int x; int y; int color; int input_color; int xx; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ printf ( "Othello Version %d\n", VERSION ); for ( y = 0; y < BOARD_SIZE; y++ ) { for ( x = 0; x < BOARD_SIZE; x++ ) { board.info[x][y] = EMPTY; } } x = BOARD_SIZE/2; y = BOARD_SIZE/2; board.info[x][y] = WHITE; board.info[x-1][y-1] = WHITE; board.info[x][y-1] = BLACK; board.info[x-1][y] = BLACK; while ( 1 == 1 ) { /* 1==1 は常に成立するのでずっと続く */ printf ( "コマを入力してください : \n" ); printf ( "x=" ); scanf ( "%d", &x ); printf ( "y=" ); scanf ( "%d", &y ); printf ( "color(B=0/W=1)=" ); scanf ( "%d", &input_color ); /* 入力(0/1) から、色(BLOCK/WHITE)への変換 */ if ( input_color == 0 ) { color = BLACK; } else { color = WHITE; } resultMigi = check_migi_yoko ( board, x, y, color ); resultHidari = check_hidari_yoko ( board, x, y, color ); if ( resultMigi.check_result == WARUI && resultHidari.check_result == WARUI ) { printf ( "そこには打てません\n" ); } else { if ( resultMigi.check_result == YOI ) { board = hikkurikaesu_migi_yoko ( board, x, y, color, resultMigi.xx ); } if ( resultHidari.check_result == YOI ) { board = hikkurikaesu_hidari_yoko ( board, x, y, color, resultHidari.xx \ ); } } printf ( " A B C D E F G H\n" ); printf ( " +--+--+--+--+--+--+--+--+\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { printf ( "%d|", y+1 ); for ( x = 0; x < BOARD_SIZE; x++ ) { if ( board.info[x][y] == EMPTY ) { printf ( " " ); } else if ( board.info[x][y] == BLACK ) { printf ( "●" ); } else if ( board.info[x][y] == WHITE ) { printf ( "○" ); } /* putchar ( board.info[x][y] ); */ putchar ( '|' ); } putchar ( '\n' ); printf ( " +--+--+--+--+--+--+--+--+\n" ); } } return 0; }
v8
#include <stdio.h> #define VERSION 8 /* Version 番号 */ #define EMPTY ' ' #define WHITE 'o' #define BLACK '*' #define YOI 1 #define WARUI 0 #define BOARD_SIZE 8 typedef char BInfo; typedef struct { BInfo info[BOARD_SIZE][BOARD_SIZE]; } Board; /* * */ typedef struct { int check_result; int xx; } CheckResult; #define DIR_RIGHT 1 /* 右方向は +1 */ #define DIR_LEFT -1 /* 左方向は -1 */ CheckResult check_yoko ( Board board, int x, int y, int color, int dir ) { CheckResult result; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ int oc; int xx; int table[] = { 0, -1, 7 }; /* int table[3]; table[0] = 7; table[1] = -1; table[2] = 0; と同じ */ /* 打った手の右がひっくり返れば OK とする */ checkResult = YOI; /* とりあえず、チェック前なので、正しいとする */ if ( color == WHITE ) { oc = BLACK; } else { oc = WHITE; } /* x の正の方向 しかみない */ /* 本当ならば 8 方向をみる必要がある */ /* いきなり8 方向は大変なので、右方向だけやってみた */ if ( x < 0 || BOARD_SIZE <= x ) { /* 盤外なのでダメ */ checkResult = WARUI; } else if ( y < 0 || BOARD_SIZE <= y ) { checkResult = WARUI; } else if ( board.info[x][y] != EMPTY ) { /* すでにコマがある */ /* これは打てない */ checkResult = WARUI; } else if ( dir * xx <= dir * table[dir+1] ) { checkResult = WARUI; } else if ( board.info[x+dir][y+0] != oc ) { /* 打った右のコマが相手コマでなかった */ /* この場合も右のコマはひっくりかえらない */ checkResult = WARUI; } else { xx = x + dir * 2; /* この位置に自分のコマがほしい */ /* yy = y + 0; */ while ( (dir == DIR_RIGHT && xx < BOARD_SIZE) || (dir == DIR_LEFT && 0 <= xx ) ) { if ( board.info[xx][y] == color ) { break; /* ここで while 終了 */ /* はさめたので OK */ } else if ( board.info[xx][y] == EMPTY ) { checkResult = WARUI; break; /* ダメ */ } else if ( board.info[xx][y] == oc ) { /* さらに次を見るまでワカラナイ*/ xx = xx + dir; } } /* while を抜けた時点で、 抜けた理由が3通りある 端まできた => checkState を 0(ダメ) にする必要がある はさめた => checkState を 1(ヨイ) のままで良い はさめなかった => checkState は 0(ダメ)になっている */ if ( dir == DIR_RIGHT && xx >= BOARD_SIZE ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } else if ( dir == DIR_LEFT && xx < 0 ) { /* 端までしらべた */ checkResult = WARUI; /* はさめなかった */ } } result.check_result = checkResult; result.xx = xx; return result; } CheckResult check_hidari_yoko ( Board board, int x, int y, int color ) { return check_yoko ( board, x, y, color, DIR_LEFT ); } CheckResult check_migi_yoko ( Board board, int x, int y, int color ) { return check_yoko ( board, x, y, color, DIR_RIGHT ); } Board hikkurikaesu_yoko ( Board board, int x, int y, int color, int dir, \ int xx ) { int xxx; /* 引っくり返す場所 */ /* 指定された指し手が正しい場合だけ、 盤面を変化させる 具体的ははさんだコマはひっくり返す そうでない(正しくない指して)の場合は、 誤りであることを提示し、再入力させる */ board.info[x][y] = color; /* うった場所 */ xxx = x + dir; /* 引っくり返す場所はその隣りから */ while ( (dir == DIR_RIGHT && xxx < xx) || (dir == DIR_LEFT && xxx > xx) ) { /* xx の直前(後)迄 */ board.info[xxx][y] = color; /* はさんだコマをひっくり返す */ xxx = xxx + dir; /* 次の場所に進む */ } return board; } Board hikkurikaesu_migi_yoko ( Board board, int x, int y, int color, int xx \ ) { return hikkurikaesu_yoko ( board, x, y, color, DIR_RIGHT, xx ); } Board hikkurikaesu_hidari_yoko ( Board board, int x, int y, int color, int \ xx ) { return hikkurikaesu_yoko ( board, x, y, color, DIR_LEFT, xx ); } int main(int argc, char *argv[] ) { CheckResult resultMigi; CheckResult resultHidari; Board board; int x; int y; int color; int input_color; int xx; int checkResult; /* うってよいかどうか (1=よい/0=悪い) */ printf ( "Othello Version %d\n", VERSION ); for ( y = 0; y < BOARD_SIZE; y++ ) { for ( x = 0; x < BOARD_SIZE; x++ ) { board.info[x][y] = EMPTY; } } x = BOARD_SIZE/2; y = BOARD_SIZE/2; board.info[x][y] = WHITE; board.info[x-1][y-1] = WHITE; board.info[x][y-1] = BLACK; board.info[x-1][y] = BLACK; while ( 1 == 1 ) { /* 1==1 は常に成立するのでずっと続く */ printf ( "コマを入力してください : \n" ); printf ( "x=" ); scanf ( "%d", &x ); printf ( "y=" ); scanf ( "%d", &y ); printf ( "color(B=0/W=1)=" ); scanf ( "%d", &input_color ); /* 入力(0/1) から、色(BLOCK/WHITE)への変換 */ if ( input_color == 0 ) { color = BLACK; } else { color = WHITE; } resultMigi = check_migi_yoko ( board, x, y, color ); resultHidari = check_hidari_yoko ( board, x, y, color ); if ( resultMigi.check_result == WARUI && resultHidari.check_result == WARUI ) { printf ( "そこには打てません\n" ); } else { if ( resultMigi.check_result == YOI ) { board = hikkurikaesu_migi_yoko ( board, x, y, color, resultMigi.xx ); } if ( resultHidari.check_result == YOI ) { board = hikkurikaesu_hidari_yoko ( board, x, y, color, resultHidari.xx \ ); } } printf ( " A B C D E F G H\n" ); printf ( " +--+--+--+--+--+--+--+--+\n" ); for ( y = 0; y < BOARD_SIZE; y++ ) { printf ( "%d|", y+1 ); for ( x = 0; x < BOARD_SIZE; x++ ) { if ( board.info[x][y] == EMPTY ) { printf ( " " ); } else if ( board.info[x][y] == BLACK ) { printf ( "●" ); } else if ( board.info[x][y] == WHITE ) { printf ( "○" ); } /* putchar ( board.info[x][y] ); */ putchar ( '|' ); } putchar ( '\n' ); printf ( " +--+--+--+--+--+--+--+--+\n" ); } } return 0; }
ありません