Доработана угадайка, добавлена змейка
This commit is contained in:
@@ -1,380 +0,0 @@
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace laba3.Subprograms
|
||||
{
|
||||
/// <summary>
|
||||
/// TUI classic game "Snake";
|
||||
/// The player controls the snake.
|
||||
/// The player has to eat apples to increase the length of the snake
|
||||
/// and try not to crash into the wall or themselves;
|
||||
/// </summary>
|
||||
internal class SnakeGame
|
||||
{
|
||||
int size_x;
|
||||
int size_y;
|
||||
int score;
|
||||
int size_xy;
|
||||
Level difficulty;
|
||||
Tiles[,] world;
|
||||
Snake snake;
|
||||
Random rnd;
|
||||
|
||||
private bool gameover;
|
||||
/// <summary>
|
||||
/// Game world constructor;
|
||||
/// </summary>
|
||||
/// <param name="difficulty">Game speed</param>
|
||||
/// <param name="size_x">Game world size dim x</param>
|
||||
/// <param name="size_y">Game world size dim y</param>
|
||||
public SnakeGame(Level difficulty, int size_x, int size_y)
|
||||
{
|
||||
this.size_x = size_x;
|
||||
this.size_y = size_y;
|
||||
this.difficulty = difficulty;
|
||||
world = new Tiles[size_x, size_y];
|
||||
rnd = new Random();
|
||||
score = 0;
|
||||
size_xy = size_x * size_y;
|
||||
}
|
||||
/// <summary>
|
||||
/// Start game;
|
||||
/// Console will be clean!;
|
||||
/// </summary>
|
||||
public void start()
|
||||
{
|
||||
int msPerTick = difficulty switch
|
||||
{
|
||||
Level.Low => 500,
|
||||
Level.Medium => 250,
|
||||
Level.High => 100,
|
||||
_ => 500,
|
||||
};
|
||||
gameover = false;
|
||||
|
||||
Console.Clear();
|
||||
Console.CursorVisible = false;
|
||||
snake = new Snake(new Point(size_x / 2, size_y / 2, this), 1, Direction.Right, this);
|
||||
|
||||
GenerateFood();
|
||||
|
||||
DrawBackground();
|
||||
DrawWorld();
|
||||
|
||||
Stopwatch tickTimer = new Stopwatch();
|
||||
while (!gameover)
|
||||
{
|
||||
tickTimer.Restart();
|
||||
if (Console.KeyAvailable)
|
||||
{
|
||||
ConsoleKeyInfo key = Console.ReadKey(false);
|
||||
snake.HandleKey(key.Key);
|
||||
while (Console.KeyAvailable)
|
||||
Console.ReadKey(false);
|
||||
}
|
||||
snake.Move();
|
||||
long delta = tickTimer.ElapsedMilliseconds;
|
||||
|
||||
Console.SetCursorPosition(1, 0);
|
||||
if (delta > msPerTick)
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Write(delta);
|
||||
|
||||
Thread.Sleep((int)Math.Max(0, msPerTick - delta));
|
||||
}
|
||||
onStop();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stop game;
|
||||
/// </summary>
|
||||
public void stop()
|
||||
{
|
||||
gameover = true;
|
||||
}
|
||||
|
||||
private void onStop()
|
||||
{
|
||||
string gameOverTitle =
|
||||
@"
|
||||
### ##
|
||||
# ## #### # # # # # # ##
|
||||
# ## # # # # # ### # # # # ### #
|
||||
# # # # # # # # # # # # #
|
||||
### ## # # # ## ## # ## #
|
||||
";
|
||||
Console.Clear();
|
||||
printArt(gameOverTitle, (Console.WindowWidth - 36) / 2, 4, ConsoleColor.DarkYellow, ConsoleColor.DarkGray);
|
||||
|
||||
Console.ResetColor();
|
||||
|
||||
string scoreString = $"Score: {score}";
|
||||
Console.SetCursorPosition((Console.WindowWidth - scoreString.Length) / 2, 11);
|
||||
Console.Write(scoreString);
|
||||
Console.SetCursorPosition((Console.WindowWidth - "Press Enter to continue".Length) / 2, 14);
|
||||
Console.CursorVisible = true;
|
||||
}
|
||||
|
||||
private void printArt(string art, int x, int y, ConsoleColor primaryColor, ConsoleColor shadowColor)
|
||||
{
|
||||
int row = 0;
|
||||
Console.SetCursorPosition(x, y);
|
||||
char shadow = ' ';
|
||||
foreach (char ch in art)
|
||||
{
|
||||
if (ch == '\n')
|
||||
{
|
||||
if (shadow == '#')
|
||||
{
|
||||
Console.BackgroundColor = shadowColor;
|
||||
Console.Write(' ');
|
||||
}
|
||||
Console.SetCursorPosition(x, y++ + row);
|
||||
Thread.Sleep(25);
|
||||
shadow = ch;
|
||||
}
|
||||
else if (ch == ' ')
|
||||
{
|
||||
if (shadow == '#')
|
||||
{
|
||||
Console.BackgroundColor = shadowColor;
|
||||
Console.Write(' ');
|
||||
}
|
||||
else
|
||||
Console.CursorLeft++;
|
||||
shadow = ch;
|
||||
}
|
||||
else if (ch == '#')
|
||||
{
|
||||
Console.BackgroundColor = primaryColor;
|
||||
Console.Write(' ');
|
||||
shadow = ch;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
private void addScore()
|
||||
{
|
||||
score += difficulty switch
|
||||
{
|
||||
Level.Low => 10,
|
||||
Level.Medium => 50,
|
||||
Level.High => 100,
|
||||
_ => 1,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Generate food in random place;
|
||||
/// </summary>
|
||||
public void GenerateFood()
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
do
|
||||
{
|
||||
x = rnd.Next(size_x);
|
||||
y = rnd.Next(size_y);
|
||||
} while (world[x, y] != Tiles.Void);
|
||||
world[x, y] = Tiles.Food;
|
||||
DrawTile(x, y);
|
||||
}
|
||||
|
||||
private void DrawBackground()
|
||||
{
|
||||
for (int x = 1; x < (size_x + 1) * 2 + 1; x++)
|
||||
{
|
||||
Console.SetCursorPosition(x, 1);
|
||||
Console.Write('#');
|
||||
Console.SetCursorPosition(x, size_y + 2);
|
||||
Console.Write('#');
|
||||
}
|
||||
for (int y = 1; y < size_y + 2; y++)
|
||||
{
|
||||
Console.SetCursorPosition(1, y);
|
||||
Console.Write('#');
|
||||
|
||||
Console.SetCursorPosition(size_x * 2 + 1, y);
|
||||
Console.Write('#');
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawTile(int x, int y)
|
||||
{
|
||||
char symbol;
|
||||
switch (world[x, y])
|
||||
{
|
||||
case Tiles.Void:
|
||||
symbol = ' ';
|
||||
break;
|
||||
case Tiles.Snake:
|
||||
symbol = '*';
|
||||
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||
break;
|
||||
case Tiles.Food:
|
||||
symbol = '@';
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
break;
|
||||
default:
|
||||
symbol = '?';
|
||||
break;
|
||||
};
|
||||
//Console.BackgroundColor = ConsoleColor.DarkGreen;
|
||||
Console.SetCursorPosition((x + 1) * 2, y + 2);
|
||||
Console.Write(symbol);
|
||||
|
||||
Console.BackgroundColor = ConsoleColor.Black;
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
}
|
||||
private void DrawWorld()
|
||||
{
|
||||
for (int x = 0; x < size_x; x++)
|
||||
{
|
||||
for (int y = 0; y < size_y; y++)
|
||||
{
|
||||
DrawTile(x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
private enum Tiles
|
||||
{
|
||||
Void,
|
||||
Snake,
|
||||
Food
|
||||
}
|
||||
public enum Level
|
||||
{
|
||||
Low,
|
||||
Medium,
|
||||
High
|
||||
}
|
||||
private class Snake
|
||||
{
|
||||
private SnakeGame game;
|
||||
private List<Point> body;
|
||||
private Direction direction;
|
||||
|
||||
public Snake(Point tail, int length, Direction initialDirection, SnakeGame game)
|
||||
{
|
||||
this.game = game;
|
||||
body = new List<Point>();
|
||||
direction = initialDirection;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
Point p = new Point(tail.X, tail.Y, game);
|
||||
body.Add(p);
|
||||
}
|
||||
}
|
||||
|
||||
public void Move()
|
||||
{
|
||||
Point head = GetNextPoint();
|
||||
Point tail = body.First();
|
||||
|
||||
if (head.X < 0 || head.Y < 0 || head.X >= game.size_x || head.Y >= game.size_y)
|
||||
{
|
||||
game.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
if (game.world[head.X, head.Y] == Tiles.Snake)
|
||||
{
|
||||
game.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
body.Add(head);
|
||||
if (game.world[head.X, head.Y] != Tiles.Food)
|
||||
{
|
||||
body.Remove(tail);
|
||||
tail.UpdateWorld(Tiles.Void);
|
||||
}
|
||||
else
|
||||
{
|
||||
game.addScore();
|
||||
game.GenerateFood();
|
||||
if (body.Count >= game.size_xy) game.stop();
|
||||
}
|
||||
head.UpdateWorld(Tiles.Snake);
|
||||
}
|
||||
|
||||
public Point GetNextPoint()
|
||||
{
|
||||
Point head = body.Last();
|
||||
Point nextPoint = new Point(head.X, head.Y, game);
|
||||
|
||||
switch (direction)
|
||||
{
|
||||
case Direction.Right:
|
||||
nextPoint.X++;
|
||||
break;
|
||||
case Direction.Left:
|
||||
nextPoint.X--;
|
||||
break;
|
||||
case Direction.Up:
|
||||
nextPoint.Y--;
|
||||
break;
|
||||
case Direction.Down:
|
||||
nextPoint.Y++;
|
||||
break;
|
||||
}
|
||||
|
||||
return nextPoint;
|
||||
}
|
||||
|
||||
public void HandleKey(ConsoleKey key)
|
||||
{
|
||||
switch (key)
|
||||
{
|
||||
case ConsoleKey.LeftArrow:
|
||||
if (direction != Direction.Right)
|
||||
direction = Direction.Left;
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
if (direction != Direction.Left)
|
||||
direction = Direction.Right;
|
||||
break;
|
||||
case ConsoleKey.UpArrow:
|
||||
if (direction != Direction.Down)
|
||||
direction = Direction.Up;
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
if (direction != Direction.Up)
|
||||
direction = Direction.Down;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum Direction
|
||||
{
|
||||
Left,
|
||||
Right,
|
||||
Up,
|
||||
Down
|
||||
}
|
||||
|
||||
private class Point
|
||||
{
|
||||
private SnakeGame game { get; set; }
|
||||
public int X { get; set; }
|
||||
public int Y { get; set; }
|
||||
|
||||
public Point(int x, int y, SnakeGame game)
|
||||
{
|
||||
this.game = game;
|
||||
X = x;
|
||||
Y = y;
|
||||
}
|
||||
|
||||
public void UpdateWorld(Tiles tile)
|
||||
{
|
||||
game.world[X, Y] = tile;
|
||||
game.DrawTile(X, Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user