Zablokowanie możliwości wyjścia poza konsole kursorem.

0

Mam taki problem. Napisałem sobie prosty system chodzenia po konsoli (taki zalążek pod zrobienie snejka) teraz mam problem bo nie wiem w jaki sposób zablokować możliwość wychodzenia "bohaterem" poza okno konsoli.
Wymiary konsoli są ustawione poprzez: Console.SetWindowSize .
Napisałem coś takiego:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Snake
{
    class Character
    {
        public int X;
        public int Y;
        public int sizeX = 90;
        public int sizeY = 35;

        public void Snake()
        {
            Console.SetCursorPosition(X, Y);
            Console.WriteLine("#");
        }

        public void Movement()
        {
            ConsoleKeyInfo keyInfo;

            while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Escape)
            {
                switch (keyInfo.Key)
                {
                    case ConsoleKey.UpArrow:
                        Y--;
                        UpdatePosition();
                        break;
                    case ConsoleKey.RightArrow:
                        X++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.DownArrow:
                        Y++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.LeftArrow:
                        X--;
                        UpdatePosition();
                        break;
                }
            }
            
        }

        public void UpdatePosition()
        {
            Console.Clear();
            CheckPosition();
            Console.SetCursorPosition(X, Y);
            Console.WriteLine("#");
        }

        public bool CheckPosition()
        {
            if (X < 0 || X >= Console.WindowWidth)
                return false;

            if (Y < 0 || Y >= Console.WindowHeight)
                return false;

            return true;
            
        }
    
    }
}
1

Przecież wcale nie blokujesz tutaj wyjścia. To, że masz do tego przygotowane metody i nawet je wywołujesz, nie znaczy, że stanie się samo. W tym momencie ZAWSZE aktualizujesz pozycję gracza, bez względu na to, czy jest poprawna, czy nie. Przyjrzyj się metodzie UpdatePosition i zobacz, czego tam brakuje.

0
Juhas napisał(a):

Przecież wcale nie blokujesz tutaj wyjścia. To, że masz do tego przygotowane metody i nawet je wywołujesz, nie znaczy, że stanie się samo. W tym momencie ZAWSZE aktualizujesz pozycję gracza, bez względu na to, czy jest poprawna, czy nie. Przyjrzyj się metodzie UpdatePosition i zobacz, czego tam brakuje.

Racja, czyli powinienem po prostu dać if'a?

public void UpdatePosition()
        {
            Console.Clear();
            if (CheckPosition() == true)
                Console.SetCursorPosition(X, Y);
            Console.Write("#");
            
        }

Tylko gdy mam taki kod to po "uderzeniu" kursor wraca na pozycje 0, 0 i trochę dziwnie się zachowuje.

0

Okej, teraz mój kod wygląda tak:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Snake
{
    class Character
    {
        public int X;
        public int Y;
        public int sizeX = 90;
        public int sizeY = 35;

        public void Snake()
        {
            Console.SetCursorPosition(X, Y);
            Console.WriteLine("#");
        }

        public void Movement()
        {
            ConsoleKeyInfo keyInfo;

            while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Escape)
            {
                switch (keyInfo.Key)
                {
                    case ConsoleKey.UpArrow:
                        Y--;
                        UpdatePosition();
                        break;
                    case ConsoleKey.RightArrow:
                        X++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.DownArrow:
                        Y++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.LeftArrow:
                        X--;
                        UpdatePosition();
                        break;
                }
            }
            
        }

        public void UpdatePosition()
        {
            Console.Clear();
            if (CheckPosition() == true)
                Console.SetCursorPosition(X, Y);

            Console.Write("#");
            
        }

        public bool CheckPosition()
        {
            if (X < 0)
            {
                Console.SetCursorPosition(0, Y);
                return false;
            }

            else if (X >= Console.WindowWidth)
            {
                Console.SetCursorPosition(sizeX, Y);
                return false;
            }

            else if (Y < 0)
            {
                Console.SetCursorPosition(X, 0);
                return false;
            }

            else if (Y >= Console.WindowHeight)
            {
                Console.SetCursorPosition(X, sizeY);
            }

            return true;
        }
    
    }
}

Niby to blokowanie działa ale mam pewien problem. Załóżmy, że dochodzę do lewej ściany i kiedy jestem na pozycji X = 0 i nacisnę np. 5 razy lewą strzałkę to, żeby wejść na pozycję X = 1 muszę prawą strzałkę nacisnąć 6 razy. Wiem, że to dlatego ponieważ w switchu cały czas inkrementuje albo dekrementuje tą zmienną. Jakieś pomysły jak to obejść?

0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Snake
{
    class Character
    {
        public int X;
        public int Y;
        public int sizeX = 90;
        public int sizeY = 35;

        public void Snake()
        {
            Console.SetCursorPosition(X, Y);
            Console.WriteLine("#");
        }

        public void Movement()
        {
            ConsoleKeyInfo keyInfo;

            while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Escape)
            {
                switch (keyInfo.Key)
                {
                    case ConsoleKey.UpArrow:
                        Y--;
                        UpdatePosition();
                        break;
                    case ConsoleKey.RightArrow:
                        X++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.DownArrow:
                        Y++;
                        UpdatePosition();
                        break;
                    case ConsoleKey.LeftArrow:
                        X--;
                        UpdatePosition();
                        break;
                }
            }
            
        }

        public void UpdatePosition()
        {
            Console.Clear();
            if (CheckPosition() == true)
                Console.SetCursorPosition(X, Y);

            Console.Write("#");
            
        }

        public bool CheckPosition()
        {
            if (X < 0)
            {
                Console.SetCursorPosition(0, Y);
                return false;
            }

            else if (X >= Console.WindowWidth)
            {
                Console.SetCursorPosition(sizeX, Y);
                return false;
            }

            else if (Y < 0)
            {
                Console.SetCursorPosition(X, 0);
                return false;
            }

            else if (Y >= Console.WindowHeight)
            {
                Console.SetCursorPosition(X, sizeY);
            }

            return true;
        }
    
    }
}

Wygląda to sensowniej i działa lepiej ale z racji dosyć później godziny nic teraz nie wymyślę. Jakbyście podpowiedzieli co tu można zrobić lepiej, co jest nieestetycznie to byłbym wdzięczny. I takie pytanie jeszcze, przy prawej stronie oraz dolnej konsoli mogę wyjechać poza okno (?) tak mi się przynajmniej wydaję - aby stamtąd się "wydostać" muszę nacisnąć odpowiednią strzałkę więcej niż raz (żeby zobaczyć ruch na ekranie), jakieś propozycje?

0

W kodzie masz dwie pozycje:

  • pozycja gracza (X,Y) - pozycja uzywana przez logike w Twoim kodzie (int X, int Y)
  • pozycja awatara reprezentujacego gracza na ekranie (Console.SetCursorPosition(X, Y); + Console.Write("#"))

aktualnie pozycja Twojego awatara nie jest zmieniana gdy gracz probuje sie ruszyc ale pozycja gracza zmienia sie przez co masz efekt jak opisales wyzej

pozycja awatara w twoim kodzie zawsze powinna byc taka sama jak pozycja gracza, powinienes jedynie walidowac pozycje gracza czyli kod w stylu:

if (X > MaxX)
  X = MaxX;

celowo nikt nie podaje Ci gotowca przy podstawowych pytaniach, zebys tez sie czegos nauczyl

0

@krwq: Nie ten kod wkleiłem co trzeba. Tzn przy ruchu gracza miałem zrobione mniej-więcej tak jak napisałeś.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Snake
{
    class Character
    {
        public int X;
        public int Y;
        public int sizeX = 90;
        public int sizeY = 35;

        public void Snake()
        {
            Console.SetCursorPosition(X, Y);
            Console.WriteLine("#");
        }

        public void Movement()
        {
            ConsoleKeyInfo keyInfo;

            while ((keyInfo = Console.ReadKey(true)).Key != ConsoleKey.Escape)
            {
                switch (keyInfo.Key)
                {
                    case ConsoleKey.UpArrow:
                        if (Y <= 0)
                            Y = 0;
                        else
                            Y--;

                        UpdatePosition();
                        break;
                    case ConsoleKey.RightArrow:
                        if (X >= sizeX)
                            X = sizeX - 1;
                        else
                            X++;

                        UpdatePosition();
                        break;
                    case ConsoleKey.DownArrow:
                        if (Y > sizeY)
                            Y = sizeY - 1;
                        else
                            Y++;

                        UpdatePosition();
                        break;
                    case ConsoleKey.LeftArrow:
                        if (X <= 0)
                            X = 0;
                        else
                            X--;

                        UpdatePosition();
                        break;
                }
            }
            
        }

        public void UpdatePosition()
        {
            Console.Clear();
            if (CheckPosition() == true)
                Console.SetCursorPosition(X, Y);

            Console.Write("#");
            
        }

        public bool CheckPosition()
        {
            if (X < 0)
            {
                Console.SetCursorPosition(0, Y);
                return false;
            }

            else if (X >= Console.WindowWidth)
            {
                Console.SetCursorPosition(sizeX, Y);
                return false;
            }

            else if (Y < 0)
            {
                Console.SetCursorPosition(X, 0);
                return false;
            }

            else if (Y >= Console.WindowHeight)
            {
                Console.SetCursorPosition(X, sizeY);
            }

            return true;
        }
    
    }
}

Tylko w tym kodzie jest problem, bo dolna jak i prawa krawędź nie działają tak jak górna i lewa - gracz może wejść na pozycję większą niż rozmiary okna, ale większą tylko o 1.

0

Zauważ że 5 liczb ma wartości od 0 do 4. Tak samo jest z rozmiarami Twojej konsoli

1 użytkowników online, w tym zalogowanych: 0, gości: 1