実現したいこと
ボタンを右クリックでパズルが自動で組んでくれるようなものを作る
プログラムを書いてエラーもないのですがうまく動いてくれません。
原因がわかる方いましたら教えていただきたいです。
- ▲▲機能を動作するようにする
前提
ここに質問の内容を詳しく書いてください。
(例)
cppで上のようなシステムを作っています
エラーはないのですがうまくパズルしてくれません。
発生している問題・エラーメッセージ
エラーメッセージ
該当のソースコード
#include "DxLib.h"
#include <windows.h>
#include <direct.h>
#include <shlwapi.h>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <functional>
#include <thread>
// グローバル変数
int pics[16];
int pic_all;
int panel[16];
enum Status { TITLE, MAIN, CLEAR };
Status status = TITLE;
struct State {
int panel[16];
int spaceIndex;
int cost;
std::vector<int> moves;
State() : panel{ 0 }, spaceIndex(0), cost(0), moves() {}
};
void solvePuzzle();
void asyncSolvePuzzle() {
std::thread solver(solvePuzzle);
solver.detach();
}
bool operator<(const State& a, const State& b) {
return a.cost > b.cost;
}
// マンハッタン距離を計算する
int manhattanDistance(int index, int value) {
int x1 = index % 4;
int y1 = index / 4;
int x2 = value % 4;
int y2 = value / 4;
return abs(x1 - x2) + abs(y1 - y2);
}
// 現在の状態のコストを計算する
int calculateCost(const State& state) {
int cost = 0;
for (int i = 0; i < 16; i++) {
if (state.panel[i] != 15) {
cost += manhattanDistance(i, state.panel[i]);
}
}
return cost;
}
// 選択したパネルと空白を入れ替える
void change(int x, int y) {
int p1 = y * 4 + x;
int p2 = -1;
if (x > 0 && panel[p1 - 1] == 15) p2 = p1 - 1;
if (x < 3 && panel[p1 + 1] == 15) p2 = p1 + 1;
if (y > 0 && panel[p1 - 4] == 15) p2 = p1 - 4;
if (y < 3 && panel[p1 + 4] == 15) p2 = p1 + 4;
if (p2 != -1) {
panel[p2] = panel[p1];
panel[p1] = 15;
}
}
// 自動でパズルを解く
void solvePuzzle() {
State initialState;
for (int i = 0; i < 16; i++) {
initialState.panel[i] = panel[i];
if (panel[i] == 15) {
initialState.spaceIndex = i;
}
}
initialState.cost = calculateCost(initialState);
std::priority_queue<State> openList; openList.push(initialState); std::vector<int> dx = { -1, 1, 0, 0 }; std::vector<int> dy = { 0, 0, -1, 1 }; while (!openList.empty()) { State current = openList.top(); openList.pop(); if (current.cost == 0) { for (int move : current.moves) { int x = current.spaceIndex % 4; int y = current.spaceIndex / 4; int newX = x + dx[move]; int newY = y + dy[move]; change(newX, newY); current.spaceIndex = newY * 4 + newX; Sleep(500); // 一つずつ動かすための待機時間 } break; } for (int move = 0; move < 4; move++) { int x = current.spaceIndex % 4; int y = current.spaceIndex / 4; int newX = x + dx[move]; int newY = y + dy[move]; if (newX >= 0 && newX < 4 && newY >= 0 && newY < 4) { State next = current; next.spaceIndex = newY * 4 + newX; next.panel[current.spaceIndex] = next.panel[next.spaceIndex]; next.panel[next.spaceIndex] = 15; next.cost = calculateCost(next); next.moves.push_back(move); openList.push(next); } } }
}
// タイトル画面
void gameTitle() {
if (GetMouseInput() & MOUSE_INPUT_LEFT) {
// 初期パネルのシャッフル
for (int i = 0; i < 16; i++) panel[i] = i;
for (int i = 0; i < 1000; i++) {
change(GetRand(3), GetRand(3));
}
status = MAIN;
}
DrawGraph(0, 0, pic_all, FALSE);
DrawString(102, 142, "CLICK TO START", GetColor(255, 0, 0));
}
// メイン画面
void gameMain() {
int mouseInput = GetMouseInput(); if (mouseInput & MOUSE_INPUT_LEFT) { int x, y; GetMousePoint(&x, &y); change(x / 80, y / 80); // パネルが全部揃ったか判定 bool clear = true; for (int i = 0; i < 16; i++) { if (panel[i] != i) clear = false; } if (clear) status = CLEAR; } else if (mouseInput & MOUSE_INPUT_RIGHT) { static bool solving = false; if (!solving) { solving = true; asyncSolvePuzzle(); solving = false; } } // パネルの描画 for (int i = 0; i < 16; i++) { if (panel[i] < 15) { DrawGraph((i % 4) * 80, (i / 4) * 80, pics[panel[i]], FALSE); } }
}
// 終了画面
void gameClear() {
DrawGraph(0, 0, pic_all, FALSE);
DrawString(115, 142, "GAME CLEAR!", GetColor(255, 0, 0));
}
int WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) {
SetGraphMode(320, 320, 32);
ChangeWindowMode(TRUE);
DxLib_Init();
SetDrawScreen(DX_SCREEN_BACK);
LoadDivGraph(".\pic.png", 16, 4, 4, 80, 80, pics);
pic_all = LoadGraph(".\pic.png");
while (!ProcessMessage()) { ClearDrawScreen(); switch (status) {
case TITLE: gameTitle(); break;
case MAIN: gameMain(); break;
case CLEAR: gameClear(); break;
}
ScreenFlip();
}
DxLib_End();
return 0;
}
cpp
ソースコード
### 試したこと 上のプログラムを作りました。 ### 補足情報(FW/ツールのバージョンなど) ここにより詳細な情報を記載してください。