Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- a) (5%)
- Du kan representere brettet slik du selv vil, men vi anbefaler at du bruker en liste av lister og bruker f.eks. True, 1 eller '*' for levende celler og False, 0 eller ' ' for døde celler. I såfall vil Steg 1 i illustrasjonen over være lagret slik:
- board = [['*', ' ', ' '],
- [' ', '*', ' '],
- [' ', '*', '*']]
- og du kan finne celle (x,y) med board[y][x]. F.eks. vil board[0][0] vil være øverste venstre hjørne og board[2][0] er nederste venstre hjørne. Andre alternativer er f.eks. å bruke en liste av kolonner i stedet for liste av rader, en dict med koordinater som nøkkel, en enkelt liste med radene liggende etter hverandre (slik at (x,y) f.eks. er på indeks y*w+x).
- Velg representasjon for brettet, og lag et lite eksempel-brett (f.eks. som board over)
- Lag en get og en set funksjon (evt. metode) som henter eller oppdaterer cellen på en gitt x, y koordinat
- b) (7%)
- Lag en funksjon som tar imot bredde og høyde, og lager et brett og fyller det med tilfeldige data. Du kan bruke random-modulen for tilfeldige data, f.eks. random.choice eller random.randint.
- Hvis du har valgt objekt-løsningen vil dette være konstruktøren, __init__(self, w, h); hvis ikke kan du kalle den f.eks. make_board(w, h))
- c) (10%)
- Lag en funksjon neighbours som finner antall levende naboer for en celle. Den bør ta x, y-koordinatene for cellen som argument (samt evt. brettet), og returnere et heltall. Bruk get-funksjonen du har laget for å sjekke innholdet i en celle. Naboene har disse koordinatene:
- (x-1,y-1)
- (x,y-1)
- (x+1,y-1)
- (x-1,y)
- (x,y)
- (x+1,y)
- (x-1,y+1)
- (x,y+1)
- (x+1,y+1)
- Du kan velge å kreve at x,y ikke ligger på kanten av brettet, slik at du vet at cellen har gyldige naboceller i alle retninger. Sjekk i såfall at koordinatene er gyldige med assert eller if/raise. Alternativt kan du gjøre det slik at de ytterste cellene bare har «døde» naboer på utsiden av brettet, f.eks. (hvor cellene med grå bakgrunn er «virtuelle» celler utenfor brettet):
- d) (13%)
- Lag en funksjon (eller metode) step() som utfører ett steg av simuleringen. Dvs., for hver celle i den nye tabellen, finn ut hvor mange levende naboer cellen hadde fra før, og sett cellen til 1 eller 0 i tråd med reglene over.
- Alle cellene skal endre tilstand samtidig, så vi trenger å bevare det nåværende brettet mens vi beregner hvilke celler som skal overleve/dø/vokse. Det er derfor antakelig lettest å lagre brettet for neste steg i en ny liste.
- e) (5%)
- Lag en funksjon som printer ut brettet på en passende måte (f.eks. med '*' for levende og ' ' for døde celler). Hvis du har implementert brettet som en klasse, kan du gjøre dette ved å implementere __str__-metoden – den skal i såfall returnere en streng, og ikke print-e noe selv.
- Du kan evt. få ting til å se ganske bra ut med Unicode blokk-tegn, '█' ('\u2588'), evt i kombinasjon med box drawing-tegn – på eksamen holder det selvfølgelig med '*'.
- #### ELEGANT LØSNING m/objekter
- ## a)
- # Brett-data lagres i en liste:
- # [1,0,0,
- # 0,1,0,
- # 0,1,1]
- # Board-klassen har __getitem__ og __setitem__ som gjør at vi kan
- # bruke board[x, y] og board[x,y] = value for å jobbe med de enkelte cellene
- class Board:
- """A two-dimensional board."""
- def __init__(self, width, height, filler = None, initial = None):
- assert width > 0 and height > 0, "Width and height must be > 0"
- self.width = width
- self.height = height
- if initial != None:
- assert len(initial) == width*height
- self.data = initial.copy()
- else:
- self.data = [filler] * (width*height)
- def __getitem__(self, pos):
- """Get item at position (x,y). E.g. board[x,y]"""
- x, y = pos
- assert x >= 0 and x < self.width, f"X must be 0 <= {x} < {self.width}"
- assert y >= 0 and y < self.width, f"Y must be 0 <= {y} < {self.height}"
- return self.data[x + y*self.width]
- def __setitem__(self, pos, v):
- """Set item at position (x,y). E.g. board[x,y] = v"""
- x, y = pos
- assert x >= 0 and x < self.width, f"X must be 0 <= {x} < {self.width}"
- assert y >= 0 and y < self.width, f"Y must be 0 <= {y} < {self.height}"
- self.data[x + y*self.width] = v
- def get(self, x, y, default):
- """Return cell at (x,y) or default if (x,y) is outside board"""
- if x < 0 or x >= self.width or y < 0 or y >= self.height:
- return default
- else:
- return self.data[x + y*self.width]
- def copy(self):
- return Board(self.width, self.height, initial=self.data)
- def __str__(self):
- rows = []
- for y in range(self.height):
- row = []
- for x in range(self.width):
- row.append(str(self[x, y]))
- rows.append(', '.join(row))
- return '\n'.join(rows)
- class GameOfLife:
- def __init__(self, width, height):
- self.board = Board(width, height, filler = 0)
- for y in range(height):
- for x in range(width):
- self.board[x,y] = random.randint(0,1)
- def neighbours(self, x, y):
- ns = [(-1,-1), (0,-1), (1,-1), (-1,0), (1,0), (-1,1), (0,1), (1,1)]
- living = 0
- for dx, dy in ns:
- living += self.board.get(x+dx, y+dy, 0) # 0 er default verdi for utenfor brettet
- return living
- # evt:
- #return sum([self.board.get(x+dx,y+dy, 0) for dx, dy in ns])
- def step(self):
- new_board = self.board.copy()
- for y in range(self.board.height):
- for x in range(self.board.width):
- neighs = self.neighbours(x, y)
- if self.board[x, y] == 1 and (neighs < 2 or neighs > 3):
- new_board[x, y] = 0
- elif self.board[x, y] == 0 and neighs == 3:
- new_board[x, y] = 1
- # uendret i de andre tilfellene
- self.board = new_board
- def __str__(self):
- head_foot = '+' + '--' * self.board.width + '+'
- rows = [head_foot]
- for y in range(self.board.height):
- row = ['|']
- for x in range(self.board.width):
- if self.board[x,y] == 1:
- row.append('██')
- else:
- row.append(' ')
- row.append('|')
- rows.append(''.join(row))
- rows.append(head_foot)
- return '\n'.join(rows)
- life = GameOfLife(10, 10)
- for i in range(20):
- print(life)
- life.step()
- print(life)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement