slackで出来るテトリス作りました。

slackでテトリス作って見ました。

遅いけど、
まぁまぁ楽しめるかもしれません。

github.com

写真載せようと思って
起動して見たら、Invalid Oauthと出てしまったので、
Debug時にアクセスしすぎたかもしれません。
slackさんすみません。。。

自分でやって見てください。

これを機にgem化とかして見たいです。

Unity 遺伝的アルゴリズムでマリオ作って見た。

C#の練習がてらunityで遺伝的アルゴリズムを可視化して見ました。

やっぱりinstantiate関数は重いですね。
重いということを実感できました。
途中でマテリアルだけ貼りかえるように変えました。

f:id:pascal_tongue:20170910143632p:plain
正解のデータ

f:id:pascal_tongue:20170910143636p:plain
途中の感じ

見てるだけでちょっと面白いかも。

github.com

pythonでテトリス作ってみた

私は自分で書くならRubyが好きなのですが、
Rubyで書いた人のコードはとても読みにくいような気がするので(たまたまかも)
仕事ではPythonが使いたいですね。

python3です!

from enum import Enum
import random
import time
import threading
from getch import getch, pause

Status = Enum("Status", "NONE, WALL, ACTIVE, FIX")

BLOCKS = [
        [ [0, 1, 0, 0], [1, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [0, 1, 1, 0], [1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [1, 1, 0, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [1, 1, 1, 1], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [1, 1, 0, 0], [1, 1, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [1, 0, 0, 0], [1, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        [ [0, 0, 1, 0], [1, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], ],
        ];

class Field:
    HEIGHT = 20
    WIDTH = 11
    DELETE_LINE = [ Status.WALL, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.FIX, Status.WALL]
    NEW_LINE = [ Status.WALL, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.NONE, Status.WALL]
    def __init__(self):
        self._field = self._initField();
        self._point = 0;

    def clear(self):
        for y in range(self.HEIGHT):
            for x in range(self.WIDTH):
                if self._field[y][x] == Status.ACTIVE:
                    self._field[y][x] = Status.NONE

    def write(self):
        print("\x1b[25D", self._point, "\x1b[25D")
        text = "\n\x1b[25D"
        for line in self._field:
            for l in line:
                if l == Status.WALL or l == Status.ACTIVE or l == Status.FIX:
                    text += "@ "
                else:
                    text += "_ "
            text += "\n\x1b[25D"
        print(text)

    def lineClear(self):
        for y in range(self.HEIGHT):
            if self._field[y] == self.DELETE_LINE:
                self._point += 1
                self._field.pop(y)
                self._field.insert(0, self.NEW_LINE)

    def gameFinish(self):
        return self._point >= 40

    def areBlock(self, pos):
        result = False
        for p in pos:
            if self._isBlock(p[0], p[1]):
                result = True

        return result

    def fix(self, pos):
        for p in pos:
            self._field[p[1]][p[0]] = Status.FIX

    def preFix(self, pos):
        for p in pos:
            self._field[p[1]][p[0]] = Status.ACTIVE

    def _initField(self):
        field = []
        for y in range(self.HEIGHT):
            line = []
            for x in range(self.WIDTH):
                if x == 0 or x == self.WIDTH - 1 or y == self.HEIGHT - 1:
                    line.append(Status.WALL)
                else:
                    line.append(Status.NONE)
            field.append(line)
        return field

    def _isBlock(self, x, y):
        return self._field[y][x] == Status.WALL or self._field[y][x] == Status.FIX


class Current:
    def __init__(self, x, y, block = None):
        self._x = x
        self._y = y
        if block == None:
            self._current = self._newBlock()
        else:
            self._current = block

    def movePosition(self):
        b_pos = []
        for y in range(4):
            for x in range(4):
                if self._current[y][x] == 1:
                    b_pos.append([self._x + x, self._y + y])
        return b_pos


    def right(self):
        return Current(self._x + 1, self._y, self._current)

    def left(self):
        return Current(self._x - 1, self._y, self._current)

    def fall(self):
        return Current(self._x, self._y + 1, self._current)

    def rotation(self):
        tmp = [[0 for i in range(4)] for j in range(4)]
        for i in range(4):
            for j in range(4):
                tmp[j][i] = self._current[i][j]
        for i in range(4):
            tmp[i].reverse()
        return Current(self._x, self._y, tmp)

    def _newBlock(self):
        return random.choice(BLOCKS)


class InputThread(threading.Thread):
    def __init__(self):
        super(InputThread, self).__init__()
        self._cmd = 'n'

    def run(self):
        i = 0
        while True:
            key = getch()
            self._cmd = key
            if key == 'q':
                break

    def getCmd(self):
        return self._cmd

    def resetCmd(self):
        self._cmd = 'n'


def displayClear():
    print("\x1b[2J\x1b[0;0H" , end = "")

def main():
    displayClear()

    field = Field()
    field.write()

    current = Current(5, 0)

    th = InputThread()
    th.start()

    while True:
        time.sleep(0.1)
        displayClear()
        print("left: f, right: j, rotate: space, q: break \x1b[25D")
        if th.getCmd() == 'f':
            tmp = current.left()
        elif th.getCmd() == 'j':
            tmp = current.right()
        elif th.getCmd() == ' ':
            tmp = current.rotation()
        else:
            tmp = current.fall()
        next_pos = tmp.movePosition()

        if not field.areBlock(next_pos):
            field.preFix(next_pos)
            current = tmp
        elif th.getCmd() != 'n':
            current = current
        else:
            current_pos = current.movePosition()
            field.fix(current_pos)
            current = Current(5, 0)
            next_pos = current.movePosition()
            if field.areBlock(next_pos):
                print("game over")
                break
        field.write()
        field.clear()
        field.lineClear()
        th.resetCmd()
        if field.gameFinish():
            print("success!!!!!!")
            break

if __name__ == '__main__':
    main()

Go言語でlife game 作ってみた

Go言語いいですよね。
早く使いこなせるようになりたいなと思っています。

/*
誕生 死んでいるセルに隣接する生きたセルがちょうど3つあれば、次の世代が誕生する。
生存 生きているセルに隣接する生きたセルが2つか3つならば、次の世代でも生存する。
過疎 生きているセルに隣接する生きたセルが1つ以下ならば、過疎により死滅する。
過密 生きているセルに隣接する生きたセルが4つ以上ならば、過密により死滅する
*/

package main

import (
	"fmt"
	"math/rand"
	"time"
)

const (
	COUNT   int = 20
	LIVE    int = 1
	DEATH   int = 0
	PIONEER int = 200
)

type Field struct {
	cells [][]int
}

func New() *Field {
	_cells := make([][]int, COUNT)
	for i := 0; i < COUNT; i++ {
		_cells[i] = make([]int, COUNT)
	}
	return &Field{
		cells: _cells,
	}
}

func (f *Field) RandomBirthday() {
	for i := 0; i < PIONEER; i++ {
		f.cells[random()][random()] = LIVE
	}
}

func random() int {
	rand.Seed(time.Now().UnixNano())
	return rand.Intn(COUNT)
}

func (f Field) DecideLife(x int, y int) int {
	neighborCount := f.getNeighborsCount(x, y)
	if f.isUnderPopulation(neighborCount) || f.isOverPopulation(neighborCount) {
		return DEATH
	} else if f.isJustPopulation(neighborCount) {
		return LIVE
	} else {
		return f.cells[x][y]
	}
}

func (f Field) Write() {
	for _, line := range f.cells {
		for _, l := range line {
			if l == DEATH {
				fmt.Print(". ")
			} else {
				fmt.Print("o ")
			}
		}
		fmt.Print("\n")
	}
	fmt.Print("\n")
}

func (f Field) getNeighborsCount(x int, y int) int {
	result := 0
	if f.isOver0(x-1) && f.isOver0(y-1) && f.isExists(x-1, y-1) {
		result += 1
	}
	if f.isOver0(y-1) && f.isExists(x, y-1) {
		result += 1
	}
	if f.isUnderCount(x+1) && f.isOver0(y-1) && f.isExists(x+1, y-1) {
		result += 1
	}
	if f.isOver0(x-1) && f.isExists(x-1, y) {
		result += 1
	}
	if f.isUnderCount(x+1) && f.isExists(x+1, y) {
		result += 1
	}
	if f.isOver0(x-1) && f.isUnderCount(y+1) && f.isExists(x-1, y+1) {
		result += 1
	}
	if f.isUnderCount(y+1) && f.isExists(x, y+1) {
		result += 1
	}
	if f.isUnderCount(x+1) && f.isUnderCount(y+1) && f.isExists(x+1, y+1) {
		result += 1
	}
	return result
}

func (f *Field) SetCell(_cells [][]int)          { f.cells = _cells }
func (f Field) isExists(x int, y int) bool       { return f.cells[x][y] == LIVE }
func (f Field) isUnderPopulation(count int) bool { return count == 0 || count == 1 }
func (f Field) isOverPopulation(count int) bool  { return count >= 4 }
func (f Field) isJustPopulation(count int) bool  { return count == 3 }
func (f Field) isOver0(num int) bool             { return num >= 0 }
func (f Field) isUnderCount(num int) bool        { return num < COUNT }

func main() {
	field := New()
	field.RandomBirthday()
	field.Write()
	for i := 0; i < 500; i++ {
		cells := make([][]int, COUNT)
		for i := 0; i < COUNT; i++ {
			cells[i] = make([]int, COUNT)
		}

		for x := 0; x < COUNT; x++ {
			for y := 0; y < COUNT; y++ {
				cells[x][y] = field.DecideLife(x, y)
			}
		}
		field.SetCell(cells)
		field.Write()
		time.Sleep(100 * time.Millisecond)
	}
}

最近周りにプログラミングする人が増えて来て嬉しいです。
友達と一緒にプロダクト作るとかはやって見たいですね:)

rubyでテトリス

rubyでterminalでのテトリス作って見ました。
無理矢理なところも結構あるので
いずれ時間があればリファクタリングとかするかもしれないです。

require 'io/console'

BLOCKS = [
      [ [0, 1, 0],
        [1, 1, 1] ],

      [ [0, 1, 1],
        [1, 1, 0] ],

      [ [1, 1, 0],
        [0, 1, 1] ],

      [ [1, 1, 1, 1], ],

      [ [1, 1],
        [1, 1] ],

      [ [1, 0, 0],
        [1, 1, 1] ],

      [ [0, 0, 1],
        [1, 1, 1] ],
]

class Field
      WIDTH = 11
      HEIGHT = 20
      WALL = 1
      NONE = 0
      FIX = 3
      ACTIVE = 2
      FINISH_COUNT = 40
      attr_reader :point

      def initialize()
            @field = init_field
            @point  = 0
      end
      def clear()
            @field.each_with_index do |line, y|
                  line.each_with_index do |l, x|
                       @field[y][x] = 0 if l == ACTIVE
                  end
            end
      end

      def line_clear()
            @field.each_with_index do |line, y|
                  if line == [WALL, FIX, FIX, FIX, FIX, FIX, FIX, FIX, FIX, FIX, WALL]
                        @point += 1
                        @field.delete_at(y)
                        @field.insert(0, [WALL, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, NONE, WALL])
                  end
            end
      end

      def game_finish?()
            @point >= 40
      end

      def are_block?(next_pos)
            result = false
            next_pos.each do |pos|
                  if is_block?(pos[0], pos[1])
                        result = true
                  end
            end
            result
      end

      def fix(now_pos)
            now_pos.each do |pos|
                  @field[pos[1]][pos[0]] = FIX
            end
      end

      def pre_fix(now_pos)
            now_pos.each do |pos|
                  @field[pos[1]][pos[0]] = ACTIVE
            end
      end

      def write()
            text = "\n\e[25D"
            @field.each do |line|
                  line.each do |l|
                        if l == NONE
                              text += "_ "
                        elsif l == ACTIVE || l == FIX
                              text += "o "
                        else
                              text += "# "
                        end
                  end
                  text += "\n\e[25D"
            end
            puts text
      end

      private
      def is_block?(x, y)
            @field[y][x] == WALL || @field[y][x] == FIX
      end

      def init_field
            f = []
            HEIGHT.times do |i|
                  line = []
                  WIDTH.times do |j|
                        line[j] = (j == 0 || j == WIDTH - 1 || i == HEIGHT - 1) ? WALL : NONE
                  end
                  f[i] = line
            end
            return f
      end
end

class Current
      def initialize(x, y, current = new_block)
            @x = x
            @y = y
            @current = current
      end

      def move_position()
            count = 0
            block_position = Array.new(4)
            @current.each_with_index do |block, y|
                  block.each_with_index do |b, x|
                        if b == 1
                              block_position[count] = [ @x + x, @y + y ]
                              count += 1
                        end
                  end
            end
            block_position
      end

      def right()
            Current.new(@x + 1, @y, @current)
      end

      def left()
            Current.new(@x - 1, @y, @current)
      end

      def fall()
            Current.new(@x, @y + 1, @current)
      end

      def rotation()
            tmp = Array.new(4){ Array.new(4, 0)}
            #転置させて、行の順番をひっくりかえす
            @current.each_with_index do |line, y|
                  line.each_with_index do |l, x|
                        tmp[x][y] = l
                  end
            end
            tmp.each_with_index do |line, i|
                  tmp[i] = line.reverse
            end
            Current.new(@x, @y, tmp)
      end

      def new_block()
            rnd = rand(BLOCKS.length)
            block = BLOCKS[rnd]

            current = Array.new(4){ Array.new(4, 0)}
            block.each_with_index do |line, i|
                  line.each_with_index do |l, j|
                        if l == 1
                              current[i][j] = 1
                        end
                  end
            end
            current
      end

      def write()
            @current.each do |line|
                  p line
            end
            # puts @x
            # puts @y
            puts ""
      end

      private
end

def display_clear()
      print "\x1b[2J\x1b[0;0H"
end

def main()
      display_clear()

      field = Field.new()
      field.write()

      current = Current.new(5, 0)
      current.write()

      cmd = 'n'
      thread = Thread::start do
            while (cmd = STDIN.getch)
                  if cmd ==  "\C-c"
                        break
                  end
            end
      end
      loop do
            sleep(0.2)
            display_clear()
            puts "left: f, right: j, rotate: space\e[25D"
            puts "\e[25D#{field.point}\e[25D"
            case cmd
            when 'f' then
                  tmp = current.left
            when 'j' then
                  tmp = current.right
            when ' ' then
                  tmp = current.rotation
            else
                  tmp = current.fall
            end
            next_pos = tmp.move_position
            # p next_pos
            if !field.are_block?(next_pos)
                  field.pre_fix(next_pos)
                  current = tmp
            elsif cmd != 'n'
                  current = current
            else
                  field.fix(current.move_position)
                  current = Current.new(5, 0)
                  next_pos = current.move_position
                  if field.are_block?(next_pos)
                        puts "game over"
                        break
                  end
            end
            field.write
            field.clear
            field.line_clear
            cmd = 'n'
            if field.game_finish?()
                  puts "success!!!!!!"
                  break
            end
      end
      Thread.kill(thread)
end

main()

まぁlispの勉強のためにお手本的なノリで書いたので
lispでは綺麗に短く書いていけたらなと思っています.

Go言語で8クイーン

久しぶりにGo言語が書いて見たくなって
8クイーン実装して見ました。

package main

import "fmt"

type Queen struct {
	num    int
	count  int
	result []int
}

func new(_num int) *Queen {
	_result := make([]int, _num)
	i := 0
	for i < _num {
		_result[i] = -1
		i++
	}
	return &Queen{
		num:    _num,
		count:  0,
		result: _result,
	}
}

func (queen *Queen) queen(y int) {
	for x := 0; x < queen.num; x++ {
		queen.init_array(y)
		if !queen.can_putp(x, y) {
			continue
		}
		queen.put(x, y)
		if y == queen.num-1 {
			queen.count++
			queen.write()
		} else {
			queen.queen(y + 1)
		}
	}
}

func (queen *Queen) init_array(y int) {
	for i := 0; i < queen.num; i++ {
		if i >= y {
			queen.result[i] = -1
		}
	}
}

func (queen Queen) can_putp(x int, y int) bool {
	return queen.result[y] == -1 && !queen.is_includep(x) && queen.slant_checkp(x, y)
}

func (queen Queen) is_includep(x int) bool {
	b := false
	for _, value := range queen.result {
		if value == x {
			b = true
		}
	}
	return b
}

func (queen Queen) slant_checkp(x int, y int) bool {
	tmp1 := y - x
	tmp2 := y + x
	b := true
	for _y, _x := range queen.result {
		if _x == -1 {
			continue
		}
		if _y == _x+tmp1 || _y == (-_x)+tmp2 {
			b = false
		}
	}
	return b
}

func (queen Queen) write() {
	for y := 0; y < queen.num; y++ {
		for x := 0; x < queen.num; x++ {
			if queen.result[y] == x {
				fmt.Print("Q ")
			} else {
				fmt.Print(". ")
			}
		}
		fmt.Print("\n")
	}
	fmt.Println(queen.count)
	fmt.Print("\n")
}

func (queen *Queen) put(x int, y int) {
	queen.result[y] = x
}

func main() {
	q := new(8)
	q.queen(0)
}

Go言語はとても見やすいですよね。

私は飽き性で色々な言語を触ってみるのですが、
Rubyはノリノリで書けますし、
Goは誰でも読めると思うし、
Lispテトリスのような気持ちでかけるし、
phpはすぐになんでも書けちゃうし、
それぞれいいところがありますよね。プログラマーになってよかったです笑

pythonでlifegameしてみた

pythonでlifegameして見ました。
lisppythonってめっちゃ目を細めてみると似ていますね。

import random

COUNT = 20
LIVE = 'o '
DEATH = '_ '
PIONEER = 100

class Field:
    def __init__(self):
        self._cells = [[DEATH for i in range(COUNT)] for j in range(COUNT)]

    def random_birthday(self):
        for i in range(PIONEER):
            self._cells[random.randint(0, COUNT - 1)][random.randint(0, COUNT - 1)] = LIVE

    def decide_life(self, x, y):
        neighbor_count = self._get_neighbors_count(x, y)
        if self._is_exists(x, y):
            if self._is_under_population(neighbor_count) or self._is_over_population(neighbor_count):
                self._death_cell(x, y)
        else:
            if self._is_just_population(neighbor_count):
                self._live_cell(x, y)

    def write(self):
        for line in self._cells:
            for l in line:
                print(l, end="")
            print("")
        print("")


    def _is_under_population(self, count):
        return count == 0 or count == 1

    def _is_over_population(self, count):
        return count >= 4

    def _is_just_population(self, count):
        return count == 3

    def _live_cell(self, x, y):
        self._cells[x][y] = LIVE

    def _death_cell(self, x, y):
        self._cells[x][y] = DEATH

    def _is_exists(self, x, y):
        return self._cells[x][y] == LIVE

    def _get_neighbors_count(self, x, y):
        result = 0
        if self._over0(x-1) and self._over0(y-1) and self._is_exists(x-1, y-1): result += 1
        if self._over0(y-1) and self._is_exists(x, y-1): result += 1
        if self._under_count(x+1) and self._over0(y-1) and self._is_exists(x+1, y-1): result += 1
        if self._over0(x-1) and self._is_exists(x-1, y): result += 1
        if self._under_count(x+1) and self._is_exists(x+1, y): result += 1
        if self._over0(x-1) and self._under_count(y+1) and self._is_exists(x-1, y+1): result += 1
        if self._under_count(y+1) and self._is_exists(x, y+1): result += 1
        if self._under_count(x+1) and self. _under_count(y+1) and self._is_exists(x+1, y+1): result += 1
        return result

    def _over0(self, num):
        return num >= 0

    def _under_count(self, num):
        return num < COUNT


def main():
    field = Field()
    field.random_birthday()
    field.write()
    i = 0
    while i < 500:
        for x in range(COUNT - 1):
            for y in range(COUNT - 1):
                field.decide_life(x, y)
        field.write()
        i += 1

if __name__ == "__main__":
    main()