色々手を尽くしましたが、自力で解決できないため教えていただければと思い質問いたします。
学習のためhttps://gist.github.com/mia-0032/5325961に掲載されているオセロプログラムをC++に移植しようとしています。
ほぼ作成は完成したものの最初の1手を打った後は全てAIが白黒の両方を打ってゲームが終了してしまいます。プレイヤーチェンジ部分のコード等を何度も確認しましたが、原因が分かりませんでした。
なお、リファクタリングもまだしていないためコードはハードコーディングもあり汚いですが、よろしくお願いいたします。
#include "Board.h"
//初期化処理(ゲームオーバー後の再開があるためコンストラクタに含められない)
void Board::Init()
{
//配列を初期化
for (int y = 0; y < MATRIX_NUM; y++) {
for (int x = 0; x < MATRIX_NUM; x++) {
board.get()[x][y] = 0;
}
}
//最初に置いてある石 board.get()[MATRIX_NUM / 2 - 1][MATRIX_NUM / 2 - 1] = WHITE; board.get()[MATRIX_NUM / 2 - 1][MATRIX_NUM / 2] = BLACK; board.get()[MATRIX_NUM / 2][MATRIX_NUM / 2 - 1] = BLACK; board.get()[MATRIX_NUM / 2][MATRIX_NUM / 2] = WHITE; //先手は黒 player = BLACK; rival = WHITE; //メッセージ初期化 for (auto& a : message) { a = TEXT('\0'); } //現在の石数をカウント CountStones();
}
//石数のカウント
void Board::CountStones()
{
black_count = 0;
white_count = 0;
for (int y = 0; y < MATRIX_NUM; y++) { for (int x = 0; x < MATRIX_NUM; x++) { if (board.get()[x][y] == BLACK) { black_count++; } else if (board.get()[x][y] == WHITE) { white_count++; } } }
}
//石描画メソッド
void Board::DrawStone(const HDC& mhdc, int player, int x, int y)
{
if (player == BLACK) {
HPEN oldPen = (HPEN)SelectObject(mhdc, GetStockObject(NULL_PEN));
HBRUSH brush = CreateSolidBrush(RGB(0x00,0x00,0x00));
HBRUSH oldBrush = (HBRUSH)SelectObject(mhdc, brush);
Ellipse(mhdc, x, y, x + 28, y + 28);
SelectObject(mhdc, oldPen);
SelectObject(mhdc, oldBrush);
DeleteObject(brush);
}
else if (player == WHITE) {
HPEN oldPen = (HPEN)SelectObject(mhdc, GetStockObject(NULL_PEN));
HBRUSH brush = CreateSolidBrush(RGB(0xFF, 0xFF, 0xFF));
HBRUSH oldBrush = (HBRUSH)SelectObject(mhdc, brush);
Ellipse(mhdc, x, y, x + 28, y + 28);
SelectObject(mhdc, oldPen);
SelectObject(mhdc, oldBrush);
DeleteObject(brush);
}
}
void Board::UserStatusDraw(const HDC& mhdc)
{
HPEN pen = CreatePen(PS_SOLID, 1, RGB(0x00, 0x00, 0x00));
HPEN oldPen = (HPEN)SelectObject(mhdc, pen);
HBRUSH oldBrush = (HBRUSH)SelectObject(mhdc, GetStockObject(NULL_BRUSH));
//画面下のプレイヤー部分 Rectangle(mhdc, 260, 220, 290, 250); DrawStone(mhdc, player, 261, 221); wchar_t* turn = TEXT("Turn"); RECT rect; rect.left = 263; rect.top = 235; StringDraw(mhdc, rect, turn, this->player); SelectObject(mhdc, oldPen); SelectObject(mhdc, oldBrush); DeleteObject(pen); //画面上のプレイヤー部分 DrawStone(mhdc, BLACK, 261, 11); wchar_t blackCount[3] = { TEXT('\0') }; wsprintf(blackCount, TEXT("%d"), black_count); rect.left = 269; rect.top = 18; StringDraw(mhdc, rect, blackCount,BLACK); DrawStone(mhdc, WHITE, 261, 71); wchar_t whiteCount[3] = { TEXT('\0') }; wsprintf(whiteCount, TEXT("%d"), white_count); rect.left = 269; rect.top = 78; StringDraw(mhdc, rect, whiteCount, WHITE); if (wcslen(message) > 0) { rect.left = 20; rect.top = 120; rect.right = 240; rect.bottom = 40; HPEN pen = CreatePen(PS_SOLID, 1, RGB(0xFF, 0x00, 0x00)); HPEN oldPen = (HPEN)SelectObject(mhdc, pen); HBRUSH oldBrush = (HBRUSH)SelectObject(mhdc, GetStockObject(WHITE_BRUSH)); Rectangle(mhdc, rect.left, rect.top, rect.right, rect.bottom); SelectObject(mhdc, oldBrush); SelectObject(mhdc, oldPen); DeleteObject(pen); rect.left = 100; rect.top = 75; StringDraw(mhdc, rect, message, 99); }
}
void Board::StringDraw(const HDC& mhdc, RECT& rect, wchar_t* str, int player)
{
if (mhdc == NULL || str == NULL) {
return;
}
HFONT font = CreateFont(12, 0, 0, 0, FW_EXTRALIGHT, FALSE, FALSE, FALSE, SHIFTJIS_CHARSET, OUT_DEFAULT_PRECIS, OUT_DEFAULT_PRECIS, DEFAULT_QUALITY, FIXED_PITCH | FF_ROMAN, NULL); SetBkMode(mhdc, TRANSPARENT); if (player == BLACK) { SetTextColor(mhdc, RGB(0xFF, 0xFF, 0xFF)); } else if (player == WHITE) { SetTextColor(mhdc, RGB(0x00, 0x00, 0x00)); } else { SetTextColor(mhdc, RGB(0x00, 0x00, 0x00)); } SelectObject(mhdc, font); TextOut(mhdc, rect.left, rect.top, str, lstrlen(str)); DeleteObject(font);
}
//指定したマスにそのプレイヤーの石が置かれているか判定
bool Board::Check(int x, int y, int player)
{
//xとyともにMATRIX_NUMの範囲内かつ指定された配列の場所に引数のプレイヤーが格納されている場合
if (x >= 0 && x < MATRIX_NUM && y >= 0 && y < MATRIX_NUM && (board.get()[x][y] == player)) {
return true;
}
else {
return false;
}
}
//今のプレイヤーが打った時に一方向に裏返すことができる石の数
int Board::CountStone(int x, int y, int dx, int dy)
{
int x1 = x + dx;
int y1 = y + dy;
int stone = 0;
while (Check(x1, y1, rival)) { x1 += dx; y1 += dy; stone++; } if (Check(x1, y1, player)) { return stone; } else { return 0; }
}
//今のプレイヤーが打った時に全方向に対して裏返すことができる石の数
int Board::CountStone(int x, int y)
{
int stone = 0;
if (Check(x, y, 0)) {
stone += CountStone(x, y, 1, 0); //右
stone += CountStone(x, y, -1, 0); //左
stone += CountStone(x, y, 0, 1); //下
stone += CountStone(x, y, 0, -1); //上
stone += CountStone(x, y, 1, 1); //右下
stone += CountStone(x, y, 1, -1); //右上
stone += CountStone(x, y, -1, 1); //左下
stone += CountStone(x, y, -1, -1); //左上
}
return stone;
}
bool Board::CanPut()
{
for (int y = 0; y < MATRIX_NUM; y++) {
for (int x = 0; x < MATRIX_NUM; x++) {
if (CountStone(x, y) > 0) {
return true;
}
}
}
return false;
}
//石を置くメソッド(一方向のみ裏返す)
int Board::PutStone(int x, int y, int dx, int dy)
{
int stone = CountStone(x, y, dx, dy);
for (int i = 1; i <= stone; i++) {
board.get()[x + dx * i][y + dy * i] = player;
}
return stone;
}
//石を置くメソッド(全方向について裏返す)
int Board::PutStone(int x, int y)
{
int stone = 0;
if (Check(x, y, 0)) {
stone += PutStone(x, y, 1, 0); // 右
stone += PutStone(x, y, -1, 0); // 左
stone += PutStone(x, y, 0, 1); // 下
stone += PutStone(x, y, 0, -1); // 上
stone += PutStone(x, y, 1, 1); // 右下
stone += PutStone(x, y, 1, -1); // 右上
stone += PutStone(x, y, -1, 1); // 左下
stone += PutStone(x, y, -1, -1); // 左上
if (stone > 0) { board.get()[x][y] = player; stone++; CountStones(); } } return stone;
}
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。