#てくにゃんすいーぱー
siv3d触ってすげえ思ったので、思っただけでは悲しいので、マインスイーパー作りました。
ダウンロードはこちら()
てくにゃん要素はボムだけなんです!こめんなさい。
##操作方法 Rキーでリスタート出来ます。あとは普通のマインスイーパーと同じです。
#include <Siv3D.hpp> | |
//色々だるいしシーケンスグローバル | |
enum class State { | |
TITLE, | |
IN_GAME, | |
GAMEOVER, | |
CLEAR, | |
}; | |
State state = State::IN_GAME; | |
//TODO: セルのクラス化? | |
//反省:[y][x]の記述多すぎ、ミスの原因にもなるので | |
class Board { | |
struct Cell { | |
bool bom; | |
bool open; | |
bool flag; | |
int num;//周りのボム数 | |
}; | |
static const int HEIGHT = 9, WIDTH = 9; | |
static const int SIZE = 30; | |
std::array<std::array<Cell, HEIGHT>, WIDTH> cellState; | |
std::array<std::array<Rect, HEIGHT>, WIDTH> cellRect; | |
Texture bomTexure { L"bom.png" }; | |
Texture flagTexure { L"flag.png" }; | |
Font font {SIZE/2}; | |
const int BOM_NUM = 10; | |
public: | |
Board() { | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
cellRect[y][x].setPos({ x * SIZE, y * SIZE }); | |
cellRect[y][x].setSize({ SIZE, SIZE });//イニシャライザリスト素敵 | |
} | |
} | |
Init(); | |
} | |
void Init() { | |
//初期化ー | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
cellState[y][x].open = false; | |
cellState[y][x].bom = false; | |
cellState[y][x].flag = false; | |
cellState[y][x].num = 0; | |
} | |
} | |
//ボム混ぜるー | |
for (int i = 0; i < BOM_NUM; i++) { | |
int x = Random(0, HEIGHT - 1); | |
int y = Random(0, WIDTH - 1); | |
if (!cellState[y][x].bom) cellState[y][x].bom = true; | |
else i--; | |
} | |
//各マスの周りのボム数カウント | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
cellState[y][x].num = searchBomCnt(x, y); | |
} | |
} | |
} | |
void Move() { | |
int openCnt = 0; | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
if (cellRect[y][x].leftClicked && !cellState[y][x].open && !cellState[y][x].flag) { | |
cellState[y][x].open = true; | |
if (cellState[y][x].num == 0 && !cellState[y][x].bom) autoOpen(x, y); | |
if (cellState[y][x].bom) { | |
state = State::GAMEOVER;//ゲームオーバー | |
//TODO:全てのボム表示 | |
for (int i = 0; i < HEIGHT; i++) for (int j = 0; j < WIDTH; j++) if (cellState[i][j].bom) cellState[i][j].open = true; | |
} | |
} | |
if (cellRect[y][x].rightClicked && !cellState[y][x].open) { | |
if (!cellState[y][x].flag) cellState[y][x].flag = true; | |
else cellState[y][x].flag = false; | |
} | |
if (cellState[y][x].open) openCnt++; | |
} | |
} | |
if (openCnt >= WIDTH * HEIGHT - BOM_NUM) state = State::CLEAR;//クリア | |
} | |
void Draw() { | |
for (int y = 0; y < HEIGHT; y++) { | |
for (int x = 0; x < WIDTH; x++) { | |
if (cellState[y][x].open) { | |
cellRect[y][x].draw(Palette::Black); | |
if (cellState[y][x].bom) { | |
bomTexure.draw(x * SIZE, y * SIZE); | |
} | |
if (cellState[y][x].num > 0) { | |
font.draw(Format(cellState[y][x].num), SIZE * x + 10, SIZE * y); | |
//font.draw(Format(cellState[y][x].bom)); | |
} | |
} else { | |
cellRect[y][x].draw(Palette::Darkgray); | |
cellRect[y][x].drawFrame(1, 0, Palette::Black); | |
if (cellState[y][x].flag) flagTexure.draw(x * SIZE, y * SIZE); | |
} | |
} | |
} | |
} | |
bool onBoard(int x, int y) { | |
if (x < 0 || x >= WIDTH || y < 0 || y >= HEIGHT) return false; | |
return true; | |
} | |
int searchBomCnt(int x, int y) { | |
int cnt = 0; | |
for (int dy = -1; dy < 2; dy++) { | |
for (int dx = -1; dx < 2; dx++) { | |
if (!onBoard(x + dx, y + dy)) continue; | |
if (dy == 0 && dx == 0) continue; | |
if (cellState[y][x].bom) continue; | |
if (cellState[y + dy][x + dx].bom) cnt++; | |
} | |
} | |
return cnt; | |
} | |
void autoOpen(int x, int y) { | |
for (int dy = -1; dy < 2; dy++) { | |
for (int dx = -1; dx < 2; dx++) { | |
if (dy == 0 && dx == 0) continue; | |
int tx = x + dx, ty = y + dy; | |
if (!onBoard(tx, ty)) continue; | |
if (cellState[ty][tx].bom) continue; | |
if (!cellState[ty][tx].open) { | |
cellState[ty][tx].open = true; | |
} else { | |
continue; | |
} | |
if (cellState[ty][tx].num == 0) autoOpen(tx, ty);//再帰的に | |
} | |
} | |
} | |
}; | |
void Main() | |
{ | |
Window::Resize(270, 270); | |
Window::SetTitle(L"てくにゃんすいーぱー"); | |
auto board = std::make_shared<Board>(); | |
Font mes(30); | |
while (System::Update()) { | |
switch (state) { | |
case State::IN_GAME: | |
board->Move(); | |
board->Draw(); | |
break; | |
case State::GAMEOVER: | |
board->Draw(); | |
mes.draw(L"GAMEOVER", { 0, 0 }, Palette::Red); | |
break; | |
case State::CLEAR: | |
board->Draw(); | |
mes.draw(L"CLEAR!", { 0, 0 }, Palette::Green); | |
break; | |
} | |
if (Input::KeyR.clicked) { | |
board->Init(); | |
state = State::IN_GAME; | |
} | |
} | |
} |