コンピュータとオセロ対戦4　～二手先まで読んで返す～

https://qiita.com/tt_and_tk/items/068f2afde6db637e189f

[前回](https://qiita.com/tt_and_tk/items/7ddb15af4609e55908d2)
# 今回の目標
[前回](https://qiita.com/tt_and_tk/items/7ddb15af4609e55908d2)で、一手先まで読んで返すプログラムを作りました。
今回はここから、二手先まで考えるプログラムを作ります。
なおこの記事は、[前回](https://qiita.com/tt_and_tk/items/7ddb15af4609e55908d2)の内容を知っている前提で書いています。

:::note warn
かなり効率の悪いプログラムなので、完成版ではここで紹介する方法は使っていません。
参考程度にご覧ください。
:::

# ここから本編
## mainの上に書くやつ
Board_stateからscoreがなくなりました。
[前回](https://qiita.com/tt_and_tk/items/7ddb15af4609e55908d2)との違いはそのくらいですね。

```2hand.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <stdbool.h>

#define NONE 0
#define WHITE 1
#define BLACK 2
#define SIZE 8

typedef struct BOARD{
    char board[SIZE][SIZE];
} Board_state;

char board_global[SIZE][SIZE] = {NONE};
bool turn;

void setup(void);
void print(void);
void que(int * line, int * col);
void put(int line, int col, Board_state * now, bool tn);
void put_global(int line, int col);
void stop(void);
bool check(int line, int col, Board_state * now);
bool check_global(int line, int col);
bool check_all(void);
bool all_none(void);
int count(Board_state * now);
void count_last(void);
void think(void);
int board_add(int line, int col);
int board_add_add(int line, int col, Board_state * now);
```
## count
Board_stateからscoreがなくなったので、countが整数を返す関数になりました。

```2hand.c
int count(Board_state * now){
    int i, j;
    int my = 0, opp = 0;

    for (i = 0; i < SIZE; i++){
        for (j = 0; j < SIZE; j++){
            if (now -> board[i][j] == WHITE) my++;
            else if (now -> board[i][j]  == BLACK) opp++;
        }
    }
    return my - opp;
}
```

## board_add
本当は再起関数にしたかったんですが、方法が思いつきませんでした。この辺りも後々アルゴリズムを変更したきっかけです。
やっていることとしては、

1. 盤面をコピペ
1. 置ける場所をすべてメモする。
1. 置ける場所がなかった場合、今のスコアを返す。
1. 置ける場所が複数あった場合、二手目の平均スコアを返す。小数点以下は切り捨て。

です。

:::note warn
このプログラムはマネしないでください。悪い例です。
:::

```2hand.c
int board_add(int line, int col){
    int i, j, k, num = 0;
    int score = 0;
    int line_a[SIZE * 2] = {-1}, col_a[SIZE * 2] = {-1};
    int line_put, col_put;
    char * line_array;
    Board_state * leaf = malloc(sizeof(Board_state));

    if (leaf == NULL) stop();

    for (i = 0; i < SIZE; i++){
        line_array = leaf -> board[i];
        for (j = 0; j < SIZE; j++){
            line_array[j] = board_global[i][j];
        }
    }
    put(line, col, leaf, turn);

    for (i = 0; i < SIZE; i++){
        for (j = 0; j < SIZE; j++){
            if (check(i, j, leaf)){
                line_a[num] = i;
                col_a[num] = j;
                num++;
            }
        }
    }

    if (num  == 0) score = count(leaf);
    else{
        for (i = 0; i < num; i++){
            score += board_add_add(line_a[i], col_a[i], leaf);
        }
        score = score / num;
    }
    free(leaf);
    return score;
}
```

## board_add_add
再起関数にすべきですね。
やっていることは[前回](https://qiita.com/tt_and_tk/items/7ddb15af4609e55908d2)のboard_addと同じです。

```2hand.c
int board_add_add(int line, int col, Board_state * now){
    int i, j, score;
    char * line_array;
    Board_state * leaf_leaf = malloc(sizeof(Board_state));

    if (leaf_leaf == NULL) stop();

    for (i = 0; i < SIZE; i++){
        line_array = leaf_leaf -> board[i];
        for (j = 0; j < SIZE; j++){
            line_array[j] = now -> board[i][j];
        }
    }
    put(line, col, leaf_leaf, !turn);
    score = count(leaf_leaf);
    free(leaf_leaf);
    return score;
}
```

# フルバージョン
この中から「2hand.c」を探してください。

https://github.com/TTaisei/osero

# 実際にやってみる
ある程度は予測できないところに売ってきました。
でもまだ満足できないです。
# 次回は
再起関数を用いて、「n手先まで読んで返す」プログラムを考えます。
[次回](https://qiita.com/tt_and_tk/items/c1c526bdb3dd7f163161)

https://qiita.com/tt_and_tk/items/068f2afde6db637e189f