前提・実現したいこと
C++(ほぼC言語の書き方)でライフゲーム(wikipediaに載っている一般的なもの)を作っていたのですが、
挙動が明らかに違います(挙動に規則がみつからなく、また、wikipediaの例と違う挙動をします)。
なので、正しい挙動をするように、おかしいところを指摘してもらえないでしょうか。
発生している問題・エラーメッセージ
上の通り、明らかに違う挙動をします(エラーメッセージは出ていません)
該当のソースコード
C++
1#include <stdio.h> 2#include <conio.h> 3#include <stdlib.h> 4 5#define FIELD_WIDTH 50 6#define FIELD_HEIGHT 45 7 8enum alive { 9 CELL_DEAD = 0, 10 CELL_ALIVE = 1, 11 CELL_MAX 12}; 13 14// 8方向のベクトルの管理 15enum vector { 16 VECTOR_UP, 17 VECTOR_DOWN, 18 VECTOR_LEFT, 19 VECTOR_RIGHT, 20 VECTOR_UP_LEFT, 21 VECTOR_UP_RIGHT, 22 VECTOR_DOWN_LEFT, 23 VECTOR_DOWN_RIGHT, 24 VECTOR_MAX 25}; 26 27int vectors[][2] = { 28 {0, -1}, // VECTOR_UP 29 {0, 1}, // VECTOR_DOWN 30 {-1, 0}, // VECTOR_LEFT 31 {1, 0}, // VECTOR_RIGHT 32 {-1, -1}, // VECTOR_UP_LEFT 33 {1, -1}, // VECTOR_UP_RIGHT 34 {-1, 1}, // VECTOR_DOWN_LEFT 35 {1, 1} // VECTOR_DOWN_RIGHT 36}; 37 38// 一つ一つの細胞の定義 39int cells[FIELD_HEIGHT][FIELD_WIDTH]; 40 41// カーソルの定義 42int cursorX = 0, cursorY = 0; 43 44// 最初に盤面のセットアップ 45void setup(void) { 46 for (int y = 0; y < FIELD_HEIGHT; y++) 47 for (int x = 0; x < FIELD_WIDTH; x++) { 48 cells[y][x] = CELL_DEAD; 49 } 50} 51 52// 盤面の更新(firstはカーソルの表示非表示) 53void update(bool cursor) { 54 // 盤面のクリア 55 system("cls"); 56 57 for (int y = 0; y < FIELD_HEIGHT; y++) { 58 for (int x = 0; x < FIELD_WIDTH; x++) { 59 // カーソルの表示 60 if (cursor) { 61 if (x == cursorX && y == cursorY) { 62 printf("◆"); 63 } 64 65 else { 66 if (cells[y][x] == CELL_DEAD) { 67 printf("□"); 68 } 69 70 if (cells[y][x] == CELL_ALIVE) { 71 printf("●"); 72 } 73 } 74 } 75 76 // 死んでいると□, 生きていると● 77 else { 78 if (cells[y][x] == CELL_DEAD) { 79 printf("□"); 80 } 81 82 if (cells[y][x] == CELL_ALIVE) { 83 printf("●"); 84 } 85 } 86 } 87 88 // FIELD_WIDTHごとに改行 89 printf("\n"); 90 } 91} 92 93// 周りの生きているセルの数のカウント 94int livesAlong(int _x, int _y) { 95 // カウント 96 int count = 0; 97 98 for (int i = 0; i < VECTOR_MAX; i++) { 99 int x2 = _x, y2 = _y; 100 x2 += vectors[i][0]; 101 y2 += vectors[i][1]; 102 103 // はみ出さないように 104 if (x2 < 0 || x2 >= FIELD_WIDTH) { 105 continue; 106 } 107 108 if (y2 < 0 || y2 >= FIELD_HEIGHT) { 109 continue; 110 } 111 112 // カウントの追加 113 if (cells[y2][x2] == CELL_ALIVE) { 114 count += 1; 115 } 116 } 117 118 return count; 119} 120 121// 次に生きているか(_alivesは周りの生きているセルの数, _cellは今のセルが生きているか死んでいるか) 122bool nextAlive(int _alives, int _cell) { 123 if (_cell == CELL_ALIVE) { 124 switch (_alives) { 125 case 1: return false; break; 126 case 2: return true; break; 127 case 3: return true; break; 128 case 4: return false; break; 129 } 130 } 131 132 if (_cell == CELL_DEAD) { 133 if (_alives == 3) { 134 return true; 135 } 136 137 else { 138 return false; 139 } 140 } 141 142 return false; 143} 144 145int main(void) { 146 // 盤面のセットアップ 147 setup(); 148 149 // ループ管理 150 bool Set = true; 151 152 int alvalg = 0; 153 154 // 最初に命をセット 155 while (Set) { 156 update(true); 157 switch (_getch()) { 158 // 移動 159 case 'w': cursorY--; break; 160 case 's': cursorY++; break; 161 case 'a': cursorX--; break; 162 case 'd': cursorX++; break; 163 164 // 命を置く 165 case 'r': cells[cursorY][cursorX] = CELL_ALIVE; break; 166 167 // ライフゲームを始める 168 case 'e': Set = false; break; 169 }; 170 171 // カーソルがはみ出さないように 172 cursorX = (FIELD_WIDTH + cursorX) % FIELD_WIDTH; 173 cursorY = (FIELD_HEIGHT + cursorY) % FIELD_HEIGHT; 174 } 175 176 // ライフゲームのループ(rキー入力で次の世代, eで終わる) 177 bool _continue = true; 178 179 while (1) { 180 update(false); 181 switch (_getch()) { 182 183 // rを押すと次の生死を判断(次の世代へ) 184 case 'r': 185 for (int y = 0; y < FIELD_HEIGHT; y++) { 186 for (int x = 0; x < FIELD_WIDTH; x++) { 187 if (nextAlive(livesAlong(x, y), cells[y][x])) { 188 cells[y][x] = CELL_ALIVE; 189 } 190 191 else { 192 cells[y][x] = CELL_DEAD; 193 } 194 } 195 } 196 break; 197 198 // eでプログラムを終える 199 case 'e': _continue = false; break; 200 default: break; 201 } 202 } 203 return 0; 204}
試したこと
周りの生きているセルの数を確認する関数(livesAlong)の値は、数回試しましたが、おそらく正常です。
次の生死の判断(nextAlive)も、おそらく正常です。
補足情報(FW/ツールのバージョンなど)
visual studio 2019の「C++コンソールアプリ」で開発しております。
回答3件
あなたの回答
tips
プレビュー