Skip to content

Instantly share code, notes, and snippets.

@AyrA
Last active October 16, 2021 04:04
Show Gist options
  • Save AyrA/b546062b18d13973cc5e823e8725b387 to your computer and use it in GitHub Desktop.
Save AyrA/b546062b18d13973cc5e823e8725b387 to your computer and use it in GitHub Desktop.
#define TTT_USELINQ //If you feel that Linq is cheating, you can remove this line.
using System;
#if TTT_USELINQ
using System.Linq;
#endif
namespace UglyRestrictions
{
/// <summary>
/// Provides a minimalistic Tic Tac Toe implementation.
/// Requirements:
/// - Do not use arrays
/// - Do not declare and use user defined functions
/// Features:
/// - No lists either. Doesn't uses Indexer syntax (square brackets) at all
/// - (Optional) No Linq, just System namespace
/// - Fully commented
/// - Using iterations for win condition check
/// - Only tests win against the player that made the last move
/// - No redundant code
/// - Shows current player
/// - Detect draw situation
/// </summary>
/// <seealso cref="https://old.reddit.com/r/programminghorror/comments/q8hptf/_/hgr2mo9/" />
public static class TTT
{
#if TTT_USELINQ
public static void Run()
{
//Using the characters '1' and '2' doubles as "Player X" output
char Player = '1';
//char* is just memory
string Field = "000000000";
//char* is also just indexes
string Label = "ABCDEFGHI";
Console.Clear();
while (Player != '0')
{
//Show field
Console.SetCursorPosition(0, 0);
for (int i = 0; i < 9; i += 3)
{
Console.WriteLine("{0} {1} {2} | {3} {4} {5}",
Field.Substring(i + 0, 1),
Field.Substring(i + 1, 1),
Field.Substring(i + 2, 1),
Label.Substring(i + 0, 1),
Label.Substring(i + 1, 1),
Label.Substring(i + 2, 1)
);
}
Console.Write("Player {0}, make your move (A-I): ", Player);
char Key = Console.ReadKey(true).KeyChar.ToString().ToUpper().First();
int Pos = Label.IndexOf(Key);
//Validate input
if (Pos < 0 || Field.Substring(Pos, 1).First() != '0')
{
//Escape key
if (Key == '\x1B')
{
Console.WriteLine("Game ended by [ESC] key");
Player = '0';
}
Console.Beep();
}
else
{
Console.WriteLine();
//make move
Field = Field.Substring(0, Pos) + Player + Field.Substring(Pos + 1);
for (int i = 0; i < 3; i++)
{
if (
//Check horizontals
Field.Substring(i, 3).All(m => m == Player) ||
//Verticals
(Field.Substring(i, 1) + Field.Substring(i + 3, 1) + Field.Substring(i + 6, 1)).All(m => m == Player))
{
Console.WriteLine("Player {0} wins", Player);
Player = '0';
}
}
//Check diagonals
if (
(Field.Substring(0, 1) + Field.Substring(4, 1) + Field.Substring(8, 1)).All(m => m == Player) ||
(Field.Substring(2, 1) + Field.Substring(4, 1) + Field.Substring(6, 1)).All(m => m == Player))
{
Console.WriteLine("Player {0} wins", Player);
Player = '0';
}
//It's a draw if all fields occupied and nobody won
if (!Field.Contains("0"))
{
Console.WriteLine("It's a draw");
Player = '0';
}
//Switch player
If(Player != '0')
{
Player = Player == '1' ? '2' : '1';
}
}
}
}
#else
public static void Run()
{
//Using the characters '1' and '2' doubles as "Player X" output
char Player = '1';
//char* is just memory
string Field = "000000000";
//char* is also just indexes
string Label = "ABCDEFGHI";
Console.Clear();
while (Player != '0')
{
//Show field
Console.SetCursorPosition(0, 0);
for (int i = 0; i < 9; i += 3)
{
Console.WriteLine("{0} {1} {2} | {3} {4} {5}",
Field.Substring(i + 0, 1),
Field.Substring(i + 1, 1),
Field.Substring(i + 2, 1),
Label.Substring(i + 0, 1),
Label.Substring(i + 1, 1),
Label.Substring(i + 2, 1)
);
}
Console.Write("Player {0}, make your move (A-I): ", Player);
string Key = Console.ReadKey(true).KeyChar.ToString().ToUpper();
int Pos = Label.IndexOf(Key);
//Validate input
if (Pos < 0 || Field.Substring(Pos, 1) != "0")
{
//Escape key
if (Key == "\x1B")
{
Console.WriteLine("Game ended by [ESC] key");
Player = '0';
}
Console.Beep();
}
else
{
//This is either "111" or "222". Used later for comparison against the field.
string PPP = string.Format("{0}{0}{0}", Player);
Console.WriteLine();
//make move
Field = Field.Substring(0, Pos) + Player + Field.Substring(Pos + 1);
for (int i = 0; i < 3; i++)
{
if (
//Check horizontals
Field.Substring(i, 3) == PPP ||
//Verticals
(Field.Substring(i, 1) + Field.Substring(i + 3, 1) + Field.Substring(i + 6, 1)) == PPP)
{
Console.WriteLine("Player {0} wins", Player);
Player = '0';
}
}
//Check diagonals
if (
(Field.Substring(0, 1) + Field.Substring(4, 1) + Field.Substring(8, 1)) == PPP ||
(Field.Substring(2, 1) + Field.Substring(4, 1) + Field.Substring(6, 1)) == PPP)
{
Console.WriteLine("Player {0} wins", Player);
Player = '0';
}
//It's a draw if all fields occupied and nobody won
if (!Field.Contains("0"))
{
Console.WriteLine("It's a draw");
Player = '0';
}
//Switch player
If(Player != '0')
{
Player = Player == '1' ? '2' : '1';
}
}
}
}
#endif
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment