×
Dodano do koszyka:
Pozycja znajduje się w koszyku, zwiększono ilość tej pozycji:
Zakupiłeś już tę pozycję:
Książkę możesz pobrać z biblioteki w panelu użytkownika
Pozycja znajduje się w koszyku
Przejdź do koszyka

Zawartość koszyka

ODBIERZ TWÓJ BONUS :: »

Sudoku z Pythonem

Sudoku z Pythonem


001: """Sudoku, autor: Al Sweigart, al@inventwithpython.com
002: Klasyczna  układanka liczbowa z planszą 9x9.
003: Więcej informacji na stronie https://pl.wikipedia.org/wiki/Sudoku.
004: Kod pobrany ze strony https://ftp.helion.pl/przyklady/wiksma.zip.
005: Etykiety: długi, gra, zorientowany obiektowo, łamigłówka"""
006: 
007: import copy, random, sys
008: 
009: # Ta gra wymaga pliku sudokupuzzle.txt, który zawiera łamigłówkę.
010: # Plik możesz pobrać ze strony https://ftp.helion.pl/przyklady/wiksma.zip.
011: # Oto przykład zawartości takiego pliku:
012: # ..3.2.6..9..3.5..1..18.64....81.29..7.......8..67.82....26.95..8..2.3..9..5.1.3..
013: # 2...8.3...6..7..84.3.5..2.9...1.54.8.........4.27.6...3.1..7.4.72..4..6...4.1...3
014: # ......9.7...42.18....7.5.261..9.4....5.....4....5.7..992.1.8....34.59...5.7......
015: # .3..5..4...8.1.5..46.....12.7.5.2.8....6.3....4.1.9.3.25.....98..1.2.6...8..6..2.
016: 
017: # Deklaracja stałych:
018: EMPTY_SPACE = '.'
019: GRID_LENGTH = 9
020: BOX_LENGTH = 3
021: FULL_GRID_SIZE = GRID_LENGTH * GRID_LENGTH
022: 
023: 
024: class SudokuGrid:
025:     def __init__(self, originalSetup):
026:         # Zmienna originalSetup to łańcuch 81 znaków początkowego stanu
027:         # planszy, z liczbami i kropkami (dla pustych pól).
028:         # Patrz plik sudokupuzzles.txt
029:         self.originalSetup = originalSetup
030: 
031:         # Dany stan planszy sudoku jest przedstawiony za pomocą słownika
032:         # z kluczami (x, y) i wartością liczbową (zapisaną w formie łańcucha znaków) w
033:         # przypisanym do klucza miejscu.
034:         self.grid = {}
035:         self.resetGrid()  # Przywróć planszę do stanu początkowego.
036:         self.moves = []  # Zapisuje każdy ruch, co jest przydatne podczas korzystania z funkcji Cofnij.
037: 
038:     def resetGrid(self):
039:         """Przywraca początkowy stan planszy,
040:         zapisany w self.originalSetup."""
041:         for x in range(1, GRID_LENGTH + 1):
042:             for y in range(1, GRID_LENGTH + 1):
043:                 self.grid[(x, y)] = EMPTY_SPACE
044: 
045:         assert len(self.originalSetup) == FULL_GRID_SIZE
046:         i = 0  # i rośnie od 0 do 80
047:         y = 0  # y rośnie od 0 do 8
048:         while i < FULL_GRID_SIZE:
049:             for x in range(GRID_LENGTH):
050:                 self.grid[(x, y)] = self.originalSetup[i]
051:                 i += 1
052:             y += 1
053: 
054:     def makeMove(self, column, row, number):
055:         """Umieszcza na planszy liczbę w danej kolumnie (litera od A do I)
056:         i danym wierszu (liczba całkowita od 1 do 9)."""
057:         x = 'ABCDEFGHI'.find(column)  # Zamień na liczbę całkowitą.
058:         y = int(row) - 1
059: 
060:         # Sprawdź, czy dany ruch jest wykonywany na liczbie, która jest podana na początku gry:
061:         if self.originalSetup[y * GRID_LENGTH + x] != EMPTY_SPACE:
062:             return False
063: 
064:         self.grid[(x, y)] = number  # Umieść tę liczbę na siatce.
065: 
066:         # Musimy zapisać osobną kopię słownika:
067:         self.moves.append(copy.copy(self.grid))
068:         return True
069: 
070:     def undo(self):
071:         """Przywróć stan planszy do poprzedniego stanu
072:         zapisanego w liście self.moves."""
073:         if self.moves == []:
074:             return  # Brak danych w self.moves, nic nie rób.
075: 
076:         self.moves.pop()  # Usuń dane bieżącego stanu.
077: 
078:         if self.moves == []:
079:             self.resetGrid()
080:         else:
081:             # Ustaw poprzedni stan siatki:
082:             self.grid = copy.copy(self.moves[-1])
083: 
084:     def display(self):
085:         """Wyświetl aktualny stan planszy na ekranie."""
086:         print('   A B C   D E F   G H I')  # Wyświetl oznaczenia kolumn.
087:         for y in range(GRID_LENGTH):
088:             for x in range(GRID_LENGTH):
089:                 if x == 0:
090:                     # Wyświetl oznaczenia wierszy:
091:                     print(str(y + 1) + '  ', end='')
092: 
093:                 print(self.grid[(x, y)] + ' ', end='')
094:                 if x == 2 or x == 5:
095:                     # Wyświetl linię pionową:
096:                     print('| ', end='')
097:             print()  # Wyświetl znak nowej linii:
098: 
099:             if y == 2 or y == 5:
100:                 # Wyświetl linię poziomą:
101:                 print('   ------+-------+------')
102: 
103:     def _isCompleteSetOfNumbers(self, numbers):
104:         """Zwraca wartość True, jeśli liczby zawierają cyfry od 1 do 9."""
105:         return sorted(numbers) == list('123456789')
106: 
107:     def isSolved(self):
108:         """Zwraca wartość True, jeśli bieżący stan planszy to rozwiązanie."""
109:         # Sprawdź każdy wiersz:
110:         for row in range(GRID_LENGTH):
111:             rowNumbers = []
112:             for x in range(GRID_LENGTH):
113:                 number = self.grid[(x, row)]
114:                 rowNumbers.append(number)
115:             if not self._isCompleteSetOfNumbers(rowNumbers):
116:                 return False
117: 
118:         # Sprawdź każdą kolumnę:
119:         for column in range(GRID_LENGTH):
120:             columnNumbers = []
121:             for y in range(GRID_LENGTH):
122:                 number = self.grid[(column, y)]
123:                 columnNumbers.append(number)
124:             if not self._isCompleteSetOfNumbers(columnNumbers):
125:                 return False
126: 
127:         # Sprawdź każdy blok 3x3:
128:         for boxx in (0, 3, 6):
129:             for boxy in (0, 3, 6):
130:                 boxNumbers = []
131:                 for x in range(BOX_LENGTH):
132:                     for y in range(BOX_LENGTH):
133:                         number = self.grid[(boxx + x, boxy + y)]
134:                         boxNumbers.append(number)
135:                 if not self._isCompleteSetOfNumbers(boxNumbers):
136:                     return False
137: 
138:         return True
139: 
140: 
141: print('''Sudoku, autor: Al Sweigart, al@inventwithpython.com
142: 
143: Sudoku to układanka liczbowa. Plansza sudoku to siatka 9x9.
144: Spróbuj umieścić na siatce liczby w taki sposób, by dana cyfra od 1 do 9
145: występowała tylko raz w danym wierszu, kolumnie i bloku 3x3.
146: 
147: Oto przykładowa plansza na początku gry i już rozwiązana:
148: 
149:     5 3 . | . 7 . | . . .     5 3 4 | 6 7 8 | 9 1 2
150:     6 . . | 1 9 5 | . . .     6 7 2 | 1 9 5 | 3 4 8
151:     . 9 8 | . . . | . 6 .     1 9 8 | 3 4 2 | 5 6 7
152:     ------+-------+------     ------+-------+------
153:     8 . . | . 6 . | . . 3     8 5 9 | 7 6 1 | 4 2 3
154:     4 . . | 8 . 3 | . . 1 --> 4 2 6 | 8 5 3 | 7 9 1
155:     7 . . | . 2 . | . . 6     7 1 3 | 9 2 4 | 8 5 6
156:     ------+-------+------     ------+-------+------
157:     . 6 . | . . . | 2 8 .     9 6 1 | 5 3 7 | 2 8 4
158:     . . . | 4 1 9 | . . 5     2 8 7 | 4 1 9 | 6 3 5
159:     . . . | . 8 . | . 7 9     3 4 5 | 2 8 6 | 1 7 9
160: ''')
161: input('Naciśnij Enter, aby rozpocząć...')
162: 
163: 
164: # Wgraj plik sudokupuzzles.txt:
165: with open('sudokupuzzles.txt') as puzzleFile:
166:     puzzles = puzzleFile.readlines()
167: 
168: # Usuń znak nowej linii na końcu każdej łamigłówki:
169: for i, puzzle in enumerate(puzzles):
170:     puzzles[i] = puzzle.strip()
171: 
172: grid = SudokuGrid(random.choice(puzzles))
173: 
174: while True:  # Główna pętla gry.
175:     grid.display()
176: 
177:     # Sprawdź, czy sudoku zostało rozwiązane.
178:     if grid.isSolved():
179:         print('Gratulacje! Rozwiązałeś łamigłówkę!')
180:         print('Dziękujemy za grę!')
181:         sys.exit()
182: 
183:     # Pobierz ruch gracza:
184:     while True:  # Pytaj, dopóki gracz nie poda prawidłowego działania.
185:         print()  # Wyświetl znak nowej linii.
186:         print('Podaj ruch lub wpisz RESET, NOWA, COFNIJ, POCZĄTEK lub KONIEC:')
187:         print('(Przykładowy ruch to "B4 9".)')
188: 
189:         action = input('> ').upper().strip()
190: 
191:         if len(action) > 0 and action[0] in ('R', 'N', 'C', 'P', 'K'):
192:             # Gracz podał prawidłowe działanie.
193:             break
194: 
195:         if len(action.split()) == 2:
196:             space, number = action.split()
197:             if len(space) != 2:
198:                 continue
199: 
200:             column, row = space
201:             if column not in list('ABCDEFGHI'):
202:                 print('Nie ma takiej kolumny', column)
203:                 continue
204:             if not row.isdecimal() or not (1 <= int(row) <= 9):
205:                 print('Nie ma takiego wiersza', row)
206:                 continue
207:             if not (1 <= int(number) <= 9):
208:                 print('Wybierz cyfrę od 1 do 9, a nie ', number)
209:                 continue
210:             break  # Gracz podał odpowiedni ruch.
211: 
212:     print()  # Wyświetl znak nowej linii.
213: 
214:     if action.startswith('R'):
215:         # Przywróć planszę do stanu początkowego:
216:         grid.resetGrid()
217:         continue
218: 
219:     if action.startswith('N'):
220:         # Wgraj nową łamigłówkę:
221:         grid = SudokuGrid(random.choice(puzzles))
222:         continue
223: 
224:     if action.startswith('C'):
225:         # Cofnij ostatni ruch:
226:         grid.undo()
227:         continue
228: 
229:     if action.startswith('P'):
230:         # Pokaż początkowy stan planszy:
231:         originalGrid = SudokuGrid(grid.originalSetup)
232:         print('Na początku plansza wyglądała tak:')
233:         originalGrid.display()
234:         input('Naciśnij Enter, aby rozpocząć...')
235: 
236:     if action.startswith('K'):
237:         # Wyjdź z gry.
238:         print('Dziękujemy za grę!')
239:         sys.exit()
240: 
241:     # Wykonaj podany przez gracza ruch:
242:     if grid.makeMove(column, row, number) == False:
243:         print('Nie możesz nadpisać liczby, która była wpisana już na początku gry.')
244:         print('Wpisz POCZĄTEK, by zobaczyć planszę początkową.')
245:         input('Naciśnij Enter, aby rozpocząć...')


 

 

Zamknij Pobierz aplikację mobilną Ebookpoint