Я не могу понять, что идет не так [закрыт]

91
01 июня 2021, 13:40
Закрыт. Этот вопрос не по теме. Ответы на него в данный момент не принимаются.

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском.

Закрыт 1 год назад.

Улучшить вопрос

Я делаю маленькую консольную игрушку, в ней я решил реализовать случайное генерирование карты. Но дело в том, что каждый раз, при возвращении в ту же точку, ее содержимое меняется. Вот пример из "реальной" жизни.

Вы переехали в новый город. Пошли в магазин, возвращаетесь домой - а там уже водоем. Возвращаетесь обратно в магазин - а там уже парк. Вот так ведет себя мой код.

using System;
using System.Collections.Generic;
namespace Adventure
{
    class MainClass
    {
        static int x = 0;
        static int y = 0;
        static Random rnd = new Random();
        static int biome = 0;
        static IDictionary<Tuple<int, int>, int> map = new Dictionary<Tuple<int, int>, int> ();
        public static void Main ()
        {
            Console.WriteLine ("\nSet X");
            int.TryParse(Console.ReadLine(), out x);
            Console.WriteLine ("Set Y");
            int.TryParse(Console.ReadLine(), out y);
            Console.WriteLine (x.ToString() + " " + y.ToString() + " | " + biome.ToString());
            MapGen ();
            Main();
    }
    static int MapGen (){
        Tuple<int, int> coords = Tuple.Create (x, y);
        if(map.ContainsKey(coords)){ // If map already has this place generated, then load it, otherwise generate and save.
            map.TryGetValue(coords, out biome);
        }else{
            biome = rnd.Next(0, 6); //0-plains, 1-forest,2-hills,3-taiga,4-desert,5-cave,6-city
            map.Add (coords, biome);
        }
        return biome;
    }
}

}

При этом x, y - поля с типом int, в то время как map - поле типа Dictionary. В методе проводится проверка на наличие координат в словаре, если нет - сгенерировать пространство и записать его в словарь, а если же есть-прочитать в словаре, что на них находится и рассказать об этом при помощи return biome;. Спасибо.

Во втором методе, который main, я пробовал вызывать MapGen() в разных местах: в начале, в конце, после перемещения на новые координаты, не работает. UPD: Заменил массив в Dictionary на Tuple, я догадался, как он работает.

Answer 1

Поменяйте:

Console.WriteLine (x.ToString() + " " + y.ToString() + " | " + biome.ToString());
MapGen ();

на:

MapGen ();
Console.WriteLine (x.ToString() + " " + y.ToString() + " | " + biome.ToString());

У вас значение biome для введенных координат задается в MapGen, а выводите вы его до вызова этого метода. Вот и получается, что координаты уже новые, а значение biome все еще старое. Отсюда и ощущение что что-то работает не так, хотя на самом деле неправильно только отображается.

В этом легко убедиться в режиме отладки, если поставить точку останова в конце вызова MapGen и посмотреть содержимое словаря или просто выполнить программу в пошаговом режиме.

Текущий код с Tuple корректно работает со словарем, разве что лично я бы более короткий синтаксис использовал.

Условие в MapGen можно переписать немного короче

if(!map.TryGetValue(coords, out biome))
{
    biome = rnd.Next(0, 6);city
    map.Add (coords, biome);
}

Работать будет ровно так же.

Вместо Tuple можно использовать структуру

struct Coords
{
    public int X { get; set; }
    public int Y { get; set; }
    public Coords(int x, int y) { X = x; Y = y; }
}

Фокус заключается в том, что структуры в C# - это Value Type и базовые реализации GetHashCode() и Equals() структур учитывают содержимое, поэтому они могут применяться в качестве ключей словаря без дополнительных танцев с бубном компаратором, если конечно не требуется какое-то особое сравнение, отличное от по-байтового, например строго по значению одного поля, без учета остального содержимого.

С классом такой фокус не пройдет (массив это класс), потому что базовые реализации GetHashCode() и Equals() учитывают только совпадение ссылок и их нужно будет переопределять самостоятельно, либо писать компаратор для словаря.

READ ALSO
Как сохранить pdf файл из iframe на сервере?

Как сохранить pdf файл из iframe на сервере?

Веб-приложение ASPNET Core MVC + c#

121
Unity движение персонажа

Unity движение персонажа

Скачал SimpleTouchController, все в нем ок, создаю сцену, помещаю туда объект, вешаю на него этот контроллер и начинается приколы, если джойстик внизу...

91
Враги должны воспринимать друг друга, как препятствие. Unity2D, C# [дубликат]

Враги должны воспринимать друг друга, как препятствие. Unity2D, C# [дубликат]

Мне нужно сделать так, чтобы враги обходили друг друга, потому что они просто проходят сквозь, а когда гонятся за игроком и вовсе сливаются...

89
Лагает текстовый редактор при большом кол-ве строк в исходном коде

Лагает текстовый редактор при большом кол-ве строк в исходном коде

У меня класс содержит более 600 строк кода, переносы я делаю не так часто, а когда код не вмещается в строку

92