1 module wireworld; 2 3 private 4 { 5 import qte5; 6 } 7 8 // элементы мира WireWorld 9 final enum Element : byte 10 { 11 Empty, // пустое поле 12 Head, // голова электрона 13 Tail, // хвост электрона 14 Conductor // проводник 15 } 16 17 // мир WireWorld 18 class WireWorld(size_t WORLD_WIDTH, size_t WORLD_HEIGHT) 19 { 20 private 21 { 22 // мир 23 byte[WORLD_HEIGHT][WORLD_WIDTH] world; 24 // копия мира 25 byte[WORLD_HEIGHT][WORLD_WIDTH] reserved; 26 27 // резервное копирование мира 28 void backupWorld() 29 { 30 for (int i = 0; i < WORLD_WIDTH; i++) 31 { 32 for (int j = 0; j < WORLD_HEIGHT; j++) 33 { 34 reserved[i][j] = world[i][j]; 35 } 36 } 37 } 38 } 39 40 this() 41 { 42 43 } 44 45 // извлечение элемента 46 auto opIndex(size_t i, size_t j) 47 { 48 return world[i][j]; 49 } 50 51 // присвоение элемента 52 void opIndexAssign(Element element, size_t i, size_t j) 53 { 54 world[i][j] = element; 55 } 56 57 // одно поколение клеточного автомата 58 auto execute() 59 { 60 // скопировать мир 61 backupWorld; 62 63 // трансформация ячейки с проводником 64 void transformConductorCell(int i, int j) 65 { 66 auto up = ((j + 1) >= WORLD_HEIGHT) ? WORLD_HEIGHT - 1 : j + 1; 67 auto down = ((j - 1) < 0) ? 0 : j - 1; 68 auto right = ((i + 1) >= WORLD_WIDTH) ? WORLD_WIDTH - 1 : i + 1; 69 auto left = ((i - 1) < 0) ? 0 : i - 1; 70 71 auto counter = 0; 72 73 if (reserved[i][up] == Element.Head) 74 { 75 counter++; 76 } 77 78 if (reserved[i][down] == Element.Head) 79 { 80 counter++; 81 } 82 83 if (reserved[left][j] == Element.Head) 84 { 85 counter++; 86 } 87 88 if (reserved[right][j] == Element.Head) 89 { 90 counter++; 91 } 92 93 if (reserved[left][up] == Element.Head) 94 { 95 counter++; 96 } 97 98 if (reserved[left][down] == Element.Head) 99 { 100 counter++; 101 } 102 103 if (reserved[right][up] == Element.Head) 104 { 105 counter++; 106 } 107 108 if (reserved[right][down] == Element.Head) 109 { 110 counter++; 111 } 112 113 if ((counter == 1) || (counter == 2)) 114 { 115 world[i][j] = Element.Head; 116 } 117 else 118 { 119 world[i][j] = Element.Conductor; 120 } 121 } 122 123 for (int i = 0; i < WORLD_WIDTH; i++) 124 { 125 for (int j = 0; j < WORLD_HEIGHT; j++) 126 { 127 auto currentCell = reserved[i][j]; 128 129 final switch (currentCell) with (Element) 130 { 131 case Empty: 132 world[i][j] = Empty; 133 break; 134 case Head: 135 world[i][j] = Tail; 136 break; 137 case Tail: 138 world[i][j] = Conductor; 139 break; 140 case Conductor: 141 transformConductorCell(i, j); 142 break; 143 } 144 } 145 } 146 } 147 148 // очистка всего мира 149 void clearWorld() 150 { 151 world = typeof(world).init; 152 } 153 154 // нарисовать мир с помощью QtE5 155 void drawWorld(QPainter painter, int cellWidth, int cellHeight) 156 { 157 158 QColor BLACK = new QColor(null); 159 QColor BLUE = new QColor(null); 160 QColor RED = new QColor(null); 161 QColor YELLOW = new QColor(null); 162 QColor GRAY = new QColor(null); 163 164 BLACK.setRgb(0, 0, 0, 230); 165 BLUE.setRgb(0, 0, 255, 230); 166 RED.setRgb(255, 0, 0, 230); 167 YELLOW.setRgb(255, 255, 0, 230); 168 GRAY.setRgb(133, 133, 133, 230); 169 170 QPen pen = new QPen; 171 pen.setColor(GRAY); 172 173 for (int i = 0; i < WORLD_WIDTH; i++) 174 { 175 for (int j = 0; j < WORLD_HEIGHT; j++) 176 { 177 auto currentCell = world[i][j]; 178 179 // рисование прямоугольника 180 QRect rect = new QRect; 181 rect.setRect(i * cellWidth, j * cellHeight, cellWidth, cellHeight); 182 183 final switch (currentCell) with (Element) 184 { 185 case Empty: 186 painter.fillRect(rect, BLACK); 187 break; 188 case Head: 189 painter.fillRect(rect, BLUE); 190 break; 191 case Tail: 192 painter.fillRect(rect, RED); 193 break; 194 case Conductor: 195 painter.fillRect(rect, YELLOW); 196 break; 197 } 198 199 painter.setPen(pen); 200 painter.drawRect(i * cellWidth, j * cellHeight, cellWidth, cellHeight); 201 } 202 } 203 } 204 }