1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-09-12

前回

今回の目標

前回で、一手先まで読んで返すプログラムを作りました。
今回はここから、二手先まで考えるプログラムを作ります。
なおこの記事は、前回の内容を知っている前提で書いています。

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

ここから本編

mainの上に書くやつ

Board_stateからscoreがなくなりました。
前回との違いはそのくらいですね。

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. 盤面をコピペ
  2. 置ける場所をすべてメモする。
  3. 置ける場所がなかった場合、今のスコアを返す。
  4. 置ける場所が複数あった場合、二手目の平均スコアを返す。小数点以下は切り捨て。

です。

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

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

再起関数にすべきですね。
やっていることは前回の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」を探してください。

実際にやってみる

ある程度は予測できないところに売ってきました。
でもまだ満足できないです。

次回は

再起関数を用いて、「n手先まで読んで返す」プログラムを考えます。
次回

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?