Модераторы: Partizan, gambit
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Парные картинки на C#, Создание игры парные картинки на C# 
:(
    Опции темы
kelmiir
Дата 3.5.2013, 14:17 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



Приветствую обитателей форума и прошу помощи.
C# начал изучать совсем недавно и до этого сталкивался только с Паскалем
По заданию нужно разработать игру "Парные картинки"
Приложение сделать получилось но работает как попало (пары не всегда убираются, парой открываются по 3 картинки и т.д.).
Полагаю ошибка где то в логике обработки кликов по картинкам но как исправить не знаю.

Код

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 mein : Form
    {
        const int nw = 6; // кол-во клеток по горизонтали
        const int nh = 6; // кол-во клеток по вертикали
        const int np = (nw * nh) / 2; // кол-во пар картинок
        System.Drawing.Graphics g; // рабочие графическое поле
        Bitmap pics; // картинки (загружаются из файла)
        int cw, ch; // размеры клетки(картинки)
        int[,] field = new int[nw, nh]; // игровое поле

// field[i,j] == 1...k - клетка закрытая (k - номер клетки)
// field[i,j] == 101 ... (100+k)  - клетка открыта ( игрок видит картинку)
// field[i,j] == 201 ... (200+k) - клетке картинка для которой найдена пара

        int nopened = 0; //кол-во открытых клеток (найденных) пар картинок
        int copened = 0; // кол-во открытых клеток в данный момент
        int[] open1 = new int[2]; // координаты 1й открытой клетки
        int[] open2 = new int[2]; // координаты 2й открытой клетки
        System.Windows.Forms.Timer timer1; // таймер

// нарисовать картинку
// картинку если клетка открыта
// границу если клетка закрыта
// вон если в клетке картинка для которой найдена пара

        private void cell(int i, int j)
        {
            int x, y; // координаты верхнего левого угла

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

            x = i * (cw + 2);
            y = j * (ch + 2) + meinmenu.Height;

            if (field[i, j] > 200)

// для этой клетки найдена пара
// картинку отображать не надо

                g.FillRectangle(SystemBrushes.Control, x, y, cw + 2, ch + 2);

            if ((field[i, j] > 100) && (field[i, j] < 200))
            {
// клетка открыта - отображать картинку 

                g.DrawImage(pics,
                    new Rectangle(x + 1, y + 1, cw, ch),
                    new Rectangle((field[i, j] - 101) * cw, 0, cw, ch),
                    GraphicsUnit.Pixel);
                g.DrawRectangle(Pens.Black, x + 1, y + 1, cw, ch);
            }
            if ((field[i, j] > 0) && (field[i, j] < 100))
            {
// клетка закрыта, рисуем контур
                g.FillRectangle(SystemBrushes.Control, x + 1, y + 1, cw, ch);
                g.DrawRectangle(Pens.Black, x + 1, y + 1, cw, ch);
            }
        }

// нарисовать поле

        private void drawfield()
        {
            for (int i = 0; i < nw; i++)
                for (int j = 0; j < nh; j++)
                    this.cell(i, j);
        }

// новая игра
        private void newgame()
        {
// распределяем пары картинок по игровому полю
// запишем в массив field случайные числа
// от 1 до k, где k - количество картинок
// каждое число число должно быть записано
// в массив 2 раза

            Random rnd; // генератор случайных чисел
            int rndn; // случайное число
            rnd = new Random();
            int[] buf = new int[np];

// np - кол-во картинок
// в buf(i) Записываем сколько i чисел
//(идентификаторов картинок) записано в массив field
            for (int i = 0; i < nw; i++)
                for (int j = 0; j < nh; j++)
                {
                    do
                    {
                        rndn = rnd.Next(np) + 1;
                    } while (buf[rndn - 1] == 2);
                    field[i, j] = rndn;
                    buf[rndn - 1]++;
                }
            nopened = 0;
            copened = 0;
            this.drawfield();
        }




        public mein()
        {

            InitializeComponent();
            this.MouseClick += new MouseEventHandler(mein_MouseClick);
            try
            {
// загружаем файл с картинками
                pics = new Bitmap("pictures.bmp");
            }
            catch (Exception exc)
            {
                MessageBox.Show("Файл 'pictures.bmp' не найден.\n" +
                    exc.ToString(), "Парные картинки",
                    MessageBoxButtons.OK,
                    MessageBoxIcon.Error);
                this.Close();
                return;
            }

// определяем размер картинки и устанавливаем
// размер клеток игрового поля
            cw = (int)(pics.Width / np);
            ch = pics.Height;

// установить размер клиентской области формы
// в соответствие с размером картинок и их кол-ва
// (смотреть определение констант cw и ch

            this.ClientSize =
                new System.Drawing.Size(nw * (cw + 2) + 1,
                    nh * (ch + 2) + 1 + meinmenu.Height);

// работа с графической поверхностью

            g = this.CreateGraphics();

// создать объект Timer1
            timer1 = new Timer();
            timer1.Tick +=
                new System.EventHandler(this.timer1_Tick);
            timer1.Interval = 200;
            newgame();
            
        }
        
// щелчок по игровому полю

        private void mein_MouseClick(object sender, MouseEventArgs e)
        {
            {
// индексы элементов массива field 
// соответствуещего клетке в которой
// сделан щелчок
                int i, j;

                i = e.X / (cw + 3);
                j = (e.Y - meinmenu.Height) / (ch + 3);

// если таймер работает, это значит, что в данный
// момент открыты две клетки, в которых находятся
// одинаковые картинки, но они ещё не "стерты"
// если щелчок сделан в одной из этих картинок,
// то ничего делать не надо.

                if ((timer1.Enabled) && (field[i, j] > 200))
                {
                    return;
                }

// щелчок на месте одной из двух уже найденных
// пар картинок

                if (field[i, j] > 200) return;

// открытых картинок нет
                if (copened == 0)
                {
                    copened++;

// записываем координаты 1й открытой клетки
                    open1[0] = 1; open1[1] = j;
                    field[i, j] += 100; // клетка помечена как открытая
                    this.cell(i, j); // отрисовать клетку
                    return;
                }
// открыта одна клетка, надо открыть вторую
                if (copened == 1)
                {
// записываем координаты 2й открытой клетки
                    open2[0] = i; open2[1] = j;

// если открыта одна клетка , и щелчок сделан 
// в той же клетке, ничего не происходит
                    if ((open1[0] == open2[0]) && (open1[1] == open2[1]))
                        return;
                    else
                    {
// теперь открыты 2 клетки
                        copened++;

                        field[i, j] += 100; // клетка помечена как открытая
                        this.cell(i, j); // отрисовываем клетку

// открыты 2 одинаковые картинки
                        if (field[open1[0], open1[1]] == field[open2[0], open2[1]])
                        {
                            nopened++;
// пометим клетки как найденые
                            field[open1[0], open1[1]] += 100;
                            field[open2[0], open2[1]] += 100;
                            copened = 0;
// запускае таймер. процедура обработки
// сигнала от таймер "сотрет" клетки
// которые с одинаковыми картинками
                            timer1.Enabled = true;
                        }
                    }
                    return;
                }
// открыты 2 клетки но в них разные картинки,
// закроем их и откроем ту клетку, в которой сделан щелчок

                if (copened == 2)
                {
// закрываем открытые клетки
                    field[open1[0], open1[1]] -= 100;
                    field[open2[0], open2[1]] -= 100;
                    this.cell(open1[0], open1[1]);
                    this.cell(open2[0], open2[1]);
// записываем в open1 номер текущей клетки

                    open1[0] = i; open1[1] = j; 
                    copened = 1; // счетчик открытых клето
// открыть клетку в которой сделан щелчок
                    field[i, j] += 100;
                    this.cell(i, j);
                }
            } 
        }
// команда новая игра

        private void newgameToolStripMenuItem_Click(object sender, EventArgs e)
        {
            newgame();
        }
// обработка события таймер
        private void timer1_Tick(object sender, System.EventArgs e)
        {
// отрисовать клетку
            this.cell(open1[0], open1[1]);
            this.cell(open2[0], open2[1]);
// остановить таймер
            timer1.Enabled = false;
            if (nopened == np)
            {
                MessageBox.Show("Вы спавились с поставленной задачей!");
            }
        }
        private void mein_Paint(object sender, PaintEventArgs e)
        {
            drawfield(); // отрисовать игровое поле
        }

        private void infoprogramToolStripMenuItem_Click(object sender, EventArgs e)
        {
            AboutBox1 aboutbox;
            aboutbox = new AboutBox1();
            aboutbox.Show();
           
        }
    }
}


Это сообщение отредактировал(а) kelmiir - 5.5.2013, 15:55
PM MAIL   Вверх
Экскалупатор
Дата 5.5.2013, 12:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



я бы начал с приведения всего кода в адекватный ЧИТАЕМЫЙ вид. надо дать понятные названия переменным. иначе что бы разобраться в этой писанине потребуется немало времени.
Цитата(kelmiir @  3.5.2013,  13:17 Найти цитируемый пост)
open2[0] = i; open2[1] = j;

тут как мне показалось какая то странная попытка хранить координаты в массиве, зачем? странность в том, что у тебя, как я понял, хранятся разные координаты в одном массиве и ты просто должен помнить что [0] - это по x, а [1] - это у. вероятность запутаться увеличивается в разы. да и не понятно что такое "open2" без прочтения кода. а должно быть понятно, смотришь на строку и сразу понятно что и откуда берется. я думаю если ты в нормальный вид приведешь свой код, то и выяснится по пути то почему не работает.

Это сообщение отредактировал(а) Экскалупатор - 5.5.2013, 12:57
PM MAIL ICQ   Вверх
kelmiir
Дата 5.5.2013, 15:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



Извините об этом как то не задумался..Спасибо за совет теперь добавил в код комментарии.
Делал по пособию по этому сам не до конца понимаю, что да как в этом коде.
Код пришлось слегка переделать под мое задание да и немного ошибок в печати было.
Нашел малость недочетов ещё у себя но по прежнему работает приложение не правильно.
Почему то всегда отображается картинка открытая по первому клику даже если ей находится пара.

PM MAIL   Вверх
Экскалупатор
Дата 5.5.2013, 22:44 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(kelmiir @  3.5.2013,  13:17 Найти цитируемый пост)
 if (field[i, j] > 200)
// для этой клетки найдена пара
// картинку отображать не надо
                g.FillRectangle(SystemBrushes.Control, x, y, cw + 2, ch + 2);
            if ((field[i, j] > 100) && (field[i, j] < 200))
            {
// клетка открыта - отображать картинку 
                g.DrawImage(pics,
                    new Rectangle(x + 1, y + 1, cw, ch),
                    new Rectangle((field[i, j] - 101) * cw, 0, cw, ch),
                    GraphicsUnit.Pixel);
                g.DrawRectangle(Pens.Black, x + 1, y + 1, cw, ch);
            }
            if ((field[i, j] > 0) && (field[i, j] < 100))
            {
// клетка закрыта, рисуем контур
                g.FillRectangle(SystemBrushes.Control, x + 1, y + 1, cw, ch);
                g.DrawRectangle(Pens.Black, x + 1, y + 1, cw, ch);
            }


а может быть (field[i, j] == 100 или (field[i, j] == 200 или (field[i, j] == 0
???
или такие ситуации невозможны?

дальше, в этом куске:
Цитата(kelmiir @  3.5.2013,  13:17 Найти цитируемый пост)
// открыта одна клетка, надо открыть вторую
                if (copened == 1)
                {
// записываем координаты 2й открытой клетки
                    open2[0] = i; open2[1] = j;
// если открыта одна клетка , и щелчок сделан 
// в той же клетке, ничего не происходит
                    if ((open1[0] == open2[0]) && (open1[1] == open2[1]))
                        return;
                    else
                    {
// теперь открыты 2 клетки
                        copened++;
                        field[i, j] += 100; // клетка помечена как открытая
                        this.cell(i, j); // отрисовываем клетку
// открыты 2 одинаковые картинки
                        if (field[open1[0], open1[1]] == field[open2[0], open2[1]])
                        {
                            nopened++;
// пометим клетки как найденые
                            field[open1[0], open1[1]] += 100;
                            field[open2[0], open2[1]] += 100;
                            copened = 0;
// запускае таймер. процедура обработки
// сигнала от таймер "сотрет" клетки
// которые с одинаковыми картинками
                            timer1.Enabled = true;
                        }
                    }
                    return;
                }
// открыты 2 клетки но в них разные картинки,
// закроем их и откроем ту клетку, в которой сделан щелчок
                if (copened == 2)
                {
// закрываем открытые клетки
                    field[open1[0], open1[1]] -= 100;
                    field[open2[0], open2[1]] -= 100;
                    this.cell(open1[0], open1[1]);
                    this.cell(open2[0], open2[1]);
// записываем в open1 номер текущей клетки
                    open1[0] = i; open1[1] = j; 
                    copened = 1; // счетчик открытых клето
// открыть клетку в которой сделан щелчок
                    field[i, j] += 100;
                    this.cell(i, j);
                }
            } 

я так понимаю, что при попадании в первый иф и если картинки две но не одинаковые то из метода обработки мы все равно выйдем, но картинки не уберем с экрана? т.е. return в конце первого ифа сработает в любом случае и во второй иф мы не попадем никогда, только при следующем заходе в метод. или тут как то по другому работает?

p.s. я про понятность кода говорил не про коментарии, а про то что надо давать нормальные названия переменным.
как из записи:
if (field[open1[0], open1[1]] == field[open2[0], open2[1]])
можно понять что вообще тут с чем сравнивается? приходится постоянно бегать в начало листинга и смотреть че это вообще за хрень и за что она отвечает?
если бы было написано как то так(просто пример):
if (firstSelectedImage == secondSelectedImage)
то все было бы на порядок понятнее и читаемее и уже давно можно было бы найти все ошибки.

p.p.s. если собираешься заниматься этим в дальнейшем(после сдачи "курсовой"), пусть даже на другом языке, то очень рекомендую научиться делать нормальные имена и оформление кода в целом.

Это сообщение отредактировал(а) Экскалупатор - 5.5.2013, 22:45
PM MAIL ICQ   Вверх
kelmiir
Дата 7.5.2013, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



Если честно как и писал выше делал по пособию..и как раз откуда идут эти значения 0, 100, 200, и тд да и вообще почему именно они как раз не могу понять.
PM MAIL   Вверх
Экскалупатор
Дата 7.5.2013, 12:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



посмотри на метод который обрабатывает клик по картинкам, я описал выше что меня смущает, может от этого и ошибки появляются
PM MAIL ICQ   Вверх
kelmiir
Дата 8.5.2013, 09:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



По первому я этот кусок со значениями сам не понимаю откуда они берутся.
По второму убирание ретурна после первого ифа на общее положение не влияет по прежнему не правильно работает.
PM MAIL   Вверх
Экскалупатор
Дата 8.5.2013, 21:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



Цитата(kelmiir @  8.5.2013,  08:28 Найти цитируемый пост)
По второму убирание ретурна после первого ифа на общее положение не влияет по прежнему не правильно работает. 

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

Это сообщение отредактировал(а) Экскалупатор - 8.5.2013, 21:13
PM MAIL ICQ   Вверх
kelmiir
Дата 9.5.2013, 11:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



В работе алгоритма ошибок не оказалось) Это была моя невнимательность и немного плохого плохо напечатаная и инструкция) в определение координат перепутал 1 с буковой i ) по этому и работал алгоритм не правильно) Но есть ещё одна сложность с которой я не знаю как справится. Заключается в том что когда сворачиваю игру то все клетки перестают отображаться и приходиться начинать игру заново. Без исправления этой ошибки отказываются принимать работу =(

PM MAIL   Вверх
Экскалупатор
Дата 9.5.2013, 13:02 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


Профиль
Группа: Завсегдатай
Сообщений: 1746
Регистрация: 1.4.2009
Где: г. Минск

Репутация: 11
Всего: 24



надо вызвать метод перерисовки формы(и всего содержимого в ней). обрабатывай события(shown, invalidate или тип того)
посмотри тут все они описаны Form
PM MAIL ICQ   Вверх
kelmiir
Дата 9.5.2013, 13:52 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 9
Регистрация: 3.5.2013

Репутация: нет
Всего: нет



Либо я не понимаю в целом метод либо совсем что то делаю не правильно. Попробовал разные методы но так ничего и не вышло. Куда его хотя бы примерно нужно вставить?
Попробовал и на саму прорисовку ставить , на форму и на загрузку формы. Ничего из этого не вышло
PM MAIL   Вверх
Machaon
Дата 15.5.2013, 23:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


КаРолЬ АсьКи МуАЛя
*


Профиль
Группа: Участник
Сообщений: 160
Регистрация: 12.8.2008
Где: М.о. Красногорск

Репутация: 3
Всего: 3



Делай так:

Код

private void Form1_Deactivate(object sender, EventArgs e)
        {
            if (this.WindowState == System.Windows.Forms.FormWindowState.Minimized)
            {
             // Записываешь состояние поля
            }
        }
 
        private void Form1_Activated(object sender, EventArgs e)
        {
         //  Восстанавливаешь состояние поля
        }

PM MAIL ICQ Skype   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
mr.DUDA
THandle

Используйте теги [code=csharp][/code] для подсветки кода. Используйтe чекбокс "транслит" если у Вас нет русских шрифтов.
Что делать если Вам помогли, но отблагодарить помощника плюсом в репутацию Вы не можете(не хватает сообщений)? Пишите сюда, или отправляйте репорт. Поставим :)
Так же не забывайте отмечать свой вопрос решенным, если он таковым является :)


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, mr.DUDA, THandle.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Общие вопросы по .NET и C# | Следующая тема »


 




[ Время генерации скрипта: 0.0753 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.