康威的生命游戏:从第二代到第三代更新

时间:2017-06-08 21:06:47

标签: python-3.x conways-game-of-life

作为对自己的挑战,我试着写出康威的生命游戏模拟器。虽然从输入值到打印出第一代和第二代,外翻工作正常,但在处理更多代时我遇到了麻烦。

到目前为止,这是我的代码:

class Game_setup:


    def __init__(self, cells):
        self.boundry = 20
        self.cells = cells
        self.x_cord = []
        self.y_cord = []
        self.cord_pairs = []
        self.coordinates = []
        self.dead_pairs = []



    def inital_values(self):
        coordinates = []
        for x in range(int(self.boundry)):
            for y in range(int(self.boundry)):
                coordinates.append([x, y])
        self.coordinates = coordinates
        return coordinates

    def intial_cells(self):
        cord_pairs = []
        with open(self.cells, 'r', encoding="utf-8") as file:
            for line in file:
                row = line.split()
                cord_pairs.append([int(row[0]),int(row[1])])
        x = []
        y = []
        for number_of_coordinates in range(len(cord_pairs)):
            x.append(cord_pairs[number_of_coordinates][0])
            y.append(cord_pairs[number_of_coordinates][1])

        self.x_cord = x
        self.y_cord = y
        self.cord_pairs = cord_pairs

        return cord_pairs

    def neighbours(self, n):
        neighbours = 0
        x_coordinate = self.cord_pairs[n][0]
        y_coordinate = self.cord_pairs[n][1]

        if [x_coordinate,y_coordinate+1] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate,y_coordinate-1] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate-1] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate+1] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate-1] in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate+1] in self.cord_pairs:
            neighbours += 1
        return neighbours


    def from_dead_to_alive(self,pair):
        x_coordinate = pair[0]
        y_coordinate = pair[1]
        neighbours = 0
        if [x_coordinate,y_coordinate+1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate,y_coordinate-1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate-1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate+1,y_coordinate+1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate-1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1
        if [x_coordinate-1,y_coordinate+1] in self.cord_pairs and [x_coordinate,y_coordinate] not in self.cord_pairs:
            neighbours += 1

        if neighbours == 3:
            self.dead_pairs.append([x_coordinate,y_coordinate])

        return neighbours

    def evaluate_initial_position(self,y_coordinate): # n är y koordinaterna som itereras över
        coordinates_to_print = []
        if y_coordinate in self.y_cord:
            x_in_y = [x_coordinate for x_coordinate, y_values in enumerate(self.y_cord) if y_values == y_coordinate]
            for items in range(len(x_in_y)):
                coordinates_to_print.append(self.x_cord[x_in_y[items]])
        for number_of_rows in range(self.boundry):
            board_rows = ''.join('X' if item in coordinates_to_print else '-' for item in list(range(self.boundry)))
            return print(board_rows)


    def nxt_gen_cell_status(self):
        status = {}

        for lenght_initial_values in range(len(life.intial_cells())):
            if life.neighbours(lenght_initial_values) == 3 or life.neighbours(lenght_initial_values) == 2:
                status[tuple(self.cord_pairs[lenght_initial_values])] = "Alive" 
            elif life.neighbours(lenght_initial_values) < 2 or life.neighbours(lenght_initial_values) > 3:
                status[tuple(self.cord_pairs[lenght_initial_values])] = "Dead"

        for lenght_dead_cells in range(len(self.dead_pairs)):
            status[tuple(self.dead_pairs[lenght_dead_cells])] = "Alive"

        return status

    def new_cells(self,status):
        del self.cord_pairs[:]
        for alive_cell in range(len(list(status.keys()))):
            kord = list(status.keys())[alive_cell]
            if status[kord] == "Alive":
                self.cord_pairs.append(list(kord))
        return self.cord_pairs

    def set_board(self):
        x = []
        y = []
        for new_coordinate in range(len(self.cord_pairs)):
            x.append(self.cord_pairs[new_coordinate][0])
            y.append(self.cord_pairs[new_coordinate][1])
        self.x_cord = x
        self.y_cord = y

        return self.cord_pairs, self.y_cord


    cells =  'www.csc.kth.se/~lk/P/glidare.txt'                                                                  
    life = Game_setup(cells)


def main():

    cell_status_ditction = {}
    life.intial_cells()

    generation = input("How many generations would you like to see?" + "\n")
    i = 0

    while i < int(generation):

        for boundry in range(10):
            life.evaluate_initial_position(boundry)

        for next_cells in range(len(life.inital_values())):
            life.from_dead_to_alive(life.inital_values()[next_cells])
            cell_status = life.nxt_gen_cell_status()
            cell_status_ditction.update(cell_status)

        life.new_cells(cell_status_ditction)
        life.set_board()

        cell_status_ditction.clear()

        print("\n" + "\n")

        i += 1
main()

注意事项:

  1. 我使用文件作为输入值[网站下载可以在这里找到:www.csc.kth.se/~lk/P/glidare.txt]
  2. 我刚刚选择了一个任意数字作为我的边界输入
  3. 除了在第二代和第三代之间更新新单元格外,Everthing工作正常 - 因此我怀疑我的方法编写方法一定有问题set_board
  4. 初始位置只是着名的滑翔机
  5. 如果我运行这三代,那就是结果:

    --------------------
    ---X----------------
    -X-X----------------
    --XX----------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    
    --------------------
    --X-----------------
    ---XX---------------
    --XX----------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    
    --------------------
    --X-----------------
    ---XX---------------
    --XX----------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    --------------------
    

    正如人们可以注意到第三个没有正确更新。有没有解决这个问题?我应该正确更新我的电路板吗?

    有关如何修复或使代码更好的任何帮助都非常感谢。我是新手编码器所以请温柔;我知道这不是最好的也不是最优的代码。

1 个答案:

答案 0 :(得分:0)

看起来像什么正在发生的事情是你的董事会没有得到新状态的更新。

我不知道python,所以我不会尝试逐行调试这段代码(或者自己编写python代码),但一般来说,Game of Life模拟器应该看起来像这样的东西(我已经抽出了一些抽象的东西,比如board的底层表示,因为这些是实现细节会有所不同,并且特定于你的代码):

#definition of board.get_neighbor_count(cell)
neighbors = 0
for(row in [cell.row - 1, cell.row + 1])
    for(column in [cell.column - 1, cell.column + 1])
        #We skip the center cell.
        if(row == 0 && column == 0) continue
        #We don't want to scan cells like [-1,0] or [20,0], which would be out of 
        #bounds. I don't know how python handles OOB accesses, but I imagine the program
        #would crash instead of behaving gracefully
        if(!board.in_bounds(row, column)) continue
        if(board.get_cell(row, column).alive) neighbors++
return neighbors

#==============================================================

#definition of board.get_next_generation()
Game_Board new_board(rows = board.rows, columns = board.columns, ruleset = board.ruleset)
for(row in [0, board.rows-1])
    for(column in [0, board.columns-1])
        cell = board.get_cell(row, column)

        neighbors = board.get_neighbor_count(cell)

        if(cell.alive && board.ruleset.survives(neighbors))
            new_board.put(cell)
        else if(cell.dead && board.ruleset.births(neighbors))
            new_board.put(cell)

return new_board

#==============================================================

#definition of main()
#Should create an empty board size 20x20. I'm assuming they'll be addressed 
#[0...rows-1],[0...columns-1]
Game_Board board{rows = 20, columns = 20, ruleset = 23S/3B}
#I'm putting values here for a Gosper Glider, but if your implementation is correct
#one could put literally anything here
board.put_starting_values({10,10}, {10,11}, {10,12}, {11,12}, {12,11})
board.print_state()
num_of_generations = 50
while(num_of_generations > 0) 
    #Note that I'm assigning a new value to `board` here! This is deliberate and
    #intended to convey explicit semantics, in that `board` should now refer to the
    #newly generated state, not the preexisting state. If, for whatever reason,
    #you need to maintain the original state, either store each successive generation
    #in an array or just the original state in a separate variable.
    board = board.get_next_generation()
    board.print_state()
    num_of_generations--

print("Done!")

你需要做的是将你的main()减少到这个逻辑流程,并找出错误的位置,因为这是一个完整的逻辑(非常简单) )GOL模拟器。以我写的方式写它应该使错误非常明显。就目前而言,你的代码包含很多内容,其中from_dead_to_alive等函数试图复制neighbors所做的工作(函数本身过于复杂)。同时,您已经拥有一个名为status的完整独立实体,负责跟踪这些单元格的评估结果,您不应该依赖这些结果,并且由于您的依赖性而使您的代码混乱它