#include "T3EBoard.h"
#include <iostream>
#include <time.h>
#include <stdlib.h>
// コンストラクタ
T3EBoard::T3EBoard()
{
srand((unsigned int)clock());
this->Reset();
}
// デストラクタ
T3EBoard::~T3EBoard()
{
}
// ゲーム初期化
void T3EBoard::Reset()
{
m_Turn = 1;
m_NextPlayer = PLAYER1;
for (int i = 0; i < BOARD_SIZE; i++) {
m_Board[i] = NONE;
}
}
// ゲーム進行
void T3EBoard::Play()
{
// ゲーム初期化
std::cout << "拡張版○× ゲーム" << std::endl << std::endl;
std::cout << "先手は 0:人間 1:CPU ?";
std::cin >> m_Player[PLAYER1];
std::cout << "後手は 0:人間 1:CPU ?";
std::cin >> m_Player[PLAYER2];
std::cout << "始め!" << std::endl;
// ターン進行
do {
// ターン情報
std::cout << std::endl << "ターン " << m_Turn << std::endl;
this->ShowBoard();
std::cout << (m_NextPlayer == PLAYER1 ? "先手" : "後手")
<< "の番です" << std::endl;
int place = (m_Player[m_NextPlayer] == PLAYER_HUMAN ? Human() : CPU());
this->SetStone(place);
int winner = this->CheckWin();
if (winner >= 0) {
this->ShowBoard();
std::cout << std::endl << (m_NextPlayer == PLAYER1 ? "先手" : "後手")
<< " 勝利" << std::endl;
break;
}
// 次の番へ
m_NextPlayer = 1 - m_NextPlayer;
if (m_NextPlayer == PLAYER1) m_Turn ++;
if (m_Turn >= MAX_TURNS) std::cout << std::endl << "引き分け!" << std::endl;
} while (m_Turn < MAX_TURNS);
std::cin.ignore(std::cin.rdbuf()->in_avail()); // 入力バッファクリア
std::cin.get(); // 終了前のキー入力待ち
}
// CPUの思考アルゴリズム
// 戻り値:コマを打つ場所
int T3EBoard::CPU()
{
int place = 0;
int i[11],j;
int tempPlace[11];
int ZeroCount=0,ZeroCount2=0;
int ImageBoard[BOARD_SIZE], ImageTurn,ImageNextPlayer,Me;
//勝敗管理配列
int row[11], col[11];
int check[11];
int sign[2] = { STONE1, STONE2 };
//複写
ImageTurn = m_Turn;
ImageNextPlayer = m_NextPlayer;
printf("ImageNext = %d\n", ImageNextPlayer);
//自分は正の数,相手は負の数で複写
if (ImageNextPlayer == PLAYER1) {
printf("私は先手\n");
for (i[0] = 0;i[0] < BOARD_SIZE;i[0]++) {
ImageBoard[i[0]] = m_Board[i[0]];
}
}
else {
printf("私は後手\n");
for (i[0] = 0;i[0] < BOARD_SIZE;i[0]++) {
ImageBoard[i[0]] = (-1)*m_Board[i[0]];
}
}
//盤上の何もない場所を数える。
for (i[0] = 0;i[0] < BOARD_SIZE;i[0]++) {
if (ImageBoard[i[0]] == 0)ZeroCount++;
}
//printf("ZERO=%d\n", ZeroCount);
//Minmax法の記述
//現在のターン全通り試すfor depth=0
for (i[0] = 0;i[0] < BOARD_SIZE;i[0]++) {
//printf("i = %d\n",i[0]);
//何も置いてない場所を見つける
if (ImageBoard[i[0]] == 0) {
//SetStoneの記述1
ImageBoard[i[0]] = ImageTurn;
tempPlace[0] = i[0];
// 古いコマを消す
if (ImageTurn > MAX_PIECE_ON_BOARD) {
int deleting = (ImageTurn - MAX_PIECE_ON_BOARD);
for (int i = 0; i < BOARD_SIZE; i++) {
if (ImageBoard[i] == deleting) ImageBoard[i] = 0;
}
}
//勝てるチャンスだったら勝つ
// 斜め方向1
for (row[0] = 0, check[0] = 0; row[0] < BOARD_HEIGHT; row[0]++) {
if (ImageBoard[row[0] * BOARD_WIDTH + row[0]] > 0) check[0]++;
}
if (check[0] == 3) {
printf("naname1\n");return i[0];
}
// 斜め方向2
for (row[0] = 0, check[0] = 0; row[0] < BOARD_HEIGHT; row[0]++) {
if (ImageBoard[row[0] * BOARD_WIDTH + (BOARD_HEIGHT - 1 - row[0])] > 0) check[0]++;
}
if (check[0] == 3) {
printf("naname2\n");return i[0];
}
// 横方向
for (row[0] = 0; row[0] < BOARD_HEIGHT; row[0]++) {
for (col[0] = 0, check[0] = 0; col[0] < BOARD_WIDTH; col[0]++) {
if (ImageBoard[row[0] * BOARD_WIDTH + col[0]] > 0) check[0]++;
}
if (check[0] == 3) {
printf("yoko\n");return i[0];
}
}
// 縦方向
for (col[0] = 0; col[0] < BOARD_WIDTH; col[0]++) {
for (row[0] = 0, check[0] = 0; row[0] < BOARD_HEIGHT; row[0]++) {
if (ImageBoard[row[0] * BOARD_WIDTH + col[0]] > 0) check[0]++;
}
if (check[0] == 3) {
printf("tate\n");return i[0];
}
}
//相手の手へ depth=1
ImageTurn++;
for (i[1] = 0;i[1] < BOARD_SIZE;i[1]++) {
if (ImageBoard[i[1]] == 0) {
}
}
//初期状態に戻す
ImageBoard[tempPlace[0]] = 0;
ImageTurn = m_Turn;
ImageNextPlayer = m_Turn;
}
}
do {
place = rand() % BOARD_SIZE;
} while (m_Board[place] != NONE);
std::cout << "CPU => " << place << std::endl;
return place;
}
// 人間の手番
// 戻り値:コマを打つ場所
int T3EBoard::Human()
{
int place = 0;
while(1) {
std::cout << "0:左上 1:上 2:右上 3:左 4:中央 5:右 6:左下 7:下 8:右下" << std::endl
<< "どこに打ちますか? ";
std::cin >> place;
if (place >= 0 && place < BOARD_SIZE) {
if (m_Board[place] == 0) break;
}
}
return place;
}
// 盤にコマを置く
// 引数 int place : 置く位置
void T3EBoard::SetStone(int place)
{
int sign = m_NextPlayer == PLAYER1 ? STONE1 : STONE2;
m_Board[place] = m_Turn * sign;
// 古いコマを消す
if (m_Turn > MAX_PIECE_ON_BOARD) {
int deleting = (m_Turn - MAX_PIECE_ON_BOARD) * sign;
for (int i = 0; i < BOARD_SIZE; i++) {
if (m_Board[i] == deleting) m_Board[i] = 0;
}
}
}
// 勝利判定
// 戻り値:-1 未決着 0(PLAYER1) 先手勝利 1(PLAYER2) 後手勝利
int T3EBoard::CheckWin()
{
int row, col;
bool check;
int sign[2] = {STONE1, STONE2};
// プレイヤー毎に判定
for (int player = PLAYER1; player <= PLAYER2; player++) {
// 斜め方向1
for (row = 0, check = true; row < BOARD_HEIGHT; row++) {
if (m_Board[row * BOARD_WIDTH + row] * sign[player] <= 0) check = false;
}
if (check) return player;
// 斜め方向2
for (row = 0, check = true; row < BOARD_HEIGHT; row++) {
if (m_Board[row * BOARD_WIDTH + (BOARD_HEIGHT - 1 - row)] * sign[player] <= 0) check = false;
}
if (check) return player;
// 横方向
for (row = 0; row < BOARD_HEIGHT; row++) {
for (col = 0, check = true; col < BOARD_WIDTH; col++) {
if (m_Board[row * BOARD_WIDTH + col] * sign[player] <= 0) check = false;
}
if (check) return player;
}
// 縦方向
for (col = 0; col < BOARD_WIDTH; col++) {
for (row = 0, check = true; row < BOARD_HEIGHT; row++) {
if (m_Board[row * BOARD_WIDTH + col] * sign[player] <= 0) check = false;
}
if (check) return player;
}
}
return -1;
}
// 盤表示
void T3EBoard::ShowBoard()
{
for (int i = 0; i < BOARD_SIZE; i++) {
std::cout << (m_Board[i] == 0 ? " " :
(m_Board[i] > 0 ? "○" : "×"));
if (i % BOARD_WIDTH < BOARD_WIDTH - 1) {
std::cout << "│";
}
else {
std::cout << std::endl;
if (i < BOARD_SIZE - 1) std::cout << "─┼─┼─" << std::endl;
}
}
}