1

Тема: 15 puzzle

Написати консольну реалізацію гри п'ятнашки. Забезпечити вибір розмірності поля і рівня складності (наскільки сильно дошка відрізняється від стану «перемога»), зробити можливість гри з ускладненням, коли замість ходу заданого користувачем відбувається деяка кількість рандомних ходів. Реалізувати можливість скасування ходів.
З використанням патернів: Сінглетон, Фабричний метод, Команда, збереження.

Присутня тільки зміна ігрового поля й то не через патерни а ще потрібно зробити відкат ходів я так зрозумів з допомогою паттерна збереження але щось не виходить допоможіть.

using System;

//Game.cs
namespace puzzle15
{
    class Points
    {
        public readonly int x, y;
        public Points(int x, int y)
        {
            this.x = x;
            this.y = y;
        }
    }
    class Game
    {
        public int Length=0;
        const int nw = 4, height = 4;
        int[,] field = new int[nw, height];
        Points[] FieldValue = new Points[16];
        

        public Game(int[] point)
        { 

            int r = 0;
            string[] file = new string[4];
            Length = 16;
          
            mixer(point);

            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < nw; i++)
                {
                    field[j, i] = point[r];
                    FieldValue[point[r]] = new Points(j, i);
                    r++;

                }
            }
          
        }

        public void mixer(int[] p)
        {

            int tmp = 0;

            Random rnd = new Random();

            for (int i = 0; i < 16; i++)
            {
                bool isExist = false;
                do
                {
                    isExist = false;
                    tmp = rnd.Next(0, 16);
                    for (int j = 0; j < i; j++)
                    {
                        if (tmp == p[j]) { isExist = true; }
                    }
                }
                while (isExist);
                p[i] = tmp;
            }
        }

        private Points GetLocation(int value)
        {

            return FieldValue[value];
        }


        public void drawField()
        {

            Console.WriteLine("----------------------------");
            for (int i = 0; i < nw; i++)
            {
                for (int j = 0; j < height; j++)
                {
                    Console.Write(field[i, j] + "\t");

                }
                Console.WriteLine();

            }

            Console.WriteLine("----------------------------");

        }

        public bool repeat(double Length,int[] point)
        {

            for (int i = 0; i < Length; ++i)
            {
                for (int y = i + 1; y < Length; ++y)
                {
                    if (point[i] == point[y])
                    {
                        Console.WriteLine(point[i] + " ==" + point[y]);
                        throw new ArgumentException("Numbers should not be repeated");
                    }


                }
            }
            return true;
        }

        public Boolean finish()
        {
            bool temp = false;
            int value = 1;
            for (int i = 0; i < nw; ++i)
            {
                for (int j = 0; j < height; ++j)
                {
                    if (field[i, j] == value)
                    {

                        temp = true;
                        ++value;
                        if (value == Length)
                        {
                            value = 0;
                        }
                    }
                    else
                    {
                        return false;
                    }

                }

            }      
            return temp;

        }

        public void Move(int value)
        {

            try
            {
            Console.WriteLine(value);
            if (value > 15 || value < 0)
            {
                throw new ArgumentException();
            }

            int x = GetLocation(0).x;
            int y = GetLocation(0).y;

            int ValueX = GetLocation(value).x;
            int ValueY = GetLocation(value).y;

                if ((ValueX == x && (ValueY == y - 1 || ValueY == y + 1))||(ValueY == y && (ValueX == x - 1 || ValueX == x + 1)))
                {

                    field[x, y] = value;
                    field[ValueX, ValueY] = 0;

                    var vere = FieldValue[0];
                    FieldValue[0] = FieldValue[value];
                    FieldValue[value] = vere;
                }

            }

            catch (ArgumentException)
            {
                Console.WriteLine("There is no such number, try again: ");
            }
            catch (Exception)
            {
                Console.WriteLine("Next to this number is not 0, try again: ");
            }
            
        }
      
    }


    //--------------------------------------------------------------------------------------------------------------------------------------------------------


    class Points2
    {
       ..............................................................................................
    }
    class Game2
    {
        public int Length = 0;
        const int nw = 3, height = 3;
        int[,] field = new int[nw, height];
        Points[] FieldValue = new Points[9];


        public Game2(int[] point)
        {

            int r = 0;
            string[] file = new string[3];
            Length = 9;

            mixer(point);

            for (int j = 0; j < height; j++)
            {
                for (int i = 0; i < nw; i++)
                {
                    field[j, i] = point[r];
                    FieldValue[point[r]] = new Points(j, i);
                    r++;

                }
            }

        }

       .................................................................................................

    }

}


//Program.cs
using System;
using System.Collections.Generic;


namespace puzzle15
...............................................................................................

//вот код начало хранителя
    class GameHistory
    {
        public Stack<Game> History { get; private set; }
        public GameHistory()
        {
            History = new Stack<Game>();
        }
    }

   
}

2

Re: 15 puzzle

а що таке ті п'ятнашки?

3

Re: 15 puzzle

https://uk.wikipedia.org/wiki/%D0%9F%27 … 0%BA%D0%B8

4

Re: 15 puzzle

мені один вумний чувак на співбесіді казав, що за допомогою патерна Команда можна робити реплеї в іграх, а ще я чув, що цей патерн може допомогти з undo redo.
Наскільки пам'ятаю, воно з себе представляю дію, з котрою можна робити певні маніпуляції. Наприклад, запихати в стек, а потім випихати назад, таким чином робити undo.
Сінглтон ви, певно, розумієте, бо воно найпростіше і не в пошані серед крутих мегапрограмістів хіпстерів.
Хвабричний метод, то має бути тупо метод, котрий приймає деякі параметри, і повертає вам об'єкт відконфігурований тими параметрами.
Про збереження нічо не чув, якщо чесно.

З розмірністю поля все ясно, а от зі складністю - хз. Можливо її можна зробити, якщо перед початком гри спочатку сортувати поле, а потім випадковим чином переміщати декілька циферок. При цьому, чим більша складність, тим більше перестановок.

зробити можливість гри з ускладненням, коли замість ходу заданого користувачем відбувається деяка кількість рандомних ходів

оце взагалі не з нашої планети, навіщо тоді нам взагалі потрібен користувач? можна ж якогось скрипта написати, котрий кожного разу буде робити той самий хід, і від цього нічого особливо не зміниться.
****************************************************
Я б зробив клас Поле, котре б містило в собі поля  Ширина та Висота, а також масив з об'єктами Клітинка (можна двомірний, якщо вам так здається логічнішим).
Далі я б додав метода Зміна, котрий приймав ми об'єкт типу Перестановка.  Кожен об'єкт типу Перестановка містить два поля - Номер_поля, та Напрямок_перестановки. Напрямок_перестановки можна зробити enum'ом з варіянтами Up, Right, Down, Left.
Коли метод Зміна приймає об'єкт Перестановка, то він перевіряє, чи Номер_поля не виходить за краї поля, і так само перевіряє, чи ми можемо піти в Няпрямок_перестановки. Якщо можемо, то йдемо, і додаємо в стек об'єкт Перестановка. Цей стек буде належати самому Полю.
Тоді ми зможемо зробити метод Undo, котрий би витягував зі стеку останню Перестановка, і відправляв би її в метод Зміна.
А фабричним методом була б якась хвункція, котра приймає Ширина, Висота, Складність і повертає Поле з заданими параметрами.

Ну, ви зрозуміли.

Подякували: LoganRoss, leofun012

5

Re: 15 puzzle

FakiNyan написав:

зробити можливість гри з ускладненням, коли замість ходу заданого користувачем відбувається деяка кількість рандомних ходів

оце взагалі не з нашої планети, навіщо тоді нам взагалі потрібен користувач? можна ж якогось скрипта написати, котрий кожного разу буде робити той самий хід, і від цього нічого особливо не зміниться.

Згідний. Пазли - це не та гра, аби комп'ютер щось складав, та і які рандомні ходи можуть бути, якщо якийсь пазл підходить тільки до однієї клітинки.
Може ви мали на увазі рандомний вибір поля. Тобто, перший раз треба зібрати пазл 10х10, потім 4х4 і т.д. рандомно.
FakiNyan запропонував хороший алгоритм, візьміть до уваги.

Подякували: FakiNyan1