7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

V言語でライフゲームしてみた

Posted at

はじめに

構文の確認程度に書いてみた。
元はNimで書いたライフゲーム用の簡易モジュールをV言語で書き直しただけ。
https://github.com/jiro4989/gameoflife

開発環境

  • V 0.1.11
  • Linux Mint 19.1

コード

import time

const (
	dead = 0
	live = 1
)

fn get_neighbour_cells(board [][]int, x, y int) []int {
	mut result := []int
	for y2 := y-1; y2 <= y+1; y2++ {
		if y2 < 0 || board.len <= y2 {
			continue
		}
		for x2 := x-1; x2 <= x+1; x2++ {
			if x2 < 0 || board[y2].len <= x2 {
				continue
			}
			if x == x2 && y == y2 {
				continue
			}
			result << board[y2][x2]
		}
	}
	return result
}

fn is_reproduction(self, living_cell_count int) bool {
	if self != dead {
		return false
	}
	return living_cell_count == 3
}

fn is_generation(self, living_cell_count int) bool {
	if self != live {
		return false
	}
	return living_cell_count == 2 || living_cell_count == 3
}

fn is_underpopulation(self, living_cell_count int) bool {
	if self != live {
		return false
	}
	return living_cell_count <= 1
}

fn is_overpopulation(self, living_cell_count int) bool {
	if self != live {
		return false
	}
	return 4 <= living_cell_count
}

fn next_step(board [][]int) [][]int {
	// v0.1.11
	// この構文はまだ使えないみたい
	// mut new_board := [][]int

	// 今は多次元配列をこう定義する
	mut new_board := []array_int
	for y := 0; y < board.len; y++ {
		row := board[y]
		mut new_row := []int

		for x := 0; x < row.len; x++ {
			cell := row[x]
			nc := get_neighbour_cells(board, x, y)
			mut living_cell_count := 0
			for c in nc {
				if c == live {
					living_cell_count++
				}
			}

			if cell == dead {
				if is_reproduction(cell, living_cell_count) {
					new_row << live
				} else {
					new_row << dead
				}
				continue
			}

			if is_generation(cell, living_cell_count) {
				new_row << live
			} else if is_underpopulation(cell, living_cell_count) {
				new_row << dead
			} else if is_overpopulation(cell, living_cell_count) {
				new_row << dead
			}
		}

		new_board << new_row
	}

	return new_board
}

fn print_board(board [][]int) {
	for row in board {
		mut s := '|'
		for c in row {
			s += ' $c |'
		}
		println(s)
	}
}

//////////////////////////////////////////////////
//   メイン処理
//////////////////////////////////////////////////

mut board := [
	[dead, dead, dead, dead, dead],
	[dead, dead, dead, dead, dead],
	[dead, live, live, live, dead],
	[dead, dead, dead, dead, dead],
	[dead, dead, dead, dead, dead],
]

for {
	board = next_step(board)
	print_board(board)
	println('------------------------------')
	time.sleep(1)
}

実行方法

公式リポジトリからmakeしてPATH通して動かしました。

git clone https://github.com/vlang/v.git
cd v
make
sudo cp -p v /usr/local/bin

cd ..
v run gameoflife.v

感想

構文はGoととても似ているけれど要所要所が違う。
今回書いてみたコードだけでもこれだけ違うことに気づいた。

  • 変数宣言がmut 変数名 := 値。mutつけないと値を変更できない。
  • 配列の長さの取得がarray.len
  • 文字列リテラルにシングルクォートを使う
  • 文字列内で変数展開ができる $variable_name
  • 命名規則がlower_snake_case
  • 値ループがfor value in elements
  • 関数宣言がfn
  • 配列宣言にいきなり[1, 2, 3]と書ける
  • 空配列の宣言がmut array := []type_name
  • 配列の末尾要素追加がarray << item

構文だけみたらGoより多少簡単に書けるように変更が入ってるのかな、くらい。
標準ライブラリを読んだ感じTODOも多いしコンパイラ自体にバグも多い。

始まったばかりですし今後どう変わっていくかに期待します。

ちなみに、ネストしたマルチラインコメントに対応してなかったので、バグ修正のPR投げたりしました。
https://github.com/vlang/v/pull/917
(公式ドキュメントではネストしたコメントOKとか書いてあったはずなのになぜ対応してなかったのか)

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?