Skip to content

Instantly share code, notes, and snippets.

@MikuroXina
Last active January 6, 2022 02:09
Show Gist options
  • Select an option

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

Select an option

Save MikuroXina/ecae87d9e96fe9ac8ac160e3d4bd78cb to your computer and use it in GitHub Desktop.
The Connected Four game.
using System;
using System.Diagnostics;
using System.Linq;
using System.Text.RegularExpressions;
using Internal;
enum Cell {
Empty,
Black,
White,
}
class Board {
Cell[, ] cells;
Action<Player> onGameSet;
public Board(int width, int height, Action<Player> gameSet) {
cells = new Cell[width, height];
onGameSet = gameSet;
for (int y = 0; y < cells.GetLength(1); ++y) {
for (int x = 0; x < cells.GetLength(0); ++x) {
cells[x, y] = Cell.Empty;
}
}
}
Player PlayerFrom(Cell cell) {
if (cell == Cell.Black) {
return Player.Black;
}
if (cell == Cell.White) {
return Player.White;
}
throw new Exception("Illegal cell state");
}
int CountSeq(Cell target, int x, int y, int vx, int vy) {
var looking = GetCell(x + vx, y + vy);
if (looking != target) {
return 0;
}
return 1 + CountSeq(target, x + vx, y + vy, vx, vy);
}
void CheckCellsFilled() {
for (int y = 0; y < cells.GetLength(1); ++y) {
for (int x = 0; x < cells.GetLength(0); ++x) {
if (cells[x, y] == Cell.Empty) {
return;
}
}
}
onGameSet(Player.Draw);
}
void Judge(int x, int y) {
var current = GetCell(x, y);
if (current == Cell.Empty) { return; }
var xDirCount = CountSeq(current, x, y, 1, 0) + CountSeq(current, x, y, -1, 0);
var yDirCount = CountSeq(current, x, y, 0, 1) + CountSeq(current, x, y, 0, -1);
var xyDirCount = CountSeq(current, x, y, 1, 1) + CountSeq(current, x, y, -1, -1);
var x_yDirCount = CountSeq(current, x, y, 1, -1) + CountSeq(current, x, y, -1, 1);
if (3 <= xDirCount || 3 <= yDirCount || 3 <= xyDirCount || 3 <= x_yDirCount) {
onGameSet(PlayerFrom(current));
}
CheckCellsFilled();
}
public Cell GetCell(int x, int y) {
if (!(0 <= x && x < cells.GetLength(0) &&
0 <= y && y < cells.GetLength(1))) {
return Cell.Empty;
}
return cells[x, y];
}
public void FallCell(Cell cell, int x) {
if (!(0 <= x && x < cells.GetLength(0))) {
throw new ArgumentOutOfRangeException("");
}
for (int y = 0; y < cells.GetLength(1); ++y) {
if (cells[x, y] == Cell.Empty) {
cells[x, y] = cell;
Judge(x, y);
return;
}
}
throw new OverflowException("");
}
}
enum Player {
Black,
White,
Draw,
}
class GameView {
Board board;
bool playing;
Player player;
readonly int W;
readonly int H;
public GameView(int width, int height) {
board = new Board(width, height, this.GameSet);
player = Player.Black;
W = width;
H = height;
}
void GameSet(Player winner) {
Flush();
if (winner == Player.Draw) {
Console.WriteLine("引き分け!");
} else {
Console.WriteLine("{0}の勝利!", PlayerName());
}
playing = false;
}
void StartGame() {
playing = true;
}
void Flush() {
Console.Clear();
// Positions
for (int x = 0; x < W; ++x) {
Console.Write(" {0}", x);
}
Console.WriteLine();
// Cells
for (int y = H - 1; 0 <= y; --y) {
for (int x = 0; x < W; ++x) {
var cellChar = "_";
switch (board.GetCell(x, y)) {
case Cell.Black:
cellChar = "■";
break;
case Cell.White:
cellChar = "○";
break;
}
Console.Write(" {0}", cellChar);
}
Console.WriteLine();
}
}
string PlayerName() {
if (player == Player.White) {
return "白";
}
if (player == Player.Black) {
return "黒";
}
return "謎の人物";
}
void AskCommand() {
Console.WriteLine("{0}の手番です。石を落とす位置を入力してね", PlayerName());
while (true) {
try {
int pos = int.Parse(Console.ReadLine());
Cell toFall = Cell.Empty;
if (player == Player.Black) {
toFall = Cell.Black;
} else if (player == Player.White) {
toFall = Cell.White;
}
board.FallCell(toFall, pos);
break;
} catch (OverflowException _e) {
Console.WriteLine("空いている列を選んでね");
} catch (Exception _ignore) {
Console.WriteLine("上の範囲内の数字で入力し直してね");
}
}
}
void NextTurn() {
if (player == Player.Black) {
player = Player.White;
} else if (player == Player.White) {
player = Player.Black;
}
}
public void Run() {
StartGame();
while (playing) {
Flush();
AskCommand();
NextTurn();
}
}
}
class Hamlet {
static int Main() {
var view = new GameView(8, 8);
view.Run();
return 0;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment