Last active
October 16, 2021 04:04
-
-
Save AyrA/b546062b18d13973cc5e823e8725b387 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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