Форум программистов, компьютерный форум, киберфорум
C# Windows Forms
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.91/34: Рейтинг темы: голосов - 34, средняя оценка - 4.91
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
1

Как перемешивать игру "Пятнашки"?

26.08.2014, 23:48. Показов 6585. Ответов 17
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Добрый день всем.

подскажите пожалуйста как перемешивать пятнашки


C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    private void стартToolStripMenuItem_Click( object sender, EventArgs e )
            {
            bool f = false;
 
 
 
            for( int i = 0; i < 4; i++ )
                for( int j = 0; j < 4; j++ )
                    {
                    
                    bool ok;
                    for( int x = 0; x < 4; x++ )
                        for( int y = 0; y < 4; y++ )
                            {  f = true;
                            ok = false;
                            while( !ok )
                                {
 
                                i = rand.Next ( 4 );
                                j = rand.Next ( 4 );
                                if( f == true )
                                    {
                                    ok = true;
                                    }
                                }
                            button[ i, j ].Location = new Point ( x, y );
                            button[ i, j ].Location = new Point ( x * 90, y * 90 + 30 );
 
                            }
                    }
            }
вот что у меня есть.
но этот код перемешивает и почему-то накладывает кнопку на кнопку.
подскажите где нужно исправить?
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
26.08.2014, 23:48
Ответы с готовыми решениями:

Как написать игру "Пятнашки"
Вот хотел написать игру пятнашки, примерно понимаю как это можно сделать. Когда кнопки...

Написать игру Пятнашки
Необходимо написать игру &quot;Пятнашки&quot; на WPF. Загружаем картинку, она разбивается на 16 квадратов,...

Как создать игру "пятнашки"
Игра пятнашки. Аналог хорошо известной игры «15». Игровое поле разбито на клетки 4×4. В...

Реализовать игру в пятнашки с консольным текстовым интерфейсом
Ребята. добрый день Нужна помощь. Реализовать игру в пятнашки с консольным текстовым...

17
8940 / 4852 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
27.08.2014, 01:02 2
Исправить нужно в подходе. Происходит то, о чем я и говорил: логика и интерфейс перепутались.
Итак, у тебя есть двумерный массив 4×4 (хотя можно обойтись одномерным, ну да ладно). Массив заполнен числами от 0 до 15. Чтобы его перемешать, нужно несколько раз, скажем 1000, менять местами случайные элементы массива. После перемешивания проходишься по всему массиву и соответственно расставляешь кнопки свои. Код сейчас не дам, т.к. пишу с телефона
2
Заблокирован
27.08.2014, 01:18 3
mixon-21, использовать рандом без повторений?
Код странный, зачем вам столько вложенных циклов?

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
        Button[,] buttons = new Button[4, 4];
        public Form1()
        {
            InitializeComponent();
            int x, y;
            for (int i = 0; i < 16; i++)
            {
                x = (i % 4);
                y = (i / 4) % 4;
                Button temp = new Button();
                temp.Location = new Point(x * 90, y * 90);
                temp.Name = "button" + i;
                temp.Size = new System.Drawing.Size(55, 46);
                temp.TabIndex = i;
                temp.Text = i.ToString();
                temp.UseVisualStyleBackColor = true;
                buttons[x, y] = temp;
 
            }
            foreach (Button t in buttons)
                Controls.Add(t);
            Button b17 = new Button();
            b17.Location = new System.Drawing.Point(505, 171);
            b17.Name = "button17";
            b17.Size = new System.Drawing.Size(55, 46);
            b17.TabIndex = 16;
            b17.Text = "Тыц";
            b17.UseVisualStyleBackColor = true;
            b17.Click += new System.EventHandler(button17_Click);
            Controls.Add(b17);
        }
 
        private void button17_Click(object sender, EventArgs e)
        {
            Random rand = new Random();
            List<int> range = new List<int>(); //последовательность от 0 до 15 в рандомном порядке
            while (range.Count != 16)
            {
                int a = rand.Next(0, 16);
                if (!range.Contains(a))
                    range.Add(a);
            }
            int x, y;
            for (int q = 0; q < 16; q++)
            {
                int i = range[q];
                x = (i % 4);
                y = (i / 4) % 4;
               // MessageBox.Show(i.ToString());
                Controls["button" + q].Location = new Point(x * 90, y * 90);
 
            }
 
        }
1
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
27.08.2014, 12:08  [ТС] 4
Цитата Сообщение от ViterAlex Посмотреть сообщение
Исправить нужно в подходе. Происходит то, о чем я и говорил: логика и интерфейс перепутались.
Итак, у тебя есть двумерный массив 4×4 (хотя можно обойтись одномерным, ну да ладно). Массив заполнен числами от 0 до 15. Чтобы его перемешать, нужно несколько раз, скажем 1000, менять местами случайные элементы массива. После перемешивания проходишься по всему массиву и соответственно расставляешь кнопки свои. Код сейчас не дам, т.к. пишу с телефона

если есть возможность напишмте код а то не могу понять.
0
Ev_Hyper
27.08.2014, 12:55
  #5

Не по теме:

mixon-21, интересно, почему вы мой ответ проигнорировали?

0
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
27.08.2014, 12:59  [ТС] 6
Цитата Сообщение от Ev_Hyper Посмотреть сообщение
Не по теме:
mixon-21, интересно, почему вы мой ответ проигнорировали?
Я Ваш код смотрел и не мог в нем разобраться.
0
2509 / 1130 / 582
Регистрация: 07.06.2014
Сообщений: 3,286
27.08.2014, 13:04 7
ещё, буду занудой. тут важно учесть, что не все случайные расклады имеют решение.
На форуме был алгоритм проверки - имеет конкретный расклад решение или нет.
Разумеется, варианты с нерешаемым расположением нужно отбрасывать!

Добавлено через 3 минуты
p.s. я бы взял простой одномерный массив на 16 элементов, заполнил его числами от нуля (это пусто) до 15.
один раз правильно перемешал.
проверил на сходимость (повторил перемешивание, если расклад плохой).
перевёл массив в кнопки.

вот и всё.
0
Заблокирован
27.08.2014, 13:12 8
mixon-21, так задавайте вопросы Пока прокомментировал:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
        Button[,] buttons = new Button[4, 4];
        public Form1()
        {
            InitializeComponent();
            int x, y; //переменные координат
            for (int i = 0; i < 16; i++)
            {
                //установка координат
                x = (i % 4);
                y = (i / 4) % 4;
                Button temp = new Button(); //создание кнопок 
                temp.Location = new Point(x * 90, y * 90);
                temp.Name = "button" + i;
                temp.Size = new System.Drawing.Size(55, 46);
                temp.TabIndex = i;
                temp.Text = i.ToString();//пронумерованы для того, чтобы было видно переиешивание
                temp.UseVisualStyleBackColor = true;
                buttons[x, y] = temp;
 
            }
            foreach (Button t in buttons) //помещаем созданные контролы на форму
                Controls.Add(t);
            //создаем кнопку, при нажатии на которую перемешиваются
            //предыдущие 16
            Button b17 = new Button();
            b17.Location = new System.Drawing.Point(505, 171);
            b17.Name = "button17";
            b17.Size = new System.Drawing.Size(55, 46);
            b17.TabIndex = 16;
            b17.Text = "Тыц";
            b17.UseVisualStyleBackColor = true;
            b17.Click += new System.EventHandler(button17_Click);
            Controls.Add(b17);
        }
 
        private void button17_Click(object sender, EventArgs e)
        {
            Random rand = new Random();
            List<int> range = new List<int>(); //последовательность от 0 до 15 в рандомном порядке
            while (range.Count != 16)//заполняем до тех  пор, пока в списке не будет всех чисел
            {
                int a = rand.Next(0, 16);
                if (!range.Contains(a)) //проверяем, находиться ли в списке сгенерированное число
                    range.Add(a);
            }
            int x, y;//координаты
            for (int q = 0; q < 16; q++)
            {
                int i = range[q];
                x = (i % 4);
                y = (i / 4) % 4;
                // MessageBox.Show(i.ToString());
                Controls["button" + q].Location = new Point(x * 90, y * 90);
                //так как кнопки находяться в списке контролов, то 
                //перемещаем кнопки последовательно, от первой к последней
            }
 
        }
 
    }
Запустите код, так быстрее разберетесь.

Цитата Сообщение от Sergio Leone Посмотреть сообщение
я бы взял простой одномерный массив на 16 элементов, заполнил его числами от нуля (это пусто) до 15.
один раз правильно перемешал.
Sergio Leone, именно это я и сделал
1
2509 / 1130 / 582
Регистрация: 07.06.2014
Сообщений: 3,286
27.08.2014, 13:26 9
Цитата Сообщение от Ev_Hyper Посмотреть сообщение
Sergio Leone, именно это я и сделал
зачем Вы меня и себя обманываете?
вы сделали НЕ ТАК.

C#
1
2
3
4
5
6
while (range.Count != 16)//заполняем до тех  пор, пока в списке не будет всех чисел
            {
                int a = rand.Next(0, 16);
                if (!range.Contains(a)) //проверяем, находиться ли в списке сгенерированное число
                    range.Add(a);
            }
вы генерите случайное число, проверяете, было ли оно раньше, если нет, до добавляете в массив, если такое число было - то повторяете цикл.

я же предлагал такое заполнение:
C#
1
2
3
4
5
  int[] mas=new int[16];
  for(int i=0;i<16;i++) 
  {
      mas[i] = i;
  }
1
Заблокирован
27.08.2014, 13:35 10
Sergio Leone, где обман? Или вы о том, что я взял список, а не массив?
Или я вас не так понял, и ключевой упор был именно на перемешивании, я взял чуть шире - подход к размещению. ИМХО - генерирование или перемешивание не так важно, это детали. Я использовал то, что было проще.
0
2509 / 1130 / 582
Регистрация: 07.06.2014
Сообщений: 3,286
27.08.2014, 13:41 11
Цитата Сообщение от Ev_Hyper Посмотреть сообщение
Я использовал то, что было проще.
вставьте в ваш код переменную, которую наращивайте при каждой генерации.
А потом выдайте.
Я Вам гарантирую, что Вам потребуется несколько десятков (явно больше 16), если не сотен циклов для генерации 16 значений. (если смотреть в динамике, то чем больше уже чисел в массиве, тем больше нужно циклов. особенно, когда мы уже 15 чисел запомнили. Получаем очередное число - а оно с вероятностью 15/16 уже есть в списке. Повторяем генерацию. И так многократно, пока не выпадет единственное отсутствующее число. Разве это не очевидно?!)
Впрочем, Вы правы, сейчас многие программы пишут так, как удобнее программисту, а не так, как быстрее или эффективнее.
0
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
27.08.2014, 17:22  [ТС] 12
Подскажите еще пожалуста как написать функцию которая проверяет выиграшную комбинацию.
0
8940 / 4852 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
27.08.2014, 17:59 13
Цитата Сообщение от mixon-21 Посмотреть сообщение
функцию которая проверяет выиграшную комбинацию.
Выигрышная комбинация будет только тогда, когда каждый элемент массива будет на своём месте, а последним элементом будет 0. Проверяется это так:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
bool IsWin(int[,] ar) {
    int n = ar.GetUpperBound(1) + 1;
    int maxI = ar.GetUpperBound(0), maxJ = ar.GetUpperBound(1);
    for (int i = 0; i <= maxI; i++) {
        for (int j = 0; j <= maxJ; j++) {
            //Проверка, что последний элемент массива равен нулю (пустая клетка)
            if ((i == maxI && j == maxJ) && ar[i,j]==0)
                return true;
            //Проверка, что каждый номер стоит на своём месте
            if (ar[i, j] != i * n + j + 1) {
                return false;
            }
        }
    }
    return true;
}
А не дай бог проверять это по расположению кнопок
1
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
27.08.2014, 18:59  [ТС] 14
Что-то не получается.
незнаю куда вставить эу функцию?
bool IsWin(int[,] ar)
вот код

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
 
namespace Пятнашки
    {
    public partial class Form1 :Form
        {
 
        MyButton[ , ] button = new MyButton[ 4, 4 ];
        int W = 90;
        int H = 90;
        int Sum = 0;
        public Form1()
            {
            InitializeComponent ();
            }
 
        private void Form1_Load( object sender, EventArgs e )
            {
            int x, y;
            for( int i = 0; i < 16; i++ )
                {
                x = ( i % 4 );
                y = ( i / 4 ) % 4;
                MyButton temp = new MyButton ();
                temp.Name = "button" + i;
                temp.Size = new Size ( W, H );
                temp.Text = "" + ( i + 1 );
                temp.Location = new Point ( x * W, y * H + 30 );
                temp.Click += new System.EventHandler ( temp_Click );
                temp.UseVisualStyleBackColor = true;
                button[ x, y ] = temp;
                }
            foreach( MyButton t in button )
                {
 
                Controls.Add ( t );
                t.BackColor = Color.MediumSeaGreen;
                t.Font = new Font ( "Arial", 24 );
 
                if( t.Text == "16" )
                    {
                    t.Text = "";
                    t.BackColor = Color.OrangeRed;
                    }   
                }
            }
 
                private void temp_Click( object sender, EventArgs e )
            {
            MyButton myBtn = ( MyButton ) sender;
            int x = Math.Abs ( myBtn.Location.X - button[ 3, 3 ].Location.X );
            int y = Math.Abs ( myBtn.Location.Y - button[ 3, 3 ].Location.Y );
            if( ( x == 90 && y == 0 ) || ( x == 0 && y == 90 ) )
                {
                Point P = myBtn.Location;
                myBtn.Location = button[ 3, 3 ].Location;
                button[ 3, 3 ].Location = P;
                myBtn.Location = new Point ( myBtn.Location.X, myBtn.Location.Y );
                button[ 3, 3 ].Location = new Point ( button[ 3, 3 ].Location.X, button[ 3, 3 ].Location.Y );
                }
                    
                 Sum++;
            labelClick.Text ="Ходов="+ Sum.ToString ();
            
            }
 
                private void стартToolStripMenuItem_Click( object sender, EventArgs e )
                    {
                    
                    Random rand = new Random ();
                    List<int> range = new List<int> (); //последовательность от 0 до 15 в рандомном порядке
                    while( range.Count != 16 )//заполняем до тех  пор, пока в списке не будет всех чисел
                        {
                        int a = rand.Next ( 0, 16 );
                        if( !range.Contains ( a ) )
                            range.Add ( a );
                        }
                    int x, y;
                    for( int q = 0; q < 16; q++ )
                        {
                        int i = range[ q ];
                        x = ( i % 4 );
                        y = ( i / 4 ) % 4;
 
                        Controls[ "button" + q ].Location = new Point ( x * 90, y * 90 + 30 );
                        }
                       Sum = 0;
                    labelClick.Text = "Ходов=" + Sum.ToString ();
                    }
                
        }
    }
0
8940 / 4852 / 1886
Регистрация: 11.02.2013
Сообщений: 10,246
27.08.2014, 19:31 15
А это к тому, что логику нужно отделять от интерфейса. В том виде, в каком это сейчас у тебя есть, искать решение слишком бессмысленная задача. Хотя и решаемая
0
5 / 5 / 3
Регистрация: 05.03.2013
Сообщений: 220
27.08.2014, 19:51  [ТС] 16
Цитата Сообщение от ViterAlex Посмотреть сообщение
А это к тому, что логику нужно отделять от интерфейса. В том виде, в каком это сейчас у тебя есть, искать решение слишком бессмысленная задача. Хотя и решаемая
в принципе я понял что эту функцию нужно вставить в private void temp_Click( object sender, EventArgs e )

но куда деть масив ar[,]?

Добавлено через 4 минуты
Цитата Сообщение от ViterAlex Посмотреть сообщение
А это к тому, что логику нужно отделять от интерфейса. В том виде, в каком это сейчас у тебя есть, искать решение слишком бессмысленная задача. Хотя и решаемая
Куда вставить функцию я разобрался в private void temp_Click( object sender, EventArgs e )

но я незнаю что делать с масивом int[,] ar?
0
Эксперт .NET
17685 / 12871 / 3365
Регистрация: 17.09.2011
Сообщений: 21,136
28.08.2014, 12:36 17
Если кому-то интересно, то вот код, который генерирует поле указанного размера с гарантированным решением за O(2n), где за первый обход генерируется выигрышная комбинация (тайлы по порядку), а за второй поле перемешивается. Пустое поле обозначено нулем:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
unsafe int[,] GenerateBoard(int width, int height)
{
    var board = new int[height, width];
 
    int length = board.Length;
    int blank = 0;
    var r = new Random();
 
    fixed (int* arr = board)
    {
        // Генерация выигрышной комбинации упорядоченных тайлов от 1 до n с пустой клеткой в нижнем правом углу.
        for (int i = 0; i < length - 1; i++)
            arr[i] = i + 1;
 
        // Перемешивание поля
        for (int i = length - 1; i > 0; i--)
        {
            int j = r.Next(i);
            Swap(ref arr[i], ref arr[j]);
            if (arr[i] == 0) blank = i;
        }
 
        // Проверка на наличие решения
        if (blank % 2 == length % 2)
        {
            int a = (blank + 1) % length;
            int b = (blank + 2) % length;
 
            Swap(ref arr[a], ref arr[b]);
        }
    }
 
    return board;
}
 
void Swap<T>(ref T a, ref T b)
{
    T c = a;
    a = b;
    b = c;
}
Небезопасный код добавил для того, чтобы работать с двумерным массивом сразу как с одномерным, без создания промежуточного одномерного и последующего копирования в двумерный.
1
Заблокирован
28.08.2014, 15:30 18
Лучший ответ Сообщение было отмечено mixon-21 как решение

Решение

mixon-21, как вариант:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
//..вызов (проверка при каждом ходе)
       if (func()) MessageBox.Show("Победа");
        }
 
        private bool func()
        {
            int x, y;
            for (int i = 0; i < 16; i++)
            {
                x = (i % 4);
                y = (i / 4) % 4;
                if (Controls["button" + i].Location.X != x * W || Controls["button" + i].Location.Y != y * H + 30)
                    return false;
 
            }
            return true;
        }
1
28.08.2014, 15:30
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
28.08.2014, 15:30
Помогаю со студенческими работами здесь

Добавить использование шаблонов проектирования в игру "Пятнашки"
Есть реализация игры пятнашки, нужно сделать откат предыдущего хода, выбор уровня сложности (рохмир...

Как лучше всего реализовать игру пятнашки?
Мне хотелось бы услышать советы по реализации такой игры. Интересует вопросы, как лучше сделать...

Пишу игру пятнашки
Пишу игру пятнашки с использованием openGL(библиотеки glut) и ООП. Проблема возникла в следущей...

Создайте игру «Пятнашки»
Создайте игру «Пятнашки». Главные особенности реализации игры: ■ Выбор режима игры: • 8 (3×3);...

Подправьте игру пятнашки
Решил написать игрушку 15-ки я хочу что бы прога содержала такие функции: заполнение поля...

реализовать игру пятнашки
Игра размером 3х3. С поиском в глубину( не обязательно, по возможности)

Написать игру пятнашки на qt
Задали написать игру пятнашки на qt. на qt писал ранее калькулятор. подскажите, с чего начать...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
18
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru