概要
DXライブラリを使用して何か動くものが作りたかったので、ライフゲームを作成してみました。
基本的にはwikipediaに書いてあるルールを参考にしています。
wikipedia ライフゲーム
プログラム初心者な為おかしい部分が多々あると思いますが、大目に見て頂ければと思います。
ソースコード
実際のソースコードは以下になります。
#include <DxLib.h>
#include "Cells.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
SetOutApplicationLogValidFlag(FALSE);//Log.txtを生成しないように設定
if (DxLib_Init() == 1) { return -1; }//初期化に失敗時にエラーを吐かせて終了
ChangeWindowMode(true);
Cells cells;
cells.Initialize();
while (ProcessMessage() == 0)
{
ClearDrawScreen();//裏画面消す
SetDrawScreen(DX_SCREEN_BACK);//描画先を裏画面に
cells.Update();
cells.Draw();
ScreenFlip();//裏画面を表画面にコピー
}
DxLib_End();
return 0;
}
#pragma once
#include <vector>
class Cells
{
private:
// セルの状態
enum State
{
Life, // 生存
Dead, // 死
Disable,
};
std::vector<std::vector<State>> m_cells;
std::vector<std::vector<State>> m_nextCells;
int m_frameCnt;
int m_updateInterval;
int m_nowGeneration;
public:
Cells();
void Initialize();
void Update();
void Draw();
private:
void UpdateGeneration();
int GetRinsetuCnt(int x, int y);
};
#include <DxLib.h>
#include <iterator>
#include <algorithm>
#include "Cells.h"
namespace
{
const int CellSize = 10; // セルの大きさ
const int CellDistance = 2; // セルの間隔
const int MaxCountX = 50; // 最大個数(X)
const int MaxCountY = 35; // 最大個数(Y)
const int InitUpdateInterval = 60; // 更新間隔
}
Cells::Cells() :
m_cells(MaxCountY, std::vector<State>(MaxCountX)),
m_nextCells(MaxCountY, std::vector<State>(MaxCountX))
{
m_frameCnt = 0;
m_updateInterval = InitUpdateInterval;
m_nowGeneration = 0;
}
// 初期状態設定
void Cells::Initialize()
{
for (int y = 0; y < m_cells.size(); y++)
{
for (int x = 0; x < m_cells[y].size(); x++)
{
// 端っこは全部壁にしとく
if ((y == 0) || (x == 0) || (y == MaxCountY-1) || (x == MaxCountX-1))
{
m_cells[y][x] = State::Disable;
}
else
{ // 生存・死のセルを半々にする
if (GetRand(1) == 0)
{
m_cells[y][x] = State::Life;
}
else
{
m_cells[y][x] = State::Dead;
}
}
}
}
}
// 更新
void Cells::Update()
{
m_frameCnt++;
// 速度早くする
if (CheckHitKey(KEY_INPUT_LEFT) != 0)
{
if (m_updateInterval > 1)
{
m_updateInterval--;
}
}
// 速度遅くする
if (CheckHitKey(KEY_INPUT_RIGHT) != 0)
{
m_updateInterval++;
}
// 世代更新
if (m_frameCnt % m_updateInterval == 0)
{
UpdateGeneration();
}
}
// 描画
void Cells::Draw()
{
int yPos = 0;
for (int y = 0; y < m_cells.size(); y++)
{
yPos += CellSize + CellDistance;
int xPos = 0;
for (int x = 0; x < m_cells[y].size(); x++)
{
xPos += CellSize + CellDistance;
if (m_cells[y][x] == State::Life)
{
DrawBox(
xPos,
yPos,
xPos + CellSize,
yPos + CellSize,
GetColor(255, 255, 255),
TRUE
);
}
}
}
char str[128];
sprintf_s(str, sizeof(str),"現在%d世代目 速度:%dフレーム毎に更新", m_nowGeneration, m_updateInterval);
DrawStringF(0, 0, str, GetColor(255, 255, 255));
}
// 次の世代の更新
void Cells::UpdateGeneration()
{
for(int y = 0; y < m_cells.size(); y++)
{
for(int x = 0; x < m_cells[y].size(); x++)
{
if (m_cells[y][x] == State::Disable)
{
m_nextCells[y][x] = State::Disable;
continue;
}
int rinsetu = GetRinsetuCnt(x, y);
// 現在死亡存状態
if (m_nextCells[y][x] == State::Dead)
{
// 誕生判定
if (rinsetu == 3)
{
m_nextCells[y][x] = State::Life;
}
}
// 現在生存状態
if (m_nextCells[y][x] == State::Life)
{
// 生存判定
if (rinsetu == 2 || rinsetu == 3)
{
m_nextCells[y][x] = State::Life;
}
// 過疎判定
if (rinsetu <= 1)
{
m_nextCells[y][x] = State::Dead;
}
// 密です判定
if (rinsetu >= 4)
{
m_nextCells[y][x] = State::Dead;
}
}
}
}
m_cells = m_nextCells;
m_nowGeneration++;
}
// 隣接するセルを取得
int Cells::GetRinsetuCnt(int x, int y)
{
int rinsetu = 0;
if(m_cells[y-1][x] == State::Life) rinsetu++;
if(m_cells[y-1][x+1] == State::Life) rinsetu++;
if(m_cells[y][x+1] == State::Life) rinsetu++;
if(m_cells[y+1][x+1] == State::Life) rinsetu++;
if(m_cells[y+1][x] == State::Life) rinsetu++;
if(m_cells[y+1][x-1] == State::Life) rinsetu++;
if(m_cells[y][x-1] == State::Life) rinsetu++;
if(m_cells[y-1][x-1] == State::Life) rinsetu++;
return rinsetu;
}
簡単な説明
セルの状態は二次元配列(コンテナ?)で持つようにしています。
Cells::UpdateGeneration()関数で、次の世代でセルが生きるか死ぬかを決めています。
最初の状態は良く分からなかったので、50%で生、50%で死の状態にしています。
また、for文の部分で警告が多々ありますが、まだ改善していません。
方向キーで、更新速度を変更できるようにしています(操作し辛いですが)
実行結果
ん~、画像だけでは分からないと思いますが、それっぽく動いている気はします…が、よく分からん…
固定物体の例や振動子の例などは一部見られますが、移動物体の例の宇宙船などは出来ていない気がする…
wikipediaのライフゲームのルールだけ見て作ったので、他に改善しないと行けない点があるかも知れない為、今後出来れば改善していきたいと思います。
以上になります。
こんな記事を見て頂き、ありがとうございました。