今回の目標
前回で、一手先まで読んで返すプログラムを作りました。
今回はここから、二手先まで考えるプログラムを作ります。
なおこの記事は、前回の内容を知っている前提で書いています。
かなり効率の悪いプログラムなので、完成版ではここで紹介する方法は使っていません。
参考程度にご覧ください。
ここから本編
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
本当は再起関数にしたかったんですが、方法が思いつきませんでした。この辺りも後々アルゴリズムを変更したきっかけです。
やっていることとしては、
- 盤面をコピペ
- 置ける場所をすべてメモする。
- 置ける場所がなかった場合、今のスコアを返す。
- 置ける場所が複数あった場合、二手目の平均スコアを返す。小数点以下は切り捨て。
です。
このプログラムはマネしないでください。悪い例です。
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手先まで読んで返す」プログラムを考えます。
次回