今度はシーンごとに分けてプログラムを書きたいのですが、
SceneManager.cpp内のChangeScene()の中で
Me_PutPice(board_y, board_x, turn);とAI_PutPice(board_y, board_x, turn);
の扱いに困っています。
外部ファイルのグロ-バル変数を参照するためにextern宣言をしているのですがこの変数の定義が
Game.cpp内の初期化関数にあるのでうまくいってないのだと思っています。
今行いたい処理は、前回質問した通りのプログラムが動いてくれればいいのですが、このシーンを管理する処理でつまずいています。
そもそもファイルの分け方がこれでいいのかすらわかっていません・・・
わかりにくい質問になってしまったのでわかりずらいところは指摘を入れてもらいながらの
返信をお待ちしております。
前回の質問
http://dixq.net/forum/viewtopic.php?f=3&t=19439
※なぜかファイルの添付がうまくいかなかったのでベタ打ちです、すみません。
※main関数には Init_First(),メインループにはChangeScene()のみです
※ヘッダーファイルには関数のプロトタイプ宣言のみしてあります
※コンパイラーはvisualstudio2017,です。
//Game.cpp
#include "DxLib.h"
#include "Input.h"
#include "Game.h"
//確定的な値
const int SCREEN_WIDIH = 840;
const int SCREEN_HEIGHT = 640;
const int vec_y[] = { -1,-1,0,1,1,1,0,-1 };
const int vec_x[] = { 0,1,1,1,0,-1,-1,-1 };
//途中で変更する可能性のある値
extern enum GameData
{
Me = 0, //自分のターン
You = 1, //相手のターン
End = 2, //終了
EMPTY = 0, //空きマス
BLACK = 1, //黒コマ
WHITE = 2, //白コマ
BOARDSIZE = 8, //ボードの大きさ,8 * 8
CELLSIZE = 80, //マス一つ分の大きさ
CURSOR_MAX = 480 //カーソルの移動できる最大値
};
//ゲーム情報
struct Obj
{
int Handle, //画像データ格納用
x, //カーソル用
y,
num; //コマを数を格納
};
Obj BoardGraph;
Obj Black;
Obj White;
Obj cursor;
int board_x;
int board_y;
int turn;
int Board[BOARDSIZE][BOARDSIZE];
//画像の初期化
void Init_Graph()
{
BoardGraph.Handle = LoadGraph("Graph/ボード.bmp");
cursor.Handle = LoadGraph("Graph/カーソル.png");
Black.Handle = LoadGraph("Graph/黒.png");
White.Handle = LoadGraph("Graph/白.png");
}
//ゲーム情報の初期化
void Init_Game()
{
turn = Me; //ターン、0は黒が先手
board_x = BOARDSIZE,
board_y = BOARDSIZE;
Black.num = 0;
White.num = 0;
cursor.x = 0;
cursor.y = 0;
}
//ボードの初期化
void Init_Board()
{
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
Board[y][x] = EMPTY;
}
}
Board[BOARDSIZE / 2 - 1][BOARDSIZE / 2] = BLACK; //[3][4]
Board[BOARDSIZE / 2][BOARDSIZE / 2 - 1] = BLACK; //[4][3]
Board[BOARDSIZE / 2][BOARDSIZE / 2] = WHITE; //[4][4]
Board[BOARDSIZE / 2 - 1][BOARDSIZE / 2 - 1] = WHITE; //[3][3]
}
//カーソルの移動
void Updata_cursor()
{
if (Key(KEY_INPUT_RIGHT) == 1 && cursor.x <= CURSOR_MAX)
{
cursor.x += CELLSIZE;
}
if (Key(KEY_INPUT_LEFT) == 1 && cursor.x > 0)
{
cursor.x -= CELLSIZE;
}
if (Key(KEY_INPUT_UP) == 1 && cursor.y > 0)
{
cursor.y -= CELLSIZE;
}
if (Key(KEY_INPUT_DOWN) == 1 && cursor.y <= CURSOR_MAX)
{
cursor.y += CELLSIZE;
}
}
//vecで指定された向きについてひっくり返るコマがあるか確認する(8方向のチェック)
int CheckFlip(int y, int x, int turn, int vec) //確認出来たらTRUEを返す(ひっくり返せるコマがある)
{
int flag = FALSE;
while (TRUE)
{
//8方向の走査
y += vec_y[vec];
x += vec_x[vec];
//盤面の外に出ていたら終了
if (x < 0 || y < 0 || x > BOARDSIZE - 1 || y > BOARDSIZE - 1)
{
return FALSE;
}
//空きマスだったら終了
if (Board[y][x] == EMPTY)
{
return FALSE;
}
//相手のコマがあったらフラグを立てる
if (Board[y][x] == (turn ? BLACK : WHITE))
{
flag = TRUE;
}
//自分のコマがあった場合にフラグが立っていれば置ける
if (Board[y][x] == (turn ? WHITE : BLACK))
{
if (flag == TRUE)
{
return TRUE;
}
//置けない
else
{
return FALSE;
}
}
}
return TRUE;
}
//その場所に置くことができるかを確認
int PutCheck(int y, int x, int turn) //置ければTRUEを返す
{
int vec;
//どれか1方向でもひっくり返せるか確認
for (vec = 0; vec < 8; ++vec)
{
if (CheckFlip(y, x, turn, vec) == TRUE)
{
return TRUE; //ひっくり返せる
}
}
return FALSE;
}
//実際に裏返す処理
void Flip(int y, int x, int turn, int vec)
{
while (1)
{
y += vec_y[vec];
x += vec_x[vec];
//自分のコマがあったら終了
if (Board[y][x] == (turn ? WHITE : BLACK))
{
break;
}
//それ以外なら自分のコマで塗りつぶす
Board[y][x] = (turn ? WHITE : BLACK);
}
}
//入力を受けて裏返せるか確かめる関数
int Put(int y, int x, int turn)
{
int vec,
flag = FALSE;
//空きマスでなければ終了
if (Board[y][x] != EMPTY)
{
return FALSE;
}
//全方向について確認
for (vec = 0; vec < BOARDSIZE; ++vec)
{
if (CheckFlip(y, x, turn, vec) == TRUE)
{
//裏返す
Flip(y, x, turn, vec);
flag = TRUE;
}
}
if (flag == TRUE)
{
//この場所にコマを置く
Board[y][x] = (turn ? WHITE : BLACK);
return TRUE;
}
return FALSE;
}
//終了判定(ターンチェンジ)
int CheckEnd(int turn)
{
//置ける場所があるか確認
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
//あれば続行しターンチェンジ
if (Board[y][x] == EMPTY && PutCheck(y, x, turn) == TRUE)
{
return (turn == Me ? Me : You);
}
}
}
//場所がなかったので交替して探す
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
//あればpassして続行
if (Board[y][x] == EMPTY && PutCheck(y, x, turn) == TRUE)
{
return (turn == Me ? Me : You);
}
}
}
//なかったのでゲーム終了
return End;
}
//コマを置く処理
void Me_PutPice(int by, int bx, int &turn)
{
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
if (Key(KEY_INPUT_Z) == 1 && CELLSIZE * x == cursor.x && CELLSIZE * y == cursor.y && turn == Me)
{
if (Put(y, x, turn) == 1)
{
Board[by][bx] = BLACK;
turn = You;
}
}
}
}
}
//CPU,置ける所に適当に置く
void AI_PutPice(int by, int bx, int &turn)
{
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
if (Key(KEY_INPUT_X) == 1 && turn == You)
{
if (Put(y, x, turn) == 1)
{
Board[by][bx] = WHITE;
turn = Me;
}
}
}
}
}
//勝敗判定とその時の表示
void CheckWinner()
{
//コマを数え上げる
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
switch (Board[y][x])
{
case BLACK:
++Black.num;
break;
case WHITE:
++White.num;
break;
}
}
}
if (Black.num > White.num)
{
DrawFormatString(680, 100, GetColor(255, 255, 255), "黒の勝ちです");
}
else if (Black.num < White.num)
{
DrawFormatString(680, 100, GetColor(255, 255, 255), "白の勝ちです");
}
else
{
DrawFormatString(680, 100, GetColor(255, 255, 255), "引き分けです");
}
}
//ゲーム情報の表示
void Draw_Game()
{
//盤面
DrawGraph(0, 0, BoardGraph.Handle, false);
//文字
if (turn == Me)
{
DrawFormatString(680, 50, GetColor(255, 255, 255), "黒のターン");
}
if (turn == You)
{
DrawFormatString(680, 50, GetColor(255, 255, 255), "黒のターン");
DrawFormatString(680, 70, GetColor(255, 255, 255), "Xキーで置きます");
}
//コマ
for (int y = 0; y < BOARDSIZE; ++y)
{
for (int x = 0; x < BOARDSIZE; ++x)
{
//ボードの情報がWHITEなら白コマが置かれる
if (Board[y][x] == WHITE)
{
DrawGraph(CELLSIZE * x, CELLSIZE * y, White.Handle, true);
}
//ボードの情報がBLACKなら黒コマが置かれる
if (Board[y][x] == BLACK)
{
DrawGraph(CELLSIZE * x, CELLSIZE * y, Black.Handle, true);
}
}
}
//グリッド線を引く
for (int x = 0; x < 9; ++x)
{
//縦線
DrawLineAA((float)CELLSIZE * x, 0.f, (float)CELLSIZE * x, (float)SCREEN_HEIGHT, GetColor(0, 0, 0), 1.4f);
}
for (int y = 0; y < 9; ++y)
{
//横線
DrawLineAA(0.f, (float)CELLSIZE * y, (float)SCREEN_HEIGHT, (float)CELLSIZE * y, GetColor(0 ,0 ,0), 1.4f);
}
//カーソルの表示
DrawGraph(cursor.x, cursor.y, cursor.Handle, true);
}
//SceneManager.cpp内
#include "DxLib.h"
#include "Input.h"
#include "Game.h"
#include "SceneManager.h"
enum GameData
{
End = 2, //終了
};
enum Scene
{
//あとから追加
Game,
};Scene scene;
extern int board_y;
extern int board_x;
extern int turn;
//初回起動時のみ実行
void Init_First()
{
Init_Graph();
Init_Board();
Init_Game();
}
//シーン管理
void ChangeScene()
{
switch (scene)
{
case Game:
Updata_Key(); //キー入力を有効にする
Updata_cursor();
Me_PutPice(board_y, board_x, turn);
AI_PutPice(board_y, board_x, turn);
turn = CheckEnd(turn);
switch (turn)
{
case End:
CheckWinner();
break;
}
Draw_Game();
break;
}
}