先日qiitaを散歩していると、短い行数で且つそれなりの可読性があるライフゲームを作るという記事を見かけたました。ちょっと古い記事ですが。
![](https://qiita-user-contents.imgix.net/https%3A%2F%2Fqiita-user-contents.imgix.net%2Fhttps%253A%252F%252Fcdn.qiita.com%252Fassets%252Fpublic%252Fadvent-calendar-ogp-background-7940cd1c8db80a7ec40711d90f43539e.jpg%3Fixlib%3Drb-4.0.0%26w%3D1200%26blend64%3DaHR0cHM6Ly9xaWl0YS11c2VyLXByb2ZpbGUtaW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnFpaXRhLWltYWdlLXN0b3JlLnMzLmFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkYwJTJGMTEzNTk1JTJGcHJvZmlsZS1pbWFnZXMlMkYxNTk0NzMyODg5P2l4bGliPXJiLTQuMC4wJmFyPTElM0ExJmZpdD1jcm9wJm1hc2s9ZWxsaXBzZSZmbT1wbmczMiZzPWU0NDhjZjRhYTEzYmRhN2VjOTM0MDRjNWQxZjRmZmM0%26blend-x%3D120%26blend-y%3D462%26blend-w%3D90%26blend-h%3D90%26blend-mode%3Dnormal%26mark64%3DaHR0cHM6Ly9xaWl0YS1vcmdhbml6YXRpb24taW1hZ2VzLmltZ2l4Lm5ldC9odHRwcyUzQSUyRiUyRnMzLWFwLW5vcnRoZWFzdC0xLmFtYXpvbmF3cy5jb20lMkZxaWl0YS1vcmdhbml6YXRpb24taW1hZ2UlMkZmN2ViOTkzNzY1ZGRjZGIyYzVlNjg5MDU1NmM0M2VhM2RlOGZiZmI3JTJGb3JpZ2luYWwuanBnJTNGMTU3MDIxNTY5MD9peGxpYj1yYi00LjAuMCZ3PTQ0Jmg9NDQmZml0PWNyb3AmbWFzaz1jb3JuZXJzJmNvcm5lci1yYWRpdXM9OCZib3JkZXI9MiUyQ0ZGRkZGRiZmbT1wbmczMiZzPWQ4ZGRjMGE4ZGU3Y2IyNGQwNmQyYzFhY2I4Nzg2NTZj%26mark-x%3D186%26mark-y%3D515%26mark-w%3D40%26mark-h%3D40%26s%3D97ea65d65534e19eea2bc7e1b1d1cf6e?ixlib=rb-4.0.0&w=1200&fm=jpg&mark64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTk2MCZoPTMyNCZ0eHQ9JUUzJTgwJTkwQyUyMyVFMyU4MCU5MTI2JUU4JUExJThDJUUzJTgxJUE3JUUzJTgzJUE5JUUzJTgyJUE0JUUzJTgzJTk1JUUzJTgyJUIyJUUzJTgzJUJDJUUzJTgzJUEwJUUzJTgyJTkyJUU2JTlCJUI4JUUzJTgxJTg0JUUzJTgxJUE2JUUzJTgxJUJGJUUzJTgyJThCJUVGJUJDJTg4JUUzJTgyJUIzJUUzJTgzJUIzJUUzJTgyJUJEJUUzJTgzJUJDJUUzJTgzJUFCJUU4JUExJUE4JUU3JUE0JUJBJUU1JThGJUFGJUU4JTgzJUJEJUVGJUJDJTg5JnR4dC1hbGlnbj1sZWZ0JTJDdG9wJnR4dC1jb2xvcj0lMjMzQTNDM0MmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9NTYmdHh0LXBhZD0wJnM9MTYzNWZhYTQ3MzZhN2Q0OTUxNTdmOWUxNTA0NmNiMWU&mark-x=120&mark-y=112&blend64=aHR0cHM6Ly9xaWl0YS11c2VyLWNvbnRlbnRzLmltZ2l4Lm5ldC9-dGV4dD9peGxpYj1yYi00LjAuMCZ3PTgzOCZoPTU4JnR4dD0lNDB5b3NoaXAxNjM5JnR4dC1jb2xvcj0lMjMzQTNDM0MmdHh0LWZvbnQ9SGlyYWdpbm8lMjBTYW5zJTIwVzYmdHh0LXNpemU9MzYmdHh0LXBhZD0wJnM9NGIwZGQ1Y2NmNjk4OGYxNDgzZDk1MzRjYzlhOTBjMTM&blend-x=242&blend-y=454&blend-w=838&blend-h=46&blend-fit=crop&blend-crop=left%2Cbottom&blend-mode=normal&txt64=VW5pdHnjgrLjg7zjg6DplovnmbrogIXjgq7jg6vjg4k&txt-x=242&txt-y=539&txt-width=838&txt-clip=end%2Cellipsis&txt-color=%233A3C3C&txt-font=Hiragino%20Sans%20W6&txt-size=28&s=e7a3b4602cd1de047dcc07e779efbc21)
【C#】26行でライフゲームを書いてみる(コンソール表示可能) - Qiita
本記事は C# その2 Advent Calender2018 17日目の記事です。はじめにこんにちは@yoship1639です。普段は個人ゲーム開発を行っています。本記事は内容は技術的です…
これ、LINQ使ったらもうちょっといけるんじゃね?ということでやってみました。
れぎゅれーしょん
- ライフゲーム
- C#
- それなりの可読性
- 縦横ともに一画面になんとなく収まるぐらい
- エラーハンドリングは考えない
ソース
class Program { const int kWidth = 10; const int kHeight = 10; public static void Main(string[] args) { var cells = (new bool[kHeight + 2]).Select(_ => (new bool[kWidth + 2]).ToList()).ToList(); var accessor = new []{(-1, -1), (-1, 0), (-1, 1), (0, -1), (0, 1), (1, -1), (1, 0), (1, 1)}; int CountOf(int x, int y) => accessor.Aggregate(0, (l, set) => l + (cells[set.Item1 + y][set.Item2 + x] ? 1 : 0)); bool IsAlive(bool alive, int count) => (!alive && count == 3) || (alive && (count == 2 || count == 3)); string[] sc = null; while ((sc = System.Console.ReadLine().Split(' '))[0] != "q") { if (sc.Length == 2) { cells[int.Parse(sc[1]) + 1][int.Parse(sc[0]) + 1] = true; } else { cells = cells.Select((line, y) > y == 0 || y == kHeight + 1 ? line : line.Select((alive, x) > x == 0 || x == kWidth + 1 ? false : IsAlive(alive, CountOf(x, y))).ToList()).ToList(); System.Console.WriteLine(string.Join('\n', cells.Skip(1).Take(kHeight).Select(y => string.Join("", y.Skip(1).Take(kWidth).Select(x => x ? '■' : '□'))))); } } } }
概要
標準入力からとってくるところは元記事をそのまま使っています。エラーハンドリング、異常値チェックなども無しで踏襲しています。
とりあえず二次元配列には消えてもらう
二次元配列はLINQが微妙なので、ListのListにしています。
とりあえず番兵
まあ、あった方がいいよね。
周囲を数えるのはインデックスを用意
Aggregateで畳込めるしインデックスの配列を用意しています。Enumerable.Rangeで3×3のEnumerableを用意してもよかったかもしれません。
入力周りは元のまま
元のまま使わせてもらっています。
次世代へはLINQで1式で
番兵以外は周囲の生存数を数えて、生き死に判定して新しいリストを再代入しています。
SelectではなくForEachにして、直接Listの中を書き換えると番兵外しの三項条件演算子がSkip().Take()に変えられると思います。そっちの方がわかりやすかったかも。
まとめ
もっと詰め込みに詰め込めばまだまだ減らせそうですが、人間にはちょっと前衛的すぎることになりそうですので、個人的にはこの辺がギリギリラインではと勝手に思っています。