void StartThread() { Message msg = new Message(1, 1); Block cur; BlockMaker rng = new BlockMaker(); Random r = new Random(); int hole = r.Next(0, W); Console.ResetColor(); Console.Clear(); DrawOutline1(f.backColor); DrawOutline2(); rng.Init(); UpdateDisplay(); // timeCnt = 0 UpdateDisplay(false, -1); msg.StartCount(); // 게임 스타트 bool wantNext = true; // 다음블럭을 가져올 것인가 bool holdUsed = false; // 게임에서 홀드가 한 번이라도 사용됐는가 (홀드창 블럭 유무) bool canHold = true; // 현재 낙하 사이클에 홀드를 쓸 수 있는가 (연속은 금지됨) bool curHeld = false; // 현재 블록에 대해 홀드를 작동 시켰는가 Block hBlock = new Block(1); // 홀드된 블럭 Block tmp = new Block(1); // cur과 hBlock을 swap하기 위한 임시 객체 bool gameOver = false; bool gameClear = false; nextTimer = 1; while (true) { if (wantNext) { cur = rng.Next(); } else { cur = new Block(tmp.type); } f.Put(f.GetTrans(cur), false); f.Put(cur, false); while (true) // 현재 블록 cur이 놓일 때까지 { Thread A; bool isLockDelay = LockDelay(cur); bool recentMove = false; string recentS = ""; if (isLockDelay) { A = new Thread(LockTimer); lockTimerEnd[nextTimer] = false; } else { A = new Thread(DropTimer); dropTimerEnd[nextTimer] = false; } A.Start(); while ((!isLockDelay && !dropTimerEnd[nextTimer]) || (isLockDelay && !lockTimerEnd[nextTimer])) { // 블록이 한 칸 떨어지기 전 동안 유저의 키 입력에 따른 블록 이동 if (playTimerEnd) { ++timeCnt; UpdateDisplay(); Thread T = new Thread(PlayTimer); playTimerEnd = false; T.Start(); } if (!Console.KeyAvailable) { continue; } ConsoleKeyInfo cki = Console.ReadKey(true); string s = cki.Key.ToString(); if (s == "P") // 일시 정지 { msg.ShowMessage("일시정지", false); while (true) { ConsoleKeyInfo cki2 = Console.ReadKey(true); string s2 = cki2.Key.ToString(); if (s2 == "P") { msg.ShowMessage("일시정지", true); msg.StartCount(); break; } } } else if (s == "Q") // 메뉴로 돌아가기 { return; } else if (s == "C") // 홀드 { if (!canHold) { continue; } canHold = false; curHeld = true; f.Put(hBlock, true); tmp = new Block(hBlock.type); hBlock = new Block(cur.type); hBlock.x = STX - 2 * BSIZE - 2; hBlock.y = STY; f.Put(hBlock, false); if (!holdUsed) { holdUsed = true; wantNext = true; } else { wantNext = false; } break; } else if (s.Contains("Arrow") || s == "Spacebar" || s == "Z" || s == "X") { int prev = cur.y; recentMove = f.BlockMove(ref cur, s); recentS = s; // Lock Delay중 움직였을 때 떨어질 곳이 생기는 경우 if (isLockDelay && !LockDelay(cur)) { break; } // Lock Delay가 아닌 도중 움직인 직후에 Lock Delay가 걸려야 하는 경우 if (!isLockDelay && LockDelay(cur)) { isLockDelay = true; break; } // Lock Delay중 다음 키를 눌렀을 때는 바로 블록이 놓여지게 함 if (s == "Spacebar") { break; } } } nextTimer = nextTimer % MAX + 1; if (!curHeld) { // lockTimer 또는 dropTimer가 다 됨 if (recentS != "Spacebar" && isLockDelay && recentMove) { continue; // Lock Delay 시간 초기화 } int prev = cur.y; f.BlockMove(ref cur, "DownArrow"); if (cur.y == prev) { wantNext = true; canHold = true; break; } } else // 기존에 있던 cur을 필드 state상에서 지우기 { f.Put(cur, true); f.Put(f.GetTrans(cur), true); break; } } // 현재 블록에 대한 처리 완료 // 다음 스폰될 블록이 홀드 블록이라면 게임오버 또는 업데이트 진행x if (curHeld) { curHeld = false; continue; } // 게임오버 검사 gameOver = false; if (f.mode == "어려움" && trashTimerEnd) { if (r.Next(0, 9876) % 13 <= 5) { hole = r.Next(0, W); } bool res = UpdateDisplay(true, hole); if (!res) { gameOver = true; break; } // 게임 오버 trashTimerEnd = false; Thread B = new Thread(TrashTimer); B.Start(); } else { UpdateDisplay(false, -1); for (int i = 0; i < W; ++i) { if (f.state[i, EXTRA - 1] > 0) { gameOver = true; } } if (gameOver) { break; } } // 게임 클리어 검사 (그림없애기 모드만 해당) if (f.mode != "그림없애기") { continue; } gameClear = true; for (int i = 0; i < W; ++i) { for (int j = 0; j < L + EXTRA; ++j) { if (f.state[i, j] == (int)ConsoleColor.Gray) { gameClear = false; } } } if (gameClear) { break; } } // 게임이 terminate 되었음 if (f.mode == "그림없애기" && gameClear) // 게임 클리어 안내 { msg.ShowMessage("게임클리어", false); Thread.Sleep(1000); msg.ShowMessage("▶ 게임클리어(Spacebar/Enter로 진행)", false); MyFunction.WaitForExit(); RecordManager rm = new RecordManager(GAMENAME); rm.UpdateRecord(f.mapName, "시간", timeCnt, true); } else // 게임 오버 안내 { msg.ShowMessage("게임오버", false); Thread.Sleep(1000); msg.ShowMessage("▶ 게임오버(Spacebar/Enter로 진행)", false); MyFunction.WaitForExit(); if (f.mode == "그림없애기") { return; } RecordManager rm = new RecordManager(GAMENAME); rm.UpdateRecord(f.mode, "점수", (int)f.score, false); } }
void Awake() { instance = this; }