namespace Nac
{
using System;
using System.Collections.Generic;
internal static class Program
{
private class Position
{
public int X { get; private set; }
public int Y { get; private set; }
public Position(int x, int y)
{
this.X = x;
this.Y = y;
}
public void Right()
{
this.Y++;
}
public void Left()
{
this.Y--;
}
public void Up()
{
this.X--;
}
public void Down()
{
this.X++;
}
}
private const int Height = 3;
private const int Width = 3;
private const char Blank = ' ';
private const char HumanPlayerSymbol = 'X';
private const char AiPlayerSymbol = 'O';
private static readonly Random Random = new Random();
private static Position _cursorPosition = new Position(0, 0);
private static readonly char[,] Field = new char[Program.Height, Program.Width];
private static void Main()
{
Console.Title = "Tic-tac-toe";
Console.CursorVisible = false;
do
{
Program.ResetField();
while (Program.HandleInput())
{
Program.Render();
}
} while (Console.ReadKey(false).Key == ConsoleKey.R);
}
private static void ResetField()
{
for (int x = 0; x < Program.Height; x++)
{
for (int y = 0; y < Program.Width; y++)
{
Program.Field[x, y] = Program.Blank;
}
}
Program.Render();
}
private static bool HandleInput()
{
switch (Console.ReadKey(true).Key)
{
case ConsoleKey.Escape:
case ConsoleKey.Q:
return false;
case ConsoleKey.RightArrow:
if (Program._cursorPosition.Y < Program.Width - 1)
{
Program._cursorPosition.Right();
}
break;
case ConsoleKey.LeftArrow:
if (Program._cursorPosition.Y > 0)
{
Program._cursorPosition.Left();
}
break;
case ConsoleKey.DownArrow:
if (Program._cursorPosition.X < Program.Height - 1)
{
Program._cursorPosition.Down();
}
break;
case ConsoleKey.UpArrow:
if (Program._cursorPosition.X > 0)
{
Program._cursorPosition.Up();
}
break;
case ConsoleKey.Spacebar:
if (Program.SetCell(Program._cursorPosition.X, Program._cursorPosition.Y, Program.HumanPlayerSymbol) == false)
{
break;
}
if (Program.PrintWinner())
{
return false;
}
if (Program.MakeAiMove() == false)
{
Program.PrintMessage("Uh oh.. nobody wins. Press 'R' to play again.", ConsoleColor.Red);
return false;
}
if (Program.PrintWinner())
{
return false;
}
break;
case ConsoleKey.R:
Program.ResetField();
break;
}
return true;
}
private static bool PrintWinner()
{
char winner = Program.DetermineWinner();
if (winner != Program.Blank)
{
Program.Render();
Program.PrintMessage($"Player {winner} won. Press 'R' to play again.", ConsoleColor.Green);
return true;
}
return false;
}
private static void PrintMessage(string message, ConsoleColor color)
{
Console.ForegroundColor = color;
Console.SetCursorPosition(0, Program.Height * 2);
Console.WriteLine(message);
Console.ResetColor();
Program.RenderCursor();
}
private static IList<Position> GetAvailableCells()
{
List<Position> available = new List<Position>();
for (int x = 0; x < Program.Height; x++)
{
for (int y = 0; y < Program.Width; y++)
{
if (Program.Field[x, y] == Program.Blank)
{
available.Add(new Position(x, y));
}
}
}
return available;
}
private static char DetermineWinner()
{
// Horizontally
for (int x = 0; x < Program.Height; x++)
{
bool won = true;
for (int y = 0; y < Program.Width - 1; y++)
{
won = won && Program.Field[x, y] != Program.Blank && Program.Field[x, y] == Program.Field[x, y + 1];
}
if (won)
{
return Program.Field[x, 0];
}
}
// Vertically
for (int y = 0; y < Program.Width; y++)
{
bool won = true;
for (int x = 0; x < Program.Height - 1; x++)
{
won = won && Program.Field[x, y] != Program.Blank && Program.Field[x, y] == Program.Field[x + 1, y];
}
if (won)
{
return Program.Field[0, y];
}
}
// Diagonal left to right
{
bool won = true;
for (int i = 0; i < Program.Height - 1; i++)
{
won = won && Program.Field[i, i] != Program.Blank &&
Program.Field[i, i] == Program.Field[i + 1, i + 1];
}
if (won)
{
return Program.Field[0, 0];
}
}
// Diagonal right to left
{
bool won = true;
for (int i = 0; i < Program.Height - 1; i++)
{
won = won && Program.Field[i, Program.Width - i - 1] != Program.Blank &&
Program.Field[i, Program.Width - i - 1] == Program.Field[i + 1, Program.Width - i - 2];
}
if (won)
{
return Program.Field[0, Program.Width - 1];
}
}
return Program.Blank;
}
private static bool MakeAiMove()
{
IList<Position> availableCells = Program.GetAvailableCells();
if (availableCells.Count == 0)
{
return false;
}
int pick = Program.Random.Next(0, availableCells.Count);
Program.SetCell(availableCells[pick].X, availableCells[pick].Y, Program.AiPlayerSymbol);
return true;
}
private static bool SetCell(int x, int y, char symbol)
{
if (Program.Field[x, y] != Program.Blank)
{
return false;
}
if (x > Program.Height || x < 0 || y > Program.Width || y < 0)
{
return false;
}
Program.Field[x, y] = symbol;
return true;
}
private static void Render()
{
Console.SetCursorPosition(0, 0);
for (int x = 0; x < Program.Height; x++)
{
for (int y = 0; y < Program.Width - 1; y++)
{
Console.Write($" {Program.Field[x, y]} |");
}
Console.Write($" {Program.Field[x, Program.Width - 1]} ");
Console.WriteLine();
if (x != Program.Height - 1)
{
const int numberOfDashes = (Program.Width - 1) * 4 + 3;
Console.WriteLine(new string('-', numberOfDashes));
}
}
// Clear printed message
Console.WriteLine();
Console.WriteLine(new string('\0', Console.BufferWidth));
Program.RenderCursor();
}
private static void RenderCursor()
{
Console.SetCursorPosition(Program._cursorPosition.Y * 4 + 1, Program._cursorPosition.X * 2);
Console.BackgroundColor = ConsoleColor.Cyan;
Console.ForegroundColor = ConsoleColor.Black;
Console.Write(Program.Field[Program._cursorPosition.X, Program._cursorPosition.Y]);
Console.ResetColor();
}
}
}
namespace Golf
{
using System;
using System.Collections.Generic;
internal static class Program
{
private class GolfClub
{
public string Name { get; private set; }
public int MinDistance { get; private set; }
public int MaxDistance { get; private set; }
public GolfClub(string name, int min, int max)
{
this.Name = name;
this.MinDistance = min;
this.MaxDistance = max;
}
public int Hit(int distanceToHole)
{
if (distanceToHole <= this.MaxDistance && distanceToHole >= this.MinDistance)
{
return Program.Random.Next(this.MinDistance, distanceToHole);
}
return Program.Random.Next(this.MinDistance, this.MaxDistance + 1);
}
}
private static readonly Random Random = new Random();
private static int _remainingDistance;
private static GolfClub _selectedClub;
private static int _hits;
private static readonly List<GolfClub> Clubs = new List<GolfClub>
{
new GolfClub("Wood", 150, 500),
new GolfClub("Iron", 100, 300),
new GolfClub("Putter", 1, 50)
};
private static void Main()
{
Console.Title = "Golf";
Console.CursorVisible = false;
do
{
Program.Reset();
while (Program._remainingDistance != 0)
{
Console.Clear();
Program.PrintFieldInfo();
Program.PrintClubInfos();
Program.SelectClub();
Program.PerformHit();
}
Console.Clear();
Console.WriteLine($"Took you {Program._hits} damn hits.");
} while (Console.ReadKey(true).Key == ConsoleKey.R);
}
private static void PrintClubInfos()
{
for (int i = 0; i < Program.Clubs.Count; i++)
{
Console.WriteLine($"{i + 1}) {Program.Clubs[i].Name}");
Console.WriteLine($" Distance: {Program.Clubs[i].MinDistance}m - {Program.Clubs[i].MaxDistance}m");
Console.WriteLine();
}
}
private static void PrintFieldInfo()
{
Console.WriteLine($"Distance to hole: {Program._remainingDistance}m");
Console.WriteLine($"Tries: {Program._hits}");
Console.WriteLine();
}
private static int ConsoleKeyToInt()
{
ConsoleKeyInfo key;
do
{
key = Console.ReadKey(true);
} while (key.Key > ConsoleKey.D9 || key.Key < ConsoleKey.D0);
return (int)key.Key - (int)ConsoleKey.D0;
}
private static void SelectClub()
{
Console.WriteLine("Please select your club.");
Console.WriteLine();
int selection = Program.ConsoleKeyToInt();
Program._selectedClub = Program.Clubs[selection - 1];
}
private static void PerformHit()
{
int distance = Program._selectedClub.Hit(Program._remainingDistance);
Program._remainingDistance -= distance;
if (Program._remainingDistance < 0)
{
Program._remainingDistance *= -1;
}
Program._hits++;
}
private static void Reset()
{
Program._remainingDistance = Program.Random.Next(300, 500);
Program._hits = 0;
Program._selectedClub = Program.Clubs[0];
}
}
}