Тия дни водих една интересна лекция, в която демонстрирах на живо в рамките на 2 часа как се пише играта змия на конзолата. Използвах езика C#. Студентите ми казваха какво искат да има в играта, аз им го писах на живо и им обяснявах кое как работи. Много фирми използват точно тази игра, за да подбират програмистите си. Казват им: "седни тук, имаш 30 минути напиши ми играта змия" и после според бързината и качеството на кода решават кой кандидат става и кой не. Тук съм качил цялото видеото от лекцията, заедно със сорс кода на змията.
Приятно гледане ;)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
namespace JustSnake
{
struct Position
{
public int row;
public int col;
public Position(int row, int col)
{
this.row = row;
this.col = col;
}
}
class Program
{
static void Main(string[] args)
{
byte right = 0;
byte left = 1;
byte down = 2;
byte up = 3;
int lastFoodTime = 0;
int foodDissapearTime = 8000;
int negativePoints = 0;
Position[] directions = new Position[]
{
new Position(0, 1), // right
new Position(0, -1), // left
new Position(1, 0), // down
new Position(-1, 0), // up
};
double sleepTime = 100;
int direction = right;
Random randomNumbersGenerator = new Random();
Console.BufferHeight = Console.WindowHeight;
lastFoodTime = Environment.TickCount;
List< Position > obstacles =
new List< Position >()
{
new Position(12, 12),
new Position(14, 20),
new Position(7, 7),
new Position(19, 19),
new Position(6, 9),
};
foreach (Position obstacle in obstacles)
{
Console.ForegroundColor = ConsoleColor.Cyan;
Console.SetCursorPosition(
obstacle.col,
obstacle.row);
Console.Write("=");
}
Queue< Position > snakeElements =
new Queue< Position >();
for (int i = 0; i <= 5; i++)
{
snakeElements.Enqueue(new Position(0, i));
}
Position food;
do
{
food = new Position(
randomNumbersGenerator.Next(0,
Console.WindowHeight),
randomNumbersGenerator.Next(0,
Console.WindowWidth));
}
while (snakeElements.Contains(food) ||
obstacles.Contains(food));
Console.SetCursorPosition(food.col, food.row);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("@");
foreach (Position position in snakeElements)
{
Console.SetCursorPosition(
position.col,
position.row);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Write("*");
}
while(true)
{
negativePoints++;
if (Console.KeyAvailable)
{
ConsoleKeyInfo userInput = Console.ReadKey();
if (userInput.Key == ConsoleKey.LeftArrow)
{
if (direction != right) direction = left;
}
if (userInput.Key == ConsoleKey.RightArrow)
{
if (direction != left) direction = right;
}
if (userInput.Key == ConsoleKey.UpArrow)
{
if (direction != down) direction = up;
}
if (userInput.Key == ConsoleKey.DownArrow)
{
if (direction != up) direction = down;
}
}
Position snakeHead = snakeElements.Last();
Position nextDirection = directions[direction];
Position snakeNewHead = new Position(
snakeHead.row + nextDirection.row,
snakeHead.col + nextDirection.col);
if (snakeNewHead.col < 0)
snakeNewHead.col = Console.WindowWidth - 1;
if (snakeNewHead.row < 0)
snakeNewHead.row = Console.WindowHeight - 1;
if (snakeNewHead.row >= Console.WindowHeight)
snakeNewHead.row = 0;
if (snakeNewHead.col >= Console.WindowWidth)
snakeNewHead.col = 0;
if (snakeElements.Contains(snakeNewHead)
|| obstacles.Contains(snakeNewHead))
{
Console.SetCursorPosition(0, 0);
Console.ForegroundColor = ConsoleColor.Red;
Console.WriteLine("Game over!");
int userPoints =
(snakeElements.Count - 6) * 100 -
negativePoints;
//if (userPoints < 0) userPoints = 0;
userPoints = Math.Max(userPoints, 0);
Console.WriteLine("Your points are: {0}",
userPoints);
Console.ReadLine();
return;
}
Console.SetCursorPosition(
snakeHead.col,
snakeHead.row);
Console.ForegroundColor = ConsoleColor.DarkGray;
Console.Write("*");
snakeElements.Enqueue(snakeNewHead);
Console.SetCursorPosition(
snakeNewHead.col,
snakeNewHead.row);
Console.ForegroundColor = ConsoleColor.Gray;
if (direction == right) Console.Write(">");
if (direction == left) Console.Write("<");
if (direction == up) Console.Write("^");
if (direction == down) Console.Write("v");
if (snakeNewHead.col == food.col &&
snakeNewHead.row == food.row)
{
// feeding the snake
do
{
food = new Position(
randomNumbersGenerator.Next(0,
Console.WindowHeight),
randomNumbersGenerator.Next(0,
Console.WindowWidth));
}
while(snakeElements.Contains(food) ||
obstacles.Contains(food));
lastFoodTime = Environment.TickCount;
Console.SetCursorPosition(
food.col,
food.row);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("@");
sleepTime--;
Position obstacle = new Position();
do
{
obstacle = new Position(
randomNumbersGenerator.Next(0,
Console.WindowHeight),
randomNumbersGenerator.Next(0,
Console.WindowWidth));
}
while(snakeElements.Contains(obstacle) ||
obstacles.Contains(obstacle) ||
(food.row != obstacle.row &&
food.col != obstacle.row));
obstacles.Add(obstacle);
Console.SetCursorPosition(
obstacle.col,
obstacle.row);
Console.ForegroundColor = ConsoleColor.Cyan;
Console.Write("=");
}
else
{
// moving...
Position last = snakeElements.Dequeue();
Console.SetCursorPosition(last.col, last.row);
Console.Write(" ");
}
if (Environment.TickCount - lastFoodTime >=
foodDissapearTime)
{
negativePoints = negativePoints + 50;
Console.SetCursorPosition(food.col, food.row);
Console.Write(" ");
do
{
food = new Position(
randomNumbersGenerator.Next(0,
Console.WindowHeight),
randomNumbersGenerator.Next(0,
Console.WindowWidth));
}
while (snakeElements.Contains(food) ||
obstacles.Contains(food));
lastFoodTime = Environment.TickCount;
}
Console.SetCursorPosition(food.col, food.row);
Console.ForegroundColor = ConsoleColor.Yellow;
Console.Write("@");
sleepTime -= 0.01;
Thread.Sleep((int)sleepTime);
}
}
}
}