当日の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;
}
ありません