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

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Игра "Жизнь", Реализация игры "Жизнь" на C# 
V
    Опции темы
SmirnovKemerovo
Дата 13.8.2009, 09:09 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте!
Пробую начать программировать на C#, придумал для себя несложную задачу - написать код известной игры "Жизнь".
Правила игры можно посмотреть здесь: "Жизнь" на Википедии
Как начинающий программист очень хотел бы выслушать замечания профессионалов относительно своего кода.
Игровое поле представлено массивом контролов Button, живая особь - кнопка белого цвета, мертвая - черного.
На форме так же присутствуют две кнопки, "GO" - запускает игру, "Clear" очищает игровое поле.
Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Life
{
    
    public partial class Form1 : Form
    {
        private bool stopflag = false; //переключатель конца игрового процесса
        private bool[,] mass = new bool[50, 50]; //массив значений мертвый-живой для ячеек игрового поля
        private bool[,] tempmass = new bool[50, 50]; // Массив временных значений
        private Button[,] massbut = new Button[50, 50]; // Массив кнопок-ячеек игрового поля
        private int generation = 0; //Счетчик поколений
        public Form1()
        {   
            InitializeComponent();
           //создаем игровое поле

            for (int i = 0; i < 50; i++)
            {
                for (int j = 0; j < 50; j++)
                {                  
                    massbut[i, j] = new Button();
                    massbut[i, j].Size = new Size(10, 10);
                    massbut[i, j].Location = new Point(i * 10 + i * 3 + 30, j * 10 + j * 3 + 30);
                    massbut[i, j].Click += new System.EventHandler(this.massbutClick);
                    massbut[i, j].Tag = new Coords(i, j); // .Tag для привязки кнопок-ячеек к массиву значений мертвый-живой  
                    massbut[i, j].FlatStyle = FlatStyle.Flat;
                    this.Controls.Add(massbut[i, j]);

                }
            }
            
            NewLife();
        }
       
        //Нажатием на кнопки-ячейки задаем первоначальное расположение особей
        private void massbutClick(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            Coords co=(Coords)btn.Tag ;
            btn.BackColor=Color.White;
            mass[co.i, co.j] = true;
        }
       
         //Нажатие кнопки GO запускаем игровой процесс в отдельном потоке
        private void butnGoClick(object sender, EventArgs e)
        {
            Thread LifeThread = new Thread(GoLife);
            LifeThread.Start();
        }
        //нажатием кнопки Clear устанавливаем переключатель конца игрового процесса
        private void butnClearClick(object sender, EventArgs e)
        {
            stopflag = true;
        }

        //Начало новой игры
        private void NewLife()
        {
            for (int i = 0; i < 50; i++)
            {
                for (int j = 0; j < 50; j++)
                {
                    mass[i, j] = false;
                    tempmass[i, j] = false;
                    massbut[i, j].BackColor = Color.Black;
                }
            }
            generation = 0;
            label1.Text = string.Empty;
            this.Refresh();
        }

        //метод выполняется в отдельном потоке, вызываем метод генерации нового поколения 
        //и проверяем состояние переключателя конца процесса
        private void GoLife()
        {
        for (int i = 0; i < 100; i++)
            {
                NextGeneration();
                generation++;
                label1.Text = generation.ToString();
                this.Refresh();
                if (stopflag) { i = 100; }
             }
        if (stopflag) { stopflag = false;  NewLife(); }
        }

        //Генерирует новое поколение
        public void NextGeneration()
        {
            this.SuspendLayout();
            
            for (int i = 0; i < 50; i++)
            {
                for (int j = 0; j < 50; j++)
                {
                    if ((sosediCount(i, j) == 3) && (!mass[i, j])) { tempmass[i, j] = true; }
                    if (((sosediCount(i, j) == 3) || (sosediCount(i, j) == 2)) && (mass[i, j])) { tempmass[i, j] = true; }
                    if ((sosediCount(i, j) < 2) && (mass[i, j])) { tempmass[i, j] = false ;  }
                    if ((sosediCount(i, j) > 3) && (mass[i, j])) { tempmass[i, j] = false; }
                }
            }
            for (int i = 0; i < 50; i++)
            {
                for (int j = 0; j < 50; j++)
                {
                    mass[i, j] = tempmass[i, j];
                    if (mass[i, j]) { massbut[i, j].BackColor = Color.White; } else {massbut[i, j].BackColor = Color.Black ; }
                }
            }
            this.ResumeLayout();
        
        }

        //функция расчета количества соседей у особи
        private int sosediCount(int a, int b)
        {
           int sosedi = 0;
            if (a > 0 && mass[a - 1, b]) {sosedi++;}
            if (a > 0 && b < 49 && mass[a - 1, b + 1]) { sosedi++; }
            if (b < 49 && mass[a, b + 1]) { sosedi++; };
            if (a < 49 && b < 49 && mass[a + 1, b + 1]) { sosedi++; }
            if (a < 49 && mass[a + 1, b]) { sosedi++; }
            if (a < 49 && b > 0 && mass[a + 1, b - 1]) { sosedi++; }
            if (b > 0 && mass[a, b - 1]) { sosedi++; }
            if (a > 0 && b > 0 && mass[a - 1, b - 1]) { sosedi++; }
            return sosedi;
        }
    }

    //класс объектов, хранящих индексы массива для Button.Tag
    public class Coords
    {
        private int _i;
        private int _j;
        public int i
        {
            get {return _i;}
            set { _i = i; }
        }
        public int j
        {
            get {return _j;}
            set { _j = j; }
        }
        public Coords(int a, int b)
        {
            _i = a; _j = b;
        }
 
    }

}


Жду комментариев.
PM MAIL   Вверх
ДобренькийПапаша
Дата 13.8.2009, 10:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Сразу навскидку можно сказать, что именование не очень удачное. Именование функций и переменных не везде идёт в соответствии со спецификацией языка. 
Правила именования

Добавлено через 3 минуты и 35 секунд
А, ну вот что ещё. У вас везде используются магические числа. Заменяйте их на переменные с нормальными именами, как то, если у вас размер массива не меняется. Объявите его границы как константную переменную. Ну и так далее. По поводу хорошего стиля можно почитать MacConell-"Code Complete" (в русском издании "Совершенный код").


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
SmirnovKemerovo
Дата 13.8.2009, 13:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



ОК, работа над ошибками

Код

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace Life
{
    
    public partial class Form1 : Form
    {
        private bool stopFlag = false; //переключатель конца игрового процесса
        private bool[,] massBool = new bool[50, 50]; //массив значений мертвый-живой для ячеек игрового поля
        private bool[,] massBoolTemp = new bool[50, 50]; // Массив временных значений
        private Button[,] massButton = new Button[50, 50]; // Массив кнопок-ячеек игрового поля
        private int generation = 0; //Счетчик поколений
        
        const int buttonLength = 10;
        Size buttonSize = new Size(buttonLength , buttonLength );
        const int margin = 30;
        const int maxValue = 50;
        const int breakPointGeneration = 100;

        public Form1()
        {   
            InitializeComponent();
           //создаем игровое поле

            for (int i = 0; i < maxValue ; i++)
            {
                for (int j = 0; j < maxValue ; j++)
                {                  
                    massButton[i, j] = new Button();
                    massButton[i, j].Size = buttonSize;
                    massButton[i, j].Location = new Point(i * buttonLength  + i * 2 + margin , j * buttonLength  + j * 2 + margin );
                    massButton[i, j].Click += new System.EventHandler(this.MassButtonClick);
                    massButton[i, j].Tag = new Coords(i, j); // .Tag для привязки кнопок-ячеек к массиву значений мертвый-живой  
                    massButton[i, j].FlatStyle = FlatStyle.Flat;
                    this.Controls.Add(massButton[i, j]);

                }
            }
            
            NewLife();
        }
       
        //Нажатием на кнопки-ячейки задаем первоначальное расположение особей
        private void MassButtonClick(object sender, EventArgs e)
        {
            Button btn = (Button)sender;
            Coords co=(Coords)btn.Tag ;
            btn.BackColor=Color.White;
            massBool[co.I, co.J] = true;
        }
       
         //Нажатие кнопки GO запускаем игровой процесс в отдельном потоке
        private void GoButtonClick(object sender, EventArgs e)
        {
            Thread LifeThread = new Thread(GoLife);
            LifeThread.Start();
        }
        //нажатием кнопки Clear устанавливаем переключатель конца игрового процесса
        private void ClearButtonClick(object sender, EventArgs e)
        {
            stopFlag = true;
        }

        //Начало новой игры
        private void NewLife()
        {
            for (int i = 0; i < maxValue ; i++)
            {
                for (int j = 0; j < maxValue; j++)
                {
                    massBool[i, j] = false;
                    massBoolTemp[i, j] = false;
                    massButton[i, j].BackColor = Color.Black;
                }
            }
            generation = 0;
            label1.Text = string.Empty;
            this.Refresh();
        }

        //метод выполняется в отдельном потоке, вызываем метод генерации нового поколения 
        //и проверяем состояние переключателя конца процесса
        private void GoLife()
        {
        for (int i = 0; i < breakPointGeneration ; i++)
            {
                NextGeneration();
                generation++;
                label1.Text = generation.ToString();
                this.Refresh();
                if (stopFlag) { break; }
             }
        if (stopFlag) { stopFlag = false;  NewLife(); }
        }

        //Генерирует новое поколение
        public void NextGeneration()
        {
            this.SuspendLayout();
            
            for (int i = 0; i < maxValue ; i++)
            {
                for (int j = 0; j < maxValue; j++)
                {
                    if ((SosediCount(i, j) == 3) && (!massBool[i, j])) { massBoolTemp[i, j] = true; }
                    if (((SosediCount(i, j) == 3) || (SosediCount(i, j) == 2)) && (massBool[i, j])) { massBoolTemp[i, j] = true; }
                    if ((SosediCount(i, j) < 2) && (massBool[i, j])) { massBoolTemp[i, j] = false ;  }
                    if ((SosediCount(i, j) > 3) && (massBool[i, j])) { massBoolTemp[i, j] = false; }
                }
            }
            for (int i = 0; i < maxValue ; i++)
            {
                for (int j = 0; j < maxValue; j++)
                {
                    massBool[i, j] = massBoolTemp[i, j];
                    if (massBool[i, j]) { massButton[i, j].BackColor = Color.White; } else {massButton[i, j].BackColor = Color.Black ; }
                }
            }
            this.ResumeLayout();
        
        }

        //функция расчета количества соседей у особи
        private int SosediCount(int a, int b)
        {
           int sosedi = 0;
           int limit = maxValue - 1;
 
            if (a > 0 && massBool[a - 1, b]) {sosedi++;}
            if (a > 0 && b < limit && massBool[a - 1, b + 1]) { sosedi++; }
            if (b < maxValue-1 && massBool[a, b + 1]) { sosedi++; };
            if (a < limit && b < limit && massBool[a + 1, b + 1]) { sosedi++; }
            if (a < limit && massBool[a + 1, b]) { sosedi++; }
            if (a < limit && b > 0 && massBool[a + 1, b - 1]) { sosedi++; }
            if (b > 0 && massBool[a, b - 1]) { sosedi++; }
            if (a > 0 && b > 0 && massBool[a - 1, b - 1]) { sosedi++; }
            return sosedi;
        }
    }

    //класс объектов, хранящих индексы массива для Button.Tag
    public class Coords
    {
        private int i;
        private int j;
        public int I
        {
            get {return i;}
            set { i = I; }
        }
        public int J
        {
            get {return j;}
            set { j = J; }
        }
        public Coords(int a, int b)
        {
            i = a; j = b;
        }
 
    }

}


Так лучше?


Это сообщение отредактировал(а) SmirnovKemerovo - 13.8.2009, 13:45
PM MAIL   Вверх
ДобренькийПапаша
Дата 13.8.2009, 14:29 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
***


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

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



Лучше, вы в самом начале задаёте три массива 50 на 50, объявите константу равную 50, и создавайте используя константу. А то вдруг спустя сто лет вы захотите сделать игровое поле больше, тогда вам придёца править возможно в большом количестве мест одно и тоже...
(Я правда в логику приложения не вдавался)

Вобщем в любом случае, вышеуказанную книгу почитайте...


--------------------
Меня зовут Себастьян Парейра, торговец чёрным деревом.
PM MAIL   Вверх
ZmeyNet
Дата 14.8.2009, 13:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 28
Регистрация: 25.1.2008
Где: Belarus, Minsk

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



SmirnovKemerovo,

FAQ по документирующим комментариям в C#

Комментарии в формате XML позволяют создавать документацию непосредственно из исходных файлов Visual Studio .NET  C# позволяет разработчикам встраивать в свои исходные файлы комментарии в формате XML — удобное средство, особенно в тех случаях, когда над одним и тем же кодом работают несколько программистов.
Анализатор C# раскрывает эти теги XML для предоставления дополнительной информации и экспортирует их во внешний документ для последующей обработки. В данной статье показаны методы использования комментариев XML проводится обсуждение необходимых тегов. Автор демонстрирует метод настройки проекта для экспорта комментариев XML в подходящую документацию для их использования другими разработчиками. Он также объясняет, как использовать комментарии для генерации файлов справки.

PM MAIL ICQ Skype   Вверх
dance
Дата 26.5.2010, 16:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



В якому компіляторі Ви її компілювали??? Як переробити на с++???

Это сообщение отредактировал(а) dance - 26.5.2010, 17:02
PM MAIL   Вверх
jonie
Дата 27.5.2010, 21:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 5613
Регистрация: 21.8.2005
Где: Владимир

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



dance, это язык C#, не С++. Тут есть на С++ http://panda.nowere.net/?page_id=75


--------------------
Что-то не поняли? -> Напейтесь до зеленых человечков... эта сверхцивилизация Вам поможет...
PM MAIL Jabber   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Прежде чем создать тему, посмотрите сюда:
Partizan
PashaPash

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


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

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


 




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


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

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