С Новым годом! Форум программистов, компьютерный форум, киберфорум
Java: GUI, графика
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.52/25: Рейтинг темы: голосов - 25, средняя оценка - 4.52
3 / 3 / 2
Регистрация: 04.01.2013
Сообщений: 73

Игра "Жизнь" с использованием MVC

06.05.2013, 04:53. Показов 4976. Ответов 2
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Всем привет. Задача в заголовке темы. С MVC знаком пару дней (с Java - второй семестр), не уверен, что понимаю его суть, но программу надо сдать до четверга. Три дня просидел над тем, что есть. Сегодня не продвинулся ни на шаг.
Пытался сделать так, чтобы можно было менять размеры окна. Если в случае с изменением цветов "налету" достаточно было изменить View, когда меняется Model, то с окном нужен, видимо, другой подход. Кроме того нужно ещё реализовать возможность смены ориентации поля (на 90, 180 , 270). Противоположные стороны поля должны быть замкнуты. Так же не пойму как реализовать автоматическую смену поколений и её скорость, т.е. подойдёт ли для этого Timer например. Но у меня почему-то даже единоразовая смена поколений не работает. Программа должна уметь порождать свои независимые друг от друга копии. Возможно ли это сделать без применения потоков?
Кто что может сказать о коде? Что в нём нормально, а что плохо? Верно ли я реализую MVC?
Буду благодарен за любую помощь, объяснение.

Java
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
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
import java.awt.*;
import java.awt.event.*;
import java.util.Observable;
import java.util.Observer;
import java.util.Timer;
import java.util.TimerTask;
import javax.swing.JPanel;
 
public class View_of_Life extends JPanel implements Observer{
    
    Color lebendig, tot;             // цвета "lebendig" мертвых и "tot" живых клеток       
    static final int tt = 0, ll = 1; // состояния клеток "0" мертвый, "1" живой
    JPanel [][] zellen;              //сами клетки
    int grid_w;                      //ширина поля
    int grid_h;                      //высота поля
    
    Timer timer = new Timer();
    //TimerTask lifetime;
    
    Model_of_Life myModel;          //модель MVC
    
    public View_of_Life(Model_of_Life M){
        
        myModel = M;        
        grid_w  = myModel.getWidth();
        grid_h  = myModel.getHeight();
        
        makegrid(grid_w,grid_h);  //создать поле
        
    }// end Konstruktor View_of_Life
    
    void makegrid(int W, int H){
                        
        setLayout (new GridLayout(H, W));
        
        zellen = new JPanel[H][W];
        
        for (int i = 0; i < H; i++){
            for (int j = 0; j < W; j++){
                zellen[i][j] = new Zellen();
                add (zellen[i][j]);
            }
        }
    }
 
    class Zellen extends JPanel {
        
        int state;  //состояние клетки
 
        public Zellen() {                               
            addMouseListener (new ML());
            setBackground(tot);
            state = tt; //состояние = мертвый
        }// end Konstruktor Zellen
        
        public void paintComponent (Graphics g){
            super.paintComponent (g);
                                    
            int x1 = 0;                                             
            int y1 = 0;                                         
            int x2 = getSize().width - 1;                   
            int y2 = getSize().height - 1;                  
            g.drawRect (x1, y1, x2, y2);                //рисуем границы самих клеток
            
            if (state == tt){ setBackground(tot); }     //и делаем их мертвыми
            else              setBackground(lebendig);
        }
        
        class ML extends MouseAdapter {                         
 
            public void mousePressed (MouseEvent e) {           
                
                if (e.getButton() == MouseEvent.BUTTON3) {  //по нажатию правой кнопки мыши            
                    state = (state == tt ? ll : tt);        //если мертвая, то сделать живой и наоборот
                    repaint();                              
                }
            }
        } // end ML
    }// end Zellen
    
    public void update(Observable obs, Object obj) {
        if (obs==myModel) {
            repaint ();     
        }
    }
    
    public void paintComponent (Graphics g) {   
                
        super.paintComponent (g);                           
        
        changecolorspalette(); //смена цвета живых и мертвых клеток "налету"
        
        if( myModel.getSimulate() ) { simulatelife(); } //попытка начать симуляцию смены поколений
                    
    }
    
    void simulatelife(){
                            
        int sum[][];
        sum = new int[zellen.length][zellen.length];
        for (int i=1; i<zellen.length-1; i++){
            for (int j=1; j<zellen[i].length-1; j++){
                if (zellen[i-1][j-1].getBackground() == (lebendig)) {sum[i][j]++;}
                if (zellen[i-1][j].getBackground()   == (lebendig)) {sum[i][j]++;}
                if (zellen[i-1][j+1].getBackground() == (lebendig)) {sum[i][j]++;}
                if (zellen[i][j-1].getBackground()   == (lebendig)) {sum[i][j]++;}
                if (zellen[i][j+1].getBackground()   == (lebendig)) {sum[i][j]++;}
                if (zellen[i+1][j-1].getBackground() == (lebendig)) {sum[i][j]++;}
                if (zellen[i+1][j].getBackground()   == (lebendig)) {sum[i][j]++;}
                if (zellen[i+1][j+1].getBackground() == (lebendig)) {sum[i][j]++;}
            }
        }
        for (int i=0; i<zellen.length; i++){
            for (int j=0; j<zellen[i].length; j++){
                if      (sum[i][j]<2  ) {zellen[i][j].setBackground(tot);}
                else if (sum[i][j]>3  ) {zellen[i][j].setBackground(tot);}
                else if (sum[i][j]==3 ) {zellen[i][j].setBackground(lebendig);}
            sum[i][j]=0;
            }
        }
    }
 
    void changecolorspalette(){
        
        lebendig = myModel.getColorOfLife();
        tot      = myModel.getColorOfDeath();
        
        for (int i = 0; i < zellen.length; i++ ){   
            for (int j = 0; j < zellen[i].length; j++ ){
            
                if (((Zellen) zellen[i][j]).state == tt)
                        ((Zellen) zellen[i][j]).setBackground(tot);
                else    ((Zellen) zellen[i][j]).setBackground(lebendig);
            }
        }       
    }
 
}//View_of_Life END
Java
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
import javax.swing.*;
import javax.swing.event.* ;
import java.awt.*;
import java.awt.event.*;
import java.util.*; 
 
public class Model_of_Life extends Observable{
    
    private int     mod_width, mod_height;
    private Color   mod_CofL , mod_CofD;
    private boolean simulate = false;
    
    public Model_of_Life (int w, int h, Color L, Color D){
        
        mod_width   = w;
        mod_height  = h;
        mod_CofL    = L;
        mod_CofD    = D;
    } // end Konstuktor
    
    public boolean getSimulate(){
        return simulate;
    }
    
    public void setSimulate (boolean yes){      
        simulate = yes;
        setChanged();
        notifyObservers();
    }
    
    public int getWidth () {        
        return mod_width;
    }
    
    public int getHeight () {       
        return mod_height;
    }
    
    public Color getColorOfLife () {        
        return mod_CofL;
    }
 
    public Color getColorOfDeath() {        
        return mod_CofD;
    }
    
    public void setWidth (int w_IN){        
        mod_width = w_IN;
        setChanged();
        notifyObservers();
    }
    
    public void setHeight (int h_IN){       
        mod_height = h_IN;
        setChanged();
        notifyObservers();      
    }
    
    public void setColorOfLife (Color CoL_IN){      
        mod_CofL = CoL_IN;
        setChanged();
        notifyObservers();
    }
 
    public void setColorOfDeath (Color CoD_IN){     
        mod_CofD = CoD_IN;
        setChanged();
        notifyObservers();
    }
}
Java
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
101
102
103
104
105
106
107
import java.awt.*;
import java.awt.event.*;
 
import javax.swing.*;
 
import Basis.MVCexample;
 
import java.util.*;
 
public class Controller_of_Life extends JFrame{
    
    static int wndw_width = 768, wndw_height = 768; //размер окна
    int zellegrs = 16;//размер клетки в пикселях
    int grid_width = wndw_width/zellegrs, grid_height = wndw_height/zellegrs; //размерность игрового поля
    
    static Color ColorOfLife = Color.GREEN, ColorOfDeath = Color.RED;
    
    //////////МЕНЮ////////////////////////////////////////////////////////////
    JMenu[] menus = {
            
        new JMenu("Modus"), // Array mit 5 Menues
        new JMenu("Geschwindigkeit"),
        new JMenu("Farbe"),
        new JMenu("Fenstergroesse"),
        new JMenu("Orientierung"),
        new JMenu("Figuren")
    };
 
    JMenuItem[] items = { // Array mit Menue-Eintraegen
 
        new JMenuItem("Laufen"), new JMenuItem("Modus2"),
        new JMenuItem("Modus3"), new JMenuItem("Modus4"),
        // ...
        new JMenuItem("Fastest"), new JMenuItem("Fast"), new JMenuItem("Medium"),
        new JMenuItem("Slow"), new JMenuItem("Slowest"),
        // ...
        new JMenuItem("Rot-Gruen"), new JMenuItem("Gruen-Rot"),
        new JMenuItem("Blau-Grau"), new JMenuItem("Grau-Blau"),
        // ...
        new JMenuItem("1366x768"), new JMenuItem("1024x768"),
        new JMenuItem("768x512"),  new JMenuItem("512x256"), 
        // ...
        new JMenuItem("North"), new JMenuItem("South"),
        new JMenuItem("West"),  new JMenuItem("East"),
        // ...
        new JMenuItem("Figur1"), new JMenuItem("Figur2"),
        new JMenuItem("Figur3"), new JMenuItem("Figur4")
    };
    
//////////МЕНЮ////////////////////////////////////////////////////////////
    
    Controller_of_Life(){//конструктор
        
        final Model_of_Life M = new Model_of_Life (grid_width,grid_height,ColorOfLife,ColorOfDeath);//модели передаем размеры игрового поля и цвета жизни и смерти
        
        Container cp = getContentPane(); 
        
        ActionListener menu_al = new ActionListener() {//слушатель событий для меню
 
        public void actionPerformed(ActionEvent e){ 
 
            String cmd = ((JMenuItem)e.getSource()).getText();
            System.out.println("cmd "+cmd);
            if (cmd == "Rot-Gruen" ) {M.setColorOfLife(Color.RED   ); M.setColorOfDeath(Color.GREEN);}
            if (cmd == "Gruen-Rot" ) {M.setColorOfLife(Color.GREEN ); M.setColorOfDeath(Color.RED  );}
            if (cmd == "Blau-Grau" ) {M.setColorOfLife(Color.BLUE  ); M.setColorOfDeath(Color.GRAY );}
            if (cmd == "Grau-Blau" ) {M.setColorOfLife(Color.GRAY  ); M.setColorOfDeath(Color.BLUE );}
            
            if (cmd == "1366x768"  ) {M.setWidth(1366); M.setHeight(768);}
            if (cmd == "1024x768"  ) {M.setWidth(1024); M.setHeight(768);}
            if (cmd == "768x512"   ) {M.setWidth(768);  M.setHeight(512);}
            if (cmd == "512x256"   ) {M.setWidth(512);  M.setHeight(256);}
            
            if (cmd == "Laufen"    ) {M.setSimulate(true);}
            
        }
        };
        for (int i = 0; i < items.length; i++) {//заполняем меню
 
            items[i].addActionListener(menu_al);
            menus[(i<4)?0:(i<9)?1:(i<13)?2:(i<17)?3:(i<21)?4:5].add(items[i]); // add Items in Menue 0|1|2|3|4|5
        }
 
        JMenuBar mb = new JMenuBar();//в менюбар вставляем меню с подменю
 
        for (int i = 0; i < menus.length; i++){//в менюбар вставляем меню с подменю
 
            mb.add (menus[i]); 
            setJMenuBar (mb); 
        }
    
        View_of_Life view1 = new View_of_Life(M);//создаем Вид(View MVC) и передаем ему Модель(Model MVC) в качестве аргумента
        M.addObserver(view1);                    //у модели регистрируем вид
    
        cp.setLayout(new BoxLayout(cp,BoxLayout.Y_AXIS));
        cp.add (view1);
        
 
    }//END_Konstruktor_Controller_of_Life
    
      public static void main(String[] args) {
          Controller_of_Life Ctrl_L = new Controller_of_Life();
          Ctrl_L.setSize(wndw_width,wndw_height);
          Ctrl_L.setVisible(true);
          Ctrl_L.setResizable(false);
      }
}
0
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
06.05.2013, 04:53
Ответы с готовыми решениями:

Игра жизнь
Помогите пожалуйста с решением. Код нужен на С++ «Жизнь» – компьютерная игра, придуманная английским математиком Джоном Конвеем (John...

Игра Жизнь
Ну, правила игры таковы: - если клетка пустая но имеет ровно 3 соседа (вообще их 8), там появляется жизнь. - если клетка полная, но там...

Игра Жизнь
Написал вот такую реализацию: #include &quot;stdafx.h&quot; #include &quot;iostream&quot; #include &quot;clocale&quot; using namespace std; int...

2
3 / 3 / 2
Регистрация: 04.01.2013
Сообщений: 73
16.05.2013, 01:11  [ТС]
Сдал вовремя, но не успел реализовать смену ориентации игрового поля. Могу выгрузить код, если кому надо. Вот это сообщение mutagen-а помогло. Хотел вообще взять это решение за основу, но так и не разобрался в прорисовке самих клеток поля и в принципе двойной буферизации. mutagen обрадовал бы меня, если бы пролил свет на это дело) И главный вопрос тоже по-прежнему в силе: Верно ли я реализовал принцип MVC в коде?
0
 Аватар для Skipy
2000 / 1427 / 92
Регистрация: 25.11.2010
Сообщений: 3,611
16.05.2013, 11:53
Цитата Сообщение от St@nton Посмотреть сообщение
так и не разобрался в прорисовке самих клеток поля и в принципе двойной буферизации. mutagen обрадовал бы меня, если бы пролил свет на это дело
Я попробую:
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
16.05.2013, 11:53
Помогаю со студенческими работами здесь

Игра 'Жизнь'
Доброго времени суток. Нужно создать программу на основе игры 'Жизнь', что именно нужно: Колония клеток пусть задана множеством (set)...

Игра жизнь
Помогите пожалуйста с решением. Код нужен на С++ «Жизнь» – компьютерная игра, придуманная английским математиком Джоном Конвеем (John...

Игра жизнь
Нужно написать игру &quot;Жизнь&quot; простым кодом. Только начал изучать c++

Игра «Жизнь»
Написать программу, демонстрирующую работу с объектами двух типов: O1 – игрок, O2 – автоматический игрок, О3 – рейтинговая таблица...

Игра «Жизнь»
Легенда задачи: Место действия этой игры – «вселенная» – это размеченная на клетки поверхность. Каждая клетка на этой поверхности может...


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

Или воспользуйтесь поиском по форуму:
3
Ответ Создать тему
Новые блоги и статьи
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути
Programma_Boinc 01.01.2026
Учёным и волонтёрам проекта «Einstein@home» удалось обнаружить четыре гамма-лучевых пульсара в джете Млечного Пути Сочетание глобально распределённой вычислительной мощности и инновационных. . .
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост.
Programma_Boinc 28.12.2025
Советы по крайней бережливости. Внимание, это ОЧЕНЬ длинный пост. Налог на собак: https:/ / **********/ gallery/ V06K53e Финансовый отчет в Excel: https:/ / **********/ gallery/ bKBkQFf Пост отсюда. . .
Кто-нибудь знает, где можно бесплатно получить настольный компьютер или ноутбук? США.
Programma_Boinc 26.12.2025
Нашел на реддите интересную статью под названием Anyone know where to get a free Desktop or Laptop? Ниже её машинный перевод. После долгих разбирательств я наконец-то вернула себе. . .
Thinkpad X220 Tablet — это лучший бюджетный ноутбук для учёбы, точка.
Programma_Boinc 23.12.2025
Рецензия / Мнение/ Перевод Нашел на реддите интересную статью под названием The Thinkpad X220 Tablet is the best budget school laptop period . Ниже её машинный перевод. Thinkpad X220 Tablet —. . .
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Как объединить две одинаковые БД Access с разными данными
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru