C# :: Aufgabe #39

2 Lösungen Lösungen öffentlich

Snake für die Konsole

Fortgeschrittener - C# von incocnito - 05.01.2013 um 16:13 Uhr
Es soll Snake (Wiki-Snake) für die Konsole programmiert werden.
Neben den klassischen Spielmerkmalen soll auch ein Highscoresystem eingebaut werden. Neben dem "Futter" müssen mit der Zeit auch andere, nicht einsammelbare Items erscheinen, die bei Kontakt das Spiel beenden. Dabei muss beachtet werden, dass soetwas nicht direkt vor dem Schlangenkopf passieren darf, am besten überhaupt nicht in einem gewissen Radius um die Schlange herum, damit das Spiel nicht unfair wird.

Lösungen:

1x
vote_ok
von eulerscheZhl (5230 Punkte) - 25.11.2014 um 20:53 Uhr
Quellcode ausblenden C#-Code
using System;
using System.Text;
using System.Collections.Generic;
using System.Timers;
using System.IO;
using System.Reflection;

namespace trainYourProgrammer
{
	class MainClass
	{
		class Game
		{
			private struct Point {
				public int x, y; 
				public Point(int x, int y) {this.x = x; this.y = y; }
			}

			private enum FieldType {Free, Food, Poison, Antidote}
			private Timer timer;
			private enum Direction {Up, Right, Down, Left}
			private List<Point> snake;
			private Direction direction;
			private const int healthMax = 20;
			private int health;
			private Random random = new Random ();
			private FieldType[,] grid;
			private int width;
			private int height;
			private bool poisoned = false;
			private string highscorePath;

			public Game()
			{
				init();
			}

			private void init()
			{
				timer = new Timer(200);
				highscorePath = Path.GetDirectoryName(Assembly.GetExecutingAssembly ().Location) 
					+ Path.DirectorySeparatorChar + "score.txt";
				width = Console.WindowWidth;
				height = Console.WindowHeight;
				grid = new FieldType[width, height];
				snake = new List<Point> ();
				snake.Add(new Point(width / 2, height - 1));
				health = healthMax;
				placeFood();
				direction = Direction.Up;
				timer.Elapsed += gameTick;
				timer.Start();
				Console.CursorVisible = false;
			}

			private void placeFood()
			{
				List<Point> candidates = new List<Point> ();
				for (int i = 0; i < width; i++)
					for (int j = 0; j < height; j++) {
						Point p = new Point (i, j);
						if (snake.Contains (p) || Math.Abs(p.x - snake[0].x) + Math.Abs(p.y + snake[0].y) < 3)
							continue;
						if (grid [i, j] == FieldType.Free)
							candidates.Add (p);
					}
				int index = random.Next (candidates.Count);
				grid [candidates [index].x, candidates [index].y] = FieldType.Food;
				candidates.RemoveAt (index);
				if (random.NextDouble () < 0.02) {
					index = random.Next (candidates.Count);
					grid [candidates [index].x, candidates [index].y] = FieldType.Poison;
					candidates.RemoveAt (index);
				}
				if (random.NextDouble () < 0.01) {
					index = random.Next (candidates.Count);
					grid [candidates [index].x, candidates [index].y] = FieldType.Antidote;
					candidates.RemoveAt (index);
				}
			}

			private void gameTick(object sender, ElapsedEventArgs e)
			{
				Point headNew = snake [0];
				switch (direction) {
					case Direction.Up: headNew.y--; break;
					case Direction.Down: headNew.y++; break;
					case Direction.Right: headNew.x++; break;
					case Direction.Left: headNew.x--; break;
				}
				if (headNew.x < 0 || headNew.x >= width || headNew.y < 0 || headNew.y >= height) {
					die (); //ins Tigergehege entlaufen
					return;
				}
				snake.Insert (0, headNew);
				switch (grid [headNew.x, headNew.y]) {
					case FieldType.Poison: poisoned = true; break;
					case FieldType.Antidote: poisoned = false; health = healthMax; break;
				case FieldType.Food: snake.Add (snake [snake.Count - 1]); placeFood (); break;
				}
				snake.RemoveAt (snake.Count - 1);
				grid [headNew.x, headNew.y] = FieldType.Free;
				if (poisoned)
					health--;
				if (health <= 0) {
					die (); //vergiftet
					return;
				}
				for (int i = 1; i < snake.Count; i++)
					if (snake [i].x == snake [0].x && snake [i].y == snake [0].y) {
						die (); //in den Schwanz gebissen
						return;
					}
				printGame ();
			}

			private void printGame()
			{
				StringBuilder sb = new StringBuilder ();
				for (int y = 0; y < height; y++) {
					for (int x = 0; x < width; x++) {
						Point p = new Point (x, y);
						if (snake.Contains (p))
							sb.Append ('\u2587');
						else if (grid [x, y] == FieldType.Antidote)
							sb.Append ('\u2665');
						else if (grid [x, y] == FieldType.Food)
							sb.Append ('\u2615');
						else if (grid [x, y] == FieldType.Poison)
							sb.Append ('\u2620');
						else
							sb.Append ('');
					}
					if (y < height + 1)
						sb.AppendLine ();
				}
				Console.Clear ();
				Console.Write (sb.ToString ());
			}

			private void die()
			{
				//highscore
				timer.Dispose ();
				Console.Clear ();
				Console.WriteLine ("\n\n    Du hast verloren!\n\n    Highscores:\n\n");
				if (!File.Exists (highscorePath)) {
					StreamWriter swTmp = new StreamWriter (highscorePath);
					swTmp.Write ("");
					swTmp.Close ();
				}
				StreamReader sr = new StreamReader (highscorePath); //Mono scheint hier mit using nicht klarzukommen
				string[] lines = sr.ReadToEnd().Split('\n');
				sr.Close();
				List<int> scores = new List<int> ();
				List<string> names = new List<string> ();
				foreach (string s in lines) {
					if (s.Contains("\t")) {
						scores.Add (int.Parse (s.Substring (0, s.IndexOf ('\t'))));
						names.Add (s.Substring (s.IndexOf ('\t') + 1));
					}
				}
				int insertPos = 0;
				while (insertPos < scores.Count && snake.Count <= scores[insertPos])
					insertPos++;
				scores.Insert (insertPos, snake.Count);
				names.Insert (insertPos, "");
				for (int i = 0; i < scores.Count && i < 10; i++) 
					Console.WriteLine ("    {0:00}: {1,-20} {2:00}",  i + 1, names [i], scores [i]);
				Console.WriteLine ("\n    Deine Punkte: {0}", snake.Count);
				if (insertPos < 10) { //zu highscores hinzufügen
					Console.CursorVisible = true;
					Console.SetCursorPosition (8, 7 + insertPos);
					while (Console.KeyAvailable)
						Console.ReadKey (true);
					Console.Out.Flush ();
					names [insertPos] = Console.ReadLine ();
					StreamWriter sw = new StreamWriter (highscorePath);
					for (int i = 0; i < scores.Count && i < 10; i++) 
						sw.WriteLine (scores [i] + "\t" + names [i]);
					sw.Close ();
				} else
					Console.ReadKey ();
				//neustart
				init ();
			}

			public void turnRight()
			{
				direction = (Direction)(((int)direction + 1) % 4);
			}

			public void turnLeft()
			{
				direction = (Direction)(((int)direction + 3) % 4);
			}

			public bool IsRunning()
			{
				return timer.Enabled;
			}
		}

		static void Main(string[] args)
		{
			Game game = new Game ();
			while (true) {
				if (game.IsRunning () && Console.KeyAvailable) {
					ConsoleKey readKey = Console.ReadKey ().Key;
					if (readKey == ConsoleKey.RightArrow)
						game.turnRight ();
					if (readKey == ConsoleKey.LeftArrow)
						game.turnLeft ();
				}
			}
		}
	}
}
vote_ok
von Torbo (880 Punkte) - 18.05.2015 um 15:13 Uhr
Quellcode ausblenden C#-Code
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);
            }
        }
    }
}
2121403

Du scheinst einen AdBlocker zu nutzen. Ich würde mich freuen, wenn du ihn auf dieser Seite deaktivierst und dich davon überzeugst, dass die Werbung hier nicht störend ist.