Skip to content

Instantly share code, notes, and snippets.

@MikuroXina
Last active August 29, 2019 10:34
Show Gist options
  • Select an option

  • Save MikuroXina/a78132b2dd933c2df1b83be7123e0ccb to your computer and use it in GitHub Desktop.

Select an option

Save MikuroXina/a78132b2dd933c2df1b83be7123e0ccb to your computer and use it in GitHub Desktop.
using System;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
class Cell {
public enum State {
None,
Mine,
}
State state;
public bool Opened { get; private set; }
public bool Flagged { get; private set; }
public int Count = 0;
public Cell(bool isMine) {
state = isMine ? State.Mine : State.None;
Opened = false;
Flagged = false;
}
public bool OpenWhetherMine() {
Opened = true;
Flagged = false;
if (state == State.Mine) {
return true;
}
return false;
}
public void ToggleFlag() {
if (Opened) { return; }
Flagged = !Flagged;
}
public override String ToString() {
if (Opened) {
if (state == State.Mine) {
return "!";
}
if (0 < Count) {
return Count.ToString();
}
return " ";
} else if (Flagged) {
return "F";
}
return "?";
}
}
class Game {
enum State {
BeforeGame,
Playing,
AfterGame,
}
State state;
Action onClear;
Action onGameOver;
bool[, ] cellsWhetherMine;
public Cell[, ] Cells { get; }
public Game(int width, int height,
Action clear, Action gameOver) {
state = State.BeforeGame;
Cells = new Cell[width, height];
onClear = clear;
onGameOver = gameOver;
var gen = new Random();
cellsWhetherMine = new bool[width, height];
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
var isMine = gen.Next(6) == 1;
Cells[x, y] = new Cell(isMine);
cellsWhetherMine[x, y] = isMine;
}
}
(int, int) [] offsets = {
(-1, -1),
(-1, 0),
(-1, 1),
(0, -1),
(0, 1),
(1, -1),
(1, 0),
(1, 1)
};
for (int y = 0; y < height; ++y) {
for (int x = 0; x < width; ++x) {
var countAroundMines = 0;
foreach (var(offestX, offsetY) in offsets) {
if (!(0 <= x + offestX && x + offestX < width && 0 <= y + offsetY && y + offsetY < height)) { continue; }
if (cellsWhetherMine[x + offestX, y + offsetY]) {
++countAroundMines;
}
}
Cells[x, y].Count = countAroundMines;
}
}
}
void CheckIfCleared() {
for (int y = 0; y < Cells.GetLength(1); ++y) {
for (int x = 0; x < Cells.GetLength(0); ++x) {
if (Cells[x, y].Flagged && !cellsWhetherMine[x, y] || !Cells[x, y].Flagged && cellsWhetherMine[x, y]) { return; }
}
}
state = State.AfterGame;
onClear();
}
public void Start() {
if (state != State.BeforeGame) { return; }
state = State.Playing;
}
public void OpenCell(int x, int y) {
if (!(0 <= x && x < Cells.GetLength(0) && 0 <= y && y < Cells.GetLength(1))) { return; }
if (state != State.Playing || Cells[x, y].Flagged || Cells[x, y].Opened) { return; }
if (Cells[x, y].OpenWhetherMine()) {
state = State.AfterGame;
onGameOver();
return;
}
if (Cells[x, y].Count == 0) {
OpenCell(x - 1, y);
OpenCell(x, y - 1);
OpenCell(x - 1, y - 1);
OpenCell(x + 1, y);
OpenCell(x, y + 1);
OpenCell(x + 1, y + 1);
OpenCell(x + 1, y - 1);
OpenCell(x - 1, y + 1);
}
}
public void FlagCell(int x, int y) {
if (!(0 <= x && x < Cells.GetLength(0) && 0 <= y && y < Cells.GetLength(1))) { return; }
if (state != State.Playing) { return; }
Cells[x, y].ToggleFlag();
CheckIfCleared();
}
}
class GameView {
enum Mode {
Flag,
Open,
}
Mode mode;
Game game;
Stopwatch sw;
bool playing = true;
public GameView() {
game = new Game(10, 10, this.Clear, this.GameOver);
mode = Mode.Open;
sw = new Stopwatch();
}
void Clear() {
sw.Stop();
FlushScreen();
var ts = sw.Elapsed;
Console.WriteLine("クリア! {0:00}:{1:00}", ts.Minutes, ts.Seconds);
playing = false;
}
void GameOver() {
sw.Stop();
FlushScreen();
Console.WriteLine("ゲームオーバー……");
playing = false;
}
void StartGame() {
game.Start();
sw.Start();
}
void AskCommand() {
Console.WriteLine("コマンドを入力してね | F/f - フラグ立てモード | T/t - マス開けモード | 数字,数字 - 座標に今のモードを実行");
string command = Console.ReadLine();
if (command == "f" || command == "F") {
mode = Mode.Flag;
return;
} else if (command == "T" || command == "t") {
mode = Mode.Open;
return;
}
var match = Regex.Match(command, @"(?<x>\d+).*,.*(?<y>\d+)");
if (match.Success) {
try {
var x = int.Parse(match.Groups["x"].Value);
var y = int.Parse(match.Groups["y"].Value);
if (mode == Mode.Flag) {
game.FlagCell(x, y);
} else {
game.OpenCell(x, y);
}
} catch (FormatException ignore) { }
}
}
void FlushScreen() {
Console.Clear();
var cells = game.Cells;
var line = " " + string.Concat(Enumerable.Repeat("-", cells.GetLength(0) * 4 + 1));
Console.Write(" ");
for (int x = 0; x < cells.GetLength(0); ++x) {
Console.Write(" {0} ", x);
}
Console.WriteLine("");
for (int y = 0; y < cells.GetLength(1); ++y) {
Console.WriteLine(line);
Console.Write(" {0} |", y);
for (int x = 0; x < cells.GetLength(0); ++x) {
Console.Write(" {0} |", cells[x, y].ToString());
}
Console.WriteLine();
}
Console.WriteLine(line);
var ts = sw.Elapsed;
Console.WriteLine("- {0}モード - {1:00}:{2:00}", (mode == Mode.Flag ? "フラグ立て" : "マス開け"), ts.Minutes, ts.Seconds);
}
public void Run() {
StartGame();
while (playing) {
FlushScreen();
AskCommand();
}
}
}
class MineSweeper {
static int Main() {
var view = new GameView();
view.Run();
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment