Skip to content

Instantly share code, notes, and snippets.

@keidaroo
Created November 17, 2018 15:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save keidaroo/9ca902ac754260fd0a781c744dfe1289 to your computer and use it in GitHub Desktop.
Save keidaroo/9ca902ac754260fd0a781c744dfe1289 to your computer and use it in GitHub Desktop.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
/*
RULE
map {
0 -> nothing
1 -> wall
2 -> goal
マップの上に行くほど添え字は小さく
upx ->指定した方向に動くブロック
downx -> 指定した方向と逆に動くブロック
}
*/
[DefaultExecutionOrder (-3)]
public class automaticgenerator : MonoBehaviour {
//------------------変数-------------------------//
public int[, ] map = new int[50, 50]; //x座標、y座標
bool[, ] confirmedBlock = new bool[50, 50]; //通ることが確定したブロック
public int upX, upY;
public int downX, downY;
public int atLeastWallNum;
public int edgeLength; //一辺の長
public int rotateNumLimit;
public int startUpX, startDownX, startUpY, startDownY;
int cnt = 0;
public int previous = 0; //0は下向き、1は右向き、2は下向き、3は左向き
//-------------------------------------------------//
// Use this for initialization
public bool isCompeteMode;
public bool isTutorialMode;
public string mapCode;
bool isSafeToConfirm (int y, int x, int range, int movex, int movey) {
for (int i = 0; i < range; i++) //ゴールにたどり着くまで
{
if (map[y + movey, x + movex] == 1 && confirmedBlock[y + movey, x + movex] == true) {
return false;
}
x += movex;
y += movey;
}
for (int i = 0; i < range; i++) {
map[y, x] = 0;
confirmedBlock[y, x] = true;
x -= movex;
y -= movey;
}
return true;
}
struct PairWithDirection {
public int x, y, beforeDirection, count;
public string beforePos;
};
PairWithDirection moveToWall (int dir, PairWithDirection now) {
int[] xy = { 0, 1, 0, -1, 0 };
while (true) {
if (map[now.y + xy[dir + 1], now.x + xy[dir]] != 1) {
now.x += xy[dir];
now.y += xy[dir + 1];
} else {
return now;
}
}
}
int conv (PairWithDirection toRed, PairWithDirection toBlue) {
string visCheck = '1' + toRed.x.ToString ().PadLeft (2, '0') + toRed.y.ToString ().PadLeft (2, '0') + toBlue.x.ToString ().PadLeft (2, '0') + toBlue.y.ToString ().PadLeft (2, '0');
return int.Parse (visCheck);
}
public Dictionary<int, int> vis = new Dictionary<int, int> ();
int CountToGoal (PairWithDirection startBlue, PairWithDirection startRed) {
var blueQueue = new Queue<PairWithDirection> ();
var redQueue = new Queue<PairWithDirection> ();
blueQueue.Enqueue (startBlue);
redQueue.Enqueue (startRed);
int finalCnt = -1;
while (blueQueue.Count > 0) {
PairWithDirection blue = blueQueue.Dequeue ();
PairWithDirection red = redQueue.Dequeue ();
if (map[blue.y, blue.x] == 2 && map[red.y, red.x] == 2) {
finalCnt = blue.count;
break;
}
for (int toDirection = 0; toDirection < 4; toDirection++) {
if (red.beforeDirection == toDirection) {
continue;
}
var toRed = moveToWall (toDirection, red);
var toBlue = moveToWall ((toDirection + 2) % 4, blue);
string visCheck = '1' + toRed.x.ToString ().PadLeft (2, '0') + toRed.y.ToString ().PadLeft (2, '0') + toBlue.x.ToString ().PadLeft (2, '0') + toBlue.y.ToString ().PadLeft (2, '0');
if (vis.ContainsKey (int.Parse (visCheck))) { continue; }
vis.Add (int.Parse (visCheck), conv (red, blue));
visCheck = '1' + toBlue.x.ToString ().PadLeft (2, '0') + toBlue.y.ToString ().PadLeft (2, '0') + toRed.x.ToString ().PadLeft (2, '0') + toRed.y.ToString ().PadLeft (2, '0');
vis.Add (int.Parse (visCheck), conv (blue, red));
toRed.beforeDirection = toBlue.beforeDirection = (toDirection + 2) % 4;
toRed.count = toBlue.count = toRed.count + 1;
blueQueue.Enqueue (toBlue);
redQueue.Enqueue (toRed);
}
}
return finalCnt;
}
void Awake () {
Application.targetFrameRate = 60; //60FPSに設定
if (isCompeteMode || isTutorialMode) {
map = GetComponent<codevisualizer> ().Lockoff (mapCode);
Debug.Log (map[0, 0]);
return;
}
int difficulty = GameObject.Find ("pointsText").GetComponent<data> ().difficulty;
if (difficulty == 0) {
upX = 7;
upY = 3;
downX = 5;
downY = 5;
atLeastWallNum = 10;
edgeLength = 10;
rotateNumLimit = 10;
} else if (difficulty == 1) {
upX = 9;
upY = 7;
downX = 7;
downY = 9;
atLeastWallNum = 40;
edgeLength = 16;
rotateNumLimit = 40;
} else if (difficulty == 2) {
upX = 13;
upY = 11;
downX = 11;
downY = 13;
atLeastWallNum = 80;
edgeLength = 24;
rotateNumLimit = 114514;
} else if (difficulty == 3) {
upX = 11;
upY = 9;
downX = 9;
downY = 11;
atLeastWallNum = 60;
edgeLength = 20;
rotateNumLimit = 114514;
}
map[downX, downY] = 0;
map[upX, upY] = 0;
startDownX = downX;
startDownY = downY;
startUpX = upX;
startUpY = upY;
//初期化
for (int i = 0; i <= edgeLength; i++) {
for (int j = 0; j <= edgeLength; j++) {
confirmedBlock[i, j] = false;
map[i, j] = 0;
}
}
//初期のブロックの位置の上下にブロックを置く
for (int i = 0; i < 3; i++) //down
{
map[upY - 1, upX - 1 + i] = 1;
confirmedBlock[upY - 1, upX - 1 + i] = true;
}
for (int i = 0; i < 3; i++) //up
{
map[downY + 1, downX - 1 + i] = 1;
confirmedBlock[downY + 1, downX - 1 + i] = true;
}
for (int i = 0; i <= edgeLength; i++) {
map[0, i] = 1;
map[i, 0] = 1;
map[edgeLength, i] = 1;
map[i, edgeLength] = 1;
confirmedBlock[0, i] = true;
confirmedBlock[i, 0] = true;
confirmedBlock[edgeLength, i] = true;
confirmedBlock[i, edgeLength] = true;
}
for (int rotateNum = 0; rotateNum < rotateNumLimit; rotateNum++) {
int direction, range = 0, downrange = 0;
//重力通りに動く玉から
while (true) {
cnt++;
if (cnt > 9990) { break; }
//0は下向き、1は右向き、2は上向き、3は左向き
direction = Random.Range (0, 4);
if (direction == previous) { continue; }
if (direction == (previous + 2) % 4) { continue; }
if (direction == 0) //した
{
range = Random.Range (0, edgeLength - 1 - upY); //壁を作る一歩手前で止まる
if (range % 2 == 1) { continue; } //もし距離が奇数なら
bool flag = false;
for (int i = 0; i < 3; i++) {
if (map[upY + range + 1, upX - 1 + i] == 0 && confirmedBlock[upY + range + 1, upX - 1 + i] == true) {
flag = true;
break;
} //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (upY, upX, range, 0, 1)) { continue; }
for (int i = 0; i < 3; i++) {
map[upY + range + 1, upX - 1 + i] = 1; //三マス塗る!
confirmedBlock[upY + range + 1, upX - 1 + i] = true;
}
//----------------------------------------------//
upY += range; //
int count2 = 0;
while (true) //
{
count2++;
if (count2 > 9999) { break; }
downrange = Random.Range (0, downY);
if (downrange % 2 == 1) { continue; }
flag = false;
for (int i = 0; i < 3; i++) {
if (map[downY - downrange - 1, downX - 1 + i] == 0 && confirmedBlock[downY - downrange - 1, downX - 1 + i] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (downY, downX, downrange, 0, -1)) { continue; }
for (int i = 0; i < 3; i++) {
map[downY - downrange - 1, downX - 1 + i] = 1;
confirmedBlock[downY - downrange - 1, downX - 1 + i] = true;
}
break;
}
//----------------------------------------------//
downY -= downrange;
}
if (direction == 1) {
range = Random.Range (0, edgeLength - 1 - upX);
if (range % 2 == 1) { continue; }
bool flag = false;
for (int i = 0; i < 3; i++) {
if (map[upY - 1 + i, upX + range + 1] == 0 && confirmedBlock[upY - 1 + i, upX + range + 1] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (upY, upX, range, 1, 0)) { continue; }
for (int i = 0; i < 3; i++) {
map[upY - 1 + i, upX + range + 1] = 1;
confirmedBlock[upY - 1 + i, upX + range + 1] = true;
}
//----------------------------------------------//
upX += range;
int count2 = 0;
while (true) {
count2++;
if (count2 > 9999) { break; }
downrange = Random.Range (0, downX);
if (downrange % 2 == 1) { continue; }
flag = false;
for (int i = 0; i < 3; i++) {
if (map[downY - 1 + i, downX - downrange - 1] == 0 && confirmedBlock[downY - 1 + i, downX - downrange - 1] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (downY, downX, downrange, -1, 0)) { continue; }
for (int i = 0; i < 3; i++) {
map[downY - 1 + i, downX - downrange - 1] = 1;
confirmedBlock[downY - 1 + i, downX - downrange - 1] = true;
}
break;
}
//----------------------------------------------//
downX -= downrange;
}
if (direction == 2) //上
{
range = Random.Range (0, upY);
if (range % 2 == 1) { continue; }
bool flag = false;
for (int i = 0; i < 3; i++) {
if (map[upY - range - 1, upX - 1 + i] == 0 && confirmedBlock[upY - range - 1, upX - 1 + i] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (upY, upX, range, 0, -1)) { continue; }
for (int i = 0; i < 3; i++) {
map[upY - range - 1, upX - 1 + i] = 1;
confirmedBlock[upY - range - 1, upX - 1 + i] = true;
}
//----------------------------------------------//
upY -= range;
int count2 = 0;
while (true) {
count2++;
if (count2 > 9999) { break; }
downrange = Random.Range (0, edgeLength - 1 - downY); //壁を作る一歩手前で止まる
if (downrange % 2 == 1) { continue; } //もし距離が奇数なら
flag = false;
for (int i = 0; i < 3; i++) {
if (map[downY + downrange + 1, downX - 1 + i] == 0 && confirmedBlock[downY + downrange + 1, downX - 1 + i] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (downY, downX, downrange, 0, 1)) { continue; }
for (int i = 0; i < 3; i++) {
map[downY + downrange + 1, downX - 1 + i] = 1; //三マス塗る!
confirmedBlock[downY + downrange + 1, downX - 1 + i] = true; //
}
break;
}
downY += downrange;
}
if (direction == 3) {
range = Random.Range (0, upX);
if (range % 2 == 1) { continue; }
bool flag = false;
for (int i = 0; i < 3; i++) {
if (map[upY - 1 + i, upX - range - 1] == 0 && confirmedBlock[upY - 1 + i, upX - range - 1] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (upY, upX, range, -1, 0)) { continue; }
for (int i = 0; i < 3; i++) {
map[upY - 1 + i, upX - range - 1] = 1;
confirmedBlock[upY - 1 + i, upX - range - 1] = true;
}
//----------------------------------------------//
upX -= range;
int count2 = 0;
while (true) {
count2++;
if (count2 > 9999) { break; }
downrange = Random.Range (0, edgeLength - 1 - downX);
if (downrange % 2 == 1) { continue; }
flag = false;
for (int i = 0; i < 3; i++) {
if (map[downY - 1 + i, downX + downrange + 1] == 0 && confirmedBlock[downY - 1 + i, downX + downrange + 1] == true) { flag = true; break; } //三マス確認
}
if (flag) { continue; }
if (!isSafeToConfirm (downY, downX, downrange, 1, 0)) { continue; }
for (int i = 0; i < 3; i++) {
map[downY - 1 + i, downX + downrange + 1] = 1;
confirmedBlock[downY - 1 + i, downX + downrange + 1] = true;
}
break;
}
downX += downrange;
}
previous = direction;
break;
}
}
string scenename = SceneManager.GetActiveScene ().name;
if (upX == startUpX && upY == startUpY) { SceneManager.LoadScene (scenename); }
if (upX == startDownX && upY == startDownY) { SceneManager.LoadScene (scenename); }
if (downX == startUpX && downY == startUpY) { SceneManager.LoadScene (scenename); }
if (downX == startDownX && downY == startDownY) { SceneManager.LoadScene (scenename); }
confirmedBlock[startUpY, startUpX] = true;
confirmedBlock[startDownY, startDownX] = true;
int pikuto = 0;
for (int i = 1; i < edgeLength; i++) {
for (int j = 1; j < edgeLength; j++) {
if (map[i, j] == 1) { pikuto++; }
}
}
if (pikuto < atLeastWallNum) { SceneManager.LoadScene (scenename); }
map[upY, upX] = 2;
map[downY, downX] = 2;
PairWithDirection a = new PairWithDirection (), b = new PairWithDirection ();
a.x = startUpX;
a.y = startUpY;
b.x = startDownX;
b.y = startDownY;
b.beforeDirection = -1;
int countGoal = CountToGoal (a, b);
Debug.Log (countGoal);
if (difficulty == 0 && countGoal <= 1) {
SceneManager.LoadScene (scenename);
} else if (difficulty == 1 && countGoal <= 3) {
SceneManager.LoadScene (scenename);
} else if (difficulty == 3 && countGoal <= 4) {
SceneManager.LoadScene (scenename);
} else if (difficulty == 2 && countGoa l <= 4) {
SceneManager.LoadScene (scenename);
}
var movetheball = GameObject.Find ("playerObjectUp").GetComponent<movePlayer> ();
movetheball.goaldownX = downX;
movetheball.goaldownY = downY;
movetheball.goalupX = upX;
movetheball.goalupY = upY;
if (SceneManager.GetActiveScene ().name == "bot") {
GameObject.Find ("pointsText").GetComponent<data> ().botGameClear ();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment