Initial commit
This commit is contained in:
243
reversi/computerVScomputer/AISim1.py
Normal file
243
reversi/computerVScomputer/AISim1.py
Normal file
@@ -0,0 +1,243 @@
|
||||
# "Реверси": клон "Отелло".
|
||||
import random
|
||||
import sys
|
||||
WIDTH = 8 # Игровое поле содержит 8 клеток по ширине.
|
||||
HEIGHT = 8 # Игровое поле содержит 8 клеток по высоте.
|
||||
CONST_X = 'X'
|
||||
CONST_O = 'O'
|
||||
def drawBoard(board):
|
||||
# Вывести игровое поле, переданное этой функции. Ничего не возвращать.
|
||||
print(' 12345678')
|
||||
print(' +--------+')
|
||||
for y in range(HEIGHT):
|
||||
print('%s|' % (y+1), end='')
|
||||
for x in range(WIDTH):
|
||||
print(board[x][y], end='')
|
||||
print('|%s' % (y+1))
|
||||
print(' +--------+')
|
||||
print(' 12345678')
|
||||
|
||||
def getNewBoard():
|
||||
# Создать структуру данных нового чистого игрового поля.
|
||||
board = []
|
||||
for i in range(WIDTH):
|
||||
board.append([' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '])
|
||||
return board
|
||||
|
||||
def isValidMove(board, tile, xstart, ystart):
|
||||
# Вернуть False, если ход игрока в клетку с координатами xstart, ystart — недопустимый.
|
||||
# Если это допустимый ход, вернуть список клеток, которые "присвоил" бы игрок, если бы сделал туда ход.
|
||||
if board[xstart][ystart] != ' ' or not isOnBoard(xstart, ystart):
|
||||
return False
|
||||
|
||||
if tile == CONST_X:
|
||||
otherTile = CONST_O
|
||||
else:
|
||||
otherTile = CONST_X
|
||||
|
||||
tilesToFlip = []
|
||||
for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]:
|
||||
x, y = xstart, ystart
|
||||
x += xdirection # Первый шаг в направлении x
|
||||
y += ydirection # Первый шаг в направлении y
|
||||
while isOnBoard(x, y) and board[x][y] == otherTile:
|
||||
# Продолжать двигаться в этом направлении x и y.
|
||||
x += xdirection
|
||||
y += ydirection
|
||||
if isOnBoard(x, y) and board[x][y] == tile:
|
||||
#Естьфишки,которыеможноперевернуть.Двигатьсявобратномнаправлениидодостиженияисходнойклетки,отмечаявсефишкинаэтомпути.
|
||||
while True:
|
||||
x -= xdirection
|
||||
y -= ydirection
|
||||
if x == xstart and y == ystart:
|
||||
break
|
||||
tilesToFlip.append([x, y])
|
||||
|
||||
if len(tilesToFlip) == 0: # Если ни одна из фишек не перевернулась, это недопустимый ход
|
||||
return False
|
||||
return tilesToFlip
|
||||
|
||||
def isOnBoard(x, y):
|
||||
# Вернуть True, если координаты есть на игровом поле.
|
||||
return x >= 0 and x <= WIDTH - 1 and y >= 0 and y <= HEIGHT - 1
|
||||
|
||||
def getBoardWithValidMoves(board, tile):
|
||||
# Вернуть новое поле с точками, обозначающими допустимые ходы, которые может сделать игрок.
|
||||
boardCopy = getBoardCopy(board)
|
||||
|
||||
for x, y in getValidMoves(boardCopy, tile):
|
||||
boardCopy[x][y] = '.'
|
||||
return boardCopy
|
||||
|
||||
def getValidMoves(board, tile):
|
||||
# Вернуть список списков с координатами x и y допустимых ходов для данного игрока на данном игровом поле.
|
||||
validMoves = []
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if isValidMove(board, tile, x, y) != False:
|
||||
validMoves.append([x, y])
|
||||
return validMoves
|
||||
|
||||
def getScoreOfBoard(board):
|
||||
# Определить количество очков, подсчитав фишки. Вернуть словарь с ключами CONST_X и CONST_O.
|
||||
xscore = 0
|
||||
oscore = 0
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if board[x][y] == CONST_X:
|
||||
xscore += 1
|
||||
if board[x][y] == CONST_O:
|
||||
oscore += 1
|
||||
return {CONST_X:xscore, CONST_O:oscore}
|
||||
|
||||
def enterPlayerTile():
|
||||
# Позволить игроку ввести выбранную фишку.
|
||||
# Возвращает список с фишкой игрока в качестве первого элемента и фишкой компьютера в качестве второго.
|
||||
tile = ''
|
||||
while not (tile == CONST_X or tile == CONST_O):
|
||||
print('Вы играете за Х или О?')
|
||||
tile = input().upper()
|
||||
|
||||
# Первый элемент в списке — фишка игрока, второй элемент — фишка компьютера.
|
||||
if tile == CONST_X:
|
||||
return [CONST_X, CONST_O]
|
||||
else:
|
||||
return [CONST_O, CONST_X]
|
||||
|
||||
def whoGoesFirst():
|
||||
# Случайно выбрать, кто ходит первым.
|
||||
if random.randint(0, 1) == 0:
|
||||
return 'Компьютер'
|
||||
else:
|
||||
return 'Человек'
|
||||
|
||||
def makeMove(board, tile, xstart, ystart):
|
||||
# Поместить фишку на игровое поле в позицию xstart, ystart и перевернуть какую-либо фишку противника.
|
||||
# Вернуть False, если это недопустимый ход; вернуть True, если допустимый.
|
||||
tilesToFlip = isValidMove(board, tile, xstart, ystart)
|
||||
|
||||
if tilesToFlip == False:
|
||||
return False
|
||||
|
||||
board[xstart][ystart] = tile
|
||||
for x, y in tilesToFlip:
|
||||
board[x][y] = tile
|
||||
return True
|
||||
|
||||
def getBoardCopy(board):
|
||||
# Сделать копию списка board и вернуть ее.
|
||||
boardCopy = getNewBoard()
|
||||
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
boardCopy[x][y] = board[x][y]
|
||||
|
||||
return boardCopy
|
||||
|
||||
def isOnCorner(x, y):
|
||||
# Вернуть True, если указанная позиция находится в одном из четырех углов.
|
||||
return (x == 0 or x == WIDTH - 1) and (y == 0 or y == HEIGHT - 1)
|
||||
|
||||
def getPlayerMove(board, playerTile):
|
||||
# Позволить игроку ввести свой ход.
|
||||
# Вернуть ход в виде [x, y] (или вернуть строки 'подсказка' или 'выход').
|
||||
DIGITS1TO8 = '1 2 3 4 5 6 7 8'.split()
|
||||
while True:
|
||||
print('Укажите ход, текст "выход" для завершения игры или "подсказка" для вывода подсказки.')
|
||||
move = input().lower()
|
||||
if move == 'выход' or move == 'подсказка':
|
||||
return move
|
||||
|
||||
if len(move) == 2 and move[0] in DIGITS1TO8 and move[1] in DIGITS1TO8:
|
||||
x = int(move[0]) - 1
|
||||
y = int(move[1]) - 1
|
||||
if isValidMove(board, playerTile, x, y) == False:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
else:
|
||||
print('Это недопустимый ход. Введите номер столбца (1-8) и номер ряда (1-8).')
|
||||
print('К примеру, значение 81 перемещает в верхний правый угол.')
|
||||
|
||||
return [x, y]
|
||||
|
||||
def getComputerMove(board, computerTile):
|
||||
# Учитывая данное игровое поле и данную фишку компьютера, определить,
|
||||
# куда сделать ход, и вернуть этот ход в виде списка [x, y].
|
||||
possibleMoves = getValidMoves(board, computerTile)
|
||||
random.shuffle(possibleMoves) # Сделать случайным порядок ходов
|
||||
|
||||
# Всегда делать ход в угол, если это возможно.
|
||||
for x, y in possibleMoves:
|
||||
if isOnCorner(x, y):
|
||||
return [x, y]
|
||||
|
||||
# Найти ход с наибольшим возможным количеством очков.
|
||||
bestScore = -1
|
||||
for x, y in possibleMoves:
|
||||
boardCopy = getBoardCopy(board)
|
||||
makeMove(boardCopy, computerTile, x, y)
|
||||
score = getScoreOfBoard(boardCopy)[computerTile]
|
||||
if score > bestScore:
|
||||
bestMove = [x, y]
|
||||
bestScore = score
|
||||
return bestMove
|
||||
|
||||
def printScore(board, playerTile, computerTile):
|
||||
scores = getScoreOfBoard(board)
|
||||
print('Ваш счет: %s. Счет компьютера: %s.' % (scores[playerTile], scores[computerTile]))
|
||||
|
||||
def playGame(playerTile, computerTile):
|
||||
showHints = False
|
||||
turn = whoGoesFirst()
|
||||
print(turn + ' ходит первым.')
|
||||
|
||||
# Очистить игровое поле и выставить стартовые фишки.
|
||||
board = getNewBoard()
|
||||
board[3][3] = CONST_X
|
||||
board[3][4] = CONST_O
|
||||
board[4][3] = CONST_O
|
||||
board[4][4] = CONST_X
|
||||
|
||||
while True:
|
||||
playerValidMoves = getValidMoves(board, playerTile)
|
||||
computerValidMoves = getValidMoves(board, computerTile)
|
||||
|
||||
if playerValidMoves == [] and computerValidMoves == []:
|
||||
return board # Ходов нет ни у кого, так что окончить игру.
|
||||
|
||||
elif turn == 'Человек': # Ход человека
|
||||
if playerValidMoves != []:
|
||||
move = getComputerMove(board, playerTile)
|
||||
makeMove(board, playerTile, move[0], move[1])
|
||||
turn = 'Компьютер'
|
||||
|
||||
elif turn == 'Компьютер': # Ход компьютера
|
||||
if computerValidMoves != []:
|
||||
move = getComputerMove(board, computerTile)
|
||||
makeMove(board, computerTile, move[0], move[1])
|
||||
turn = 'Человек'
|
||||
|
||||
|
||||
|
||||
print('Приветствуем в игре "Р е в е р с и"!')
|
||||
|
||||
playerTile, computerTile = [CONST_X, CONST_O]
|
||||
|
||||
while True:
|
||||
finalBoard = playGame(playerTile, computerTile)
|
||||
|
||||
# Отобразить итоговый счет.
|
||||
drawBoard(finalBoard)
|
||||
scores = getScoreOfBoard(finalBoard)
|
||||
print('X набрал %s очков. O набрал %s очков.' % (scores[CONST_X], scores[CONST_O]))
|
||||
if scores[playerTile] > scores[computerTile]:
|
||||
print('ИИ 1 победил ИИ 2, обогнав его на %s очков!' % (scores[playerTile] - scores[computerTile]))
|
||||
elif scores[playerTile] < scores[computerTile]:
|
||||
print('ИИ 2 победил ИИ 1, обогнав его на %s очков!' % (scores[computerTile] - scores[playerTile]))
|
||||
else:
|
||||
print('Ничья!')
|
||||
|
||||
print('Хотите сыграть еще раз? (да или нет)')
|
||||
if not input().lower().startswith('д'):
|
||||
break
|
||||
278
reversi/computerVScomputer/AISim2.py
Normal file
278
reversi/computerVScomputer/AISim2.py
Normal file
@@ -0,0 +1,278 @@
|
||||
# Reversegam: a clone of Othello/Reversi
|
||||
import random
|
||||
import sys
|
||||
WIDTH = 8 # Board is 8 spaces wide
|
||||
HEIGHT = 8 # Board is 8 spaces tall
|
||||
def drawBoard(board):
|
||||
# This function prints the board that it was passed. Returns None.
|
||||
print(' 12345678')
|
||||
print(' +--------+')
|
||||
for y in range(HEIGHT):
|
||||
print('%s|' % (y+1), end='')
|
||||
for x in range(WIDTH):
|
||||
print(board[x][y], end='')
|
||||
print('|%s' % (y+1))
|
||||
print(' +--------+')
|
||||
print(' 12345678')
|
||||
|
||||
def getNewBoard():
|
||||
# Creates a brand-new, blank board data structure.
|
||||
board = []
|
||||
for i in range(WIDTH):
|
||||
board.append([' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '])
|
||||
return board
|
||||
|
||||
def isValidMove(board, tile, xstart, ystart):
|
||||
# Returns False if the player's move on space xstart, ystart is invalid.
|
||||
# If it is a valid move, returns a list of spaces that would become the player's if they made a move here.
|
||||
if board[xstart][ystart] != ' ' or not isOnBoard(xstart, ystart):
|
||||
return False
|
||||
|
||||
if tile == 'Х':
|
||||
otherTile = 'О'
|
||||
else:
|
||||
otherTile = 'Х'
|
||||
|
||||
tilesToFlip = []
|
||||
for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]:
|
||||
x, y = xstart, ystart
|
||||
x += xdirection # First step in the x direction
|
||||
y += ydirection # First step in the y direction
|
||||
while isOnBoard(x, y) and board[x][y] == otherTile:
|
||||
# Keep moving in this x & y direction.
|
||||
x += xdirection
|
||||
y += ydirection
|
||||
if isOnBoard(x, y) and board[x][y] == tile:
|
||||
# There are pieces to flip over. Go in the reverse direction until we reach the original space, noting all the tiles along the way.
|
||||
while True:
|
||||
x -= xdirection
|
||||
y -= ydirection
|
||||
if x == xstart and y == ystart:
|
||||
break
|
||||
tilesToFlip.append([x, y])
|
||||
|
||||
if len(tilesToFlip) == 0: # If no tiles were flipped, this is not a valid move.
|
||||
return False
|
||||
return tilesToFlip
|
||||
|
||||
def isOnBoard(x, y):
|
||||
# Returns True if the coordinates are located on the board.
|
||||
return x >= 0 and x <= WIDTH - 1 and y >= 0 and y <= HEIGHT - 1
|
||||
|
||||
def getBoardWithValidMoves(board, tile):
|
||||
# Returns a new board with periods marking the valid moves the player can make.
|
||||
boardCopy = getBoardCopy(board)
|
||||
|
||||
for x, y in getValidMoves(boardCopy, tile):
|
||||
boardCopy[x][y] = '.'
|
||||
return boardCopy
|
||||
|
||||
def getValidMoves(board, tile):
|
||||
# Returns a list of [x,y] lists of valid moves for the given player on the given board.
|
||||
validMoves = []
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if isValidMove(board, tile, x, y) != False:
|
||||
validMoves.append([x, y])
|
||||
return validMoves
|
||||
|
||||
def getScoreOfBoard(board):
|
||||
# Determine the score by counting the tiles. Returns a dictionary with keys 'X' and 'O'.
|
||||
xscore = 0
|
||||
oscore = 0
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if board[x][y] == 'Х':
|
||||
xscore += 1
|
||||
if board[x][y] == 'О':
|
||||
oscore += 1
|
||||
return {'Х':xscore, 'О':oscore}
|
||||
|
||||
def enterPlayerTile():
|
||||
# Lets the player type which tile they want to be.
|
||||
# Returns a list with the player's tile as the first item and the computer's tile as the second.
|
||||
tile = ''
|
||||
while not (tile == 'Х' or tile == 'О'):
|
||||
print('Вы играете за Х или О?')
|
||||
tile = input().upper()
|
||||
|
||||
# The first element in the list is the player's tile, and the second is the computer's tile.
|
||||
if tile == 'Х':
|
||||
return ['Х', 'О']
|
||||
else:
|
||||
return ['О', 'Х']
|
||||
|
||||
def whoGoesFirst():
|
||||
# Randomly choose who goes first.
|
||||
if random.randint(0, 1) == 0:
|
||||
return 'computer'
|
||||
else:
|
||||
return 'player'
|
||||
|
||||
def makeMove(board, tile, xstart, ystart):
|
||||
# Place the tile on the board at xstart, ystart, and flip any of the opponent's pieces.
|
||||
# Returns False if this is an invalid move; True if it is valid.
|
||||
tilesToFlip = isValidMove(board, tile, xstart, ystart)
|
||||
|
||||
if tilesToFlip == False:
|
||||
return False
|
||||
|
||||
board[xstart][ystart] = tile
|
||||
for x, y in tilesToFlip:
|
||||
board[x][y] = tile
|
||||
return True
|
||||
|
||||
def getBoardCopy(board):
|
||||
# Make a duplicate of the board list and return it.
|
||||
boardCopy = getNewBoard()
|
||||
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
boardCopy[x][y] = board[x][y]
|
||||
|
||||
return boardCopy
|
||||
|
||||
def isOnCorner(x, y):
|
||||
# Returns True if the position is in one of the four corners.
|
||||
return (x == 0 or x == WIDTH - 1) and (y == 0 or y == HEIGHT - 1)
|
||||
|
||||
def getPlayerMove(board, playerTile):
|
||||
# Let the player enter their move.
|
||||
# Returns the move as [x, y] (or returns the strings 'hints' or 'quit').
|
||||
DIGITS1TO8 = '1 2 3 4 5 6 7 8'.split()
|
||||
while True:
|
||||
print('Укажите ход, текст "выход" для завершения игры или "подсказка" для вывода подсказки.')
|
||||
move = input().lower()
|
||||
if move == 'выход' or move == 'подсказка':
|
||||
return move
|
||||
|
||||
if len(move) == 2 and move[0] in DIGITS1TO8 and move[1] in DIGITS1TO8:
|
||||
x = int(move[0]) - 1
|
||||
y = int(move[1]) - 1
|
||||
if isValidMove(board, playerTile, x, y) == False:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
else:
|
||||
print('Это недопустимый ход. Введите номер столбца (1-8) и номер ряда (1-8).')
|
||||
print('К примеру, значение 81 перемещает в верхний правый угол.')
|
||||
|
||||
return [x, y]
|
||||
|
||||
def getComputerMove(board, computerTile):
|
||||
# Given a board and the computer's tile, determine where to
|
||||
# move and return that move as a [x, y] list.
|
||||
possibleMoves = getValidMoves(board, computerTile)
|
||||
random.shuffle(possibleMoves) # randomize the order of the moves
|
||||
|
||||
# Always go for a corner if available.
|
||||
for x, y in possibleMoves:
|
||||
if isOnCorner(x, y):
|
||||
return [x, y]
|
||||
|
||||
# Find the highest-scoring move possible.
|
||||
bestScore = -1
|
||||
for x, y in possibleMoves:
|
||||
boardCopy = getBoardCopy(board)
|
||||
makeMove(boardCopy, computerTile, x, y)
|
||||
score = getScoreOfBoard(boardCopy)[computerTile]
|
||||
if score > bestScore:
|
||||
bestMove = [x, y]
|
||||
bestScore = score
|
||||
return bestMove
|
||||
|
||||
def printScore(board, playerTile, computerTile):
|
||||
scores = getScoreOfBoard(board)
|
||||
print('Ваш счет: %s. Счет компьютера: %s.' % (scores[playerTile], scores[computerTile]))
|
||||
|
||||
def playGame(playerTile, computerTile):
|
||||
showHints = False
|
||||
turn = whoGoesFirst()
|
||||
#print('The ' + turn + ' will go first.')
|
||||
|
||||
# Clear the board and place starting pieces.
|
||||
board = getNewBoard()
|
||||
board[3][3] = 'Х'
|
||||
board[3][4] = 'О'
|
||||
board[4][3] = 'О'
|
||||
board[4][4] = 'Х'
|
||||
|
||||
while True:
|
||||
playerValidMoves = getValidMoves(board, playerTile)
|
||||
computerValidMoves = getValidMoves(board, computerTile)
|
||||
|
||||
if playerValidMoves == [] and computerValidMoves == []:
|
||||
return board # No one can move, so end the game.
|
||||
|
||||
elif turn == 'player': # Player's turn
|
||||
if playerValidMoves != []:
|
||||
#if showHints:
|
||||
# validMovesBoard = getBoardWithValidMoves(board, playerTile)
|
||||
# drawBoard(validMovesBoard)
|
||||
#else:
|
||||
#drawBoard(board)
|
||||
#printScore(board, playerTile, computerTile)
|
||||
|
||||
move = getComputerMove(board, playerTile)
|
||||
#if move == 'quit':
|
||||
# print('Thanks for playing!')
|
||||
# sys.exit() # Terminate the program.
|
||||
#elif move == 'hints':
|
||||
# showHints = not showHints
|
||||
# continue
|
||||
#else:
|
||||
makeMove(board, playerTile, move[0], move[1])
|
||||
turn = 'computer'
|
||||
|
||||
elif turn == 'computer': # Computer's turn
|
||||
if computerValidMoves != []:
|
||||
#drawBoard(board)
|
||||
#printScore(board, playerTile, computerTile)
|
||||
|
||||
#input('Press Enter to see the computer\'s move.')
|
||||
move = getComputerMove(board, computerTile)
|
||||
makeMove(board, computerTile, move[0], move[1])
|
||||
turn = 'player'
|
||||
|
||||
NUM_GAMES = 250
|
||||
xWins = oWins = ties = 0
|
||||
print('Приветствуем в игре "Реверси"!')
|
||||
ans = input("Вам показывать процесс или нет? д/н ")
|
||||
if ans == "д":
|
||||
pokaz = True
|
||||
else:
|
||||
pokaz = False
|
||||
|
||||
playerTile, computerTile = ['Х', 'О'] #enterPlayerTile()
|
||||
|
||||
for i in range(NUM_GAMES): #while True:
|
||||
finalBoard = playGame(playerTile, computerTile)
|
||||
|
||||
# Display the final score.
|
||||
#drawBoard(finalBoard)
|
||||
scores = getScoreOfBoard(finalBoard)
|
||||
if pokaz == True:
|
||||
print('X набрал %s очков. O набрал %s очков.' % (scores['Х'], scores['О']))
|
||||
if scores[playerTile] > scores[computerTile]:
|
||||
xWins += 1 #print('You beat the computer by %s points! Congratulations!' % (scores[playerTile] - scores[computerTile]))
|
||||
elif scores[playerTile] < scores[computerTile]:
|
||||
oWins += 1 #print('You lost. The computer beat you by %s points.' % (scores[computerTile] - scores[playerTile]))
|
||||
else:
|
||||
ties += 1 #print('The game was a tie!')
|
||||
|
||||
else:
|
||||
if scores[playerTile] > scores[computerTile]:
|
||||
xWins += 1 # print('You beat the computer by %s points! Congratulations!' % (scores[playerTile] - scores[computerTile]))
|
||||
elif scores[playerTile] < scores[computerTile]:
|
||||
oWins += 1 # print('You lost. The computer beat you by %s points.' % (scores[computerTile] - scores[playerTile]))
|
||||
else:
|
||||
ties += 1 # print('The game was a tie!')
|
||||
|
||||
|
||||
#print('Do you want to play again? (yes or no)')
|
||||
#if not input().lower().startswith('y'):
|
||||
# break
|
||||
|
||||
print('X победил: %s (%s%%)' % (xWins, round(xWins / NUM_GAMES * 100, 1)))
|
||||
print('O победил: %s (%s%%)' % (oWins, round(oWins / NUM_GAMES * 100, 1)))
|
||||
print('Ничьи: %s (%s%%)' % (ties, round(ties / NUM_GAMES * 100, 1)))
|
||||
259
reversi/playerVScomputer/reversi.py
Normal file
259
reversi/playerVScomputer/reversi.py
Normal file
@@ -0,0 +1,259 @@
|
||||
# "Реверси": клон "Отелло".
|
||||
import random
|
||||
import sys
|
||||
WIDTH = 8 # Игровое поле содержит 8 клеток по ширине.
|
||||
HEIGHT = 8 # Игровое поле содержит 8 клеток по высоте.
|
||||
def drawBoard(board):
|
||||
# Вывести игровое поле, переданное этой функции. Ничего не возвращать.
|
||||
print(' 12345678')
|
||||
print(' +--------+')
|
||||
for y in range(HEIGHT):
|
||||
print('%s|' % (y+1), end='')
|
||||
for x in range(WIDTH):
|
||||
print(board[x][y], end='')
|
||||
print('|%s' % (y+1))
|
||||
print(' +--------+')
|
||||
print(' 12345678')
|
||||
|
||||
def getNewBoard():
|
||||
# Создать структуру данных нового чистого игрового поля.
|
||||
board = []
|
||||
for i in range(WIDTH):
|
||||
board.append([' ', ' ', ' ', ' ', ' ', ' ', ' ', ' '])
|
||||
return board
|
||||
|
||||
def isValidMove(board, tile, xstart, ystart):
|
||||
# Вернуть False, если ход игрока в клетку с координатами xstart, ystart — недопустимый.
|
||||
# Если это допустимый ход, вернуть список клеток, которые "присвоил" бы игрок, если бы сделал туда ход.
|
||||
if board[xstart][ystart] != ' ' or not isOnBoard(xstart, ystart):
|
||||
return False
|
||||
|
||||
if tile == 'Х':
|
||||
otherTile = 'О'
|
||||
else:
|
||||
otherTile = 'Х'
|
||||
|
||||
tilesToFlip = []
|
||||
for xdirection, ydirection in [[0, 1], [1, 1], [1, 0], [1, -1], [0, -1], [-1, -1], [-1, 0], [-1, 1]]:
|
||||
x, y = xstart, ystart
|
||||
x += xdirection # Первый шаг в направлении x
|
||||
y += ydirection # Первый шаг в направлении y
|
||||
while isOnBoard(x, y) and board[x][y] == otherTile:
|
||||
# Продолжать двигаться в этом направлении x и y.
|
||||
x += xdirection
|
||||
y += ydirection
|
||||
if isOnBoard(x, y) and board[x][y] == tile:
|
||||
#Естьфишки,которыеможноперевернуть.Двигатьсявобратномнаправлениидодостиженияисходнойклетки,отмечаявсефишкинаэтомпути.
|
||||
while True:
|
||||
x -= xdirection
|
||||
y -= ydirection
|
||||
if x == xstart and y == ystart:
|
||||
break
|
||||
tilesToFlip.append([x, y])
|
||||
|
||||
if len(tilesToFlip) == 0: # Если ни одна из фишек не перевернулась, это недопустимый ход
|
||||
return False
|
||||
return tilesToFlip
|
||||
|
||||
def isOnBoard(x, y):
|
||||
# Вернуть True, если координаты есть на игровом поле.
|
||||
return x >= 0 and x <= WIDTH - 1 and y >= 0 and y <= HEIGHT - 1
|
||||
|
||||
def getBoardWithValidMoves(board, tile):
|
||||
# Вернуть новое поле с точками, обозначающими допустимые ходы, которые может сделать игрок.
|
||||
boardCopy = getBoardCopy(board)
|
||||
|
||||
for x, y in getValidMoves(boardCopy, tile):
|
||||
boardCopy[x][y] = '.'
|
||||
return boardCopy
|
||||
|
||||
def getValidMoves(board, tile):
|
||||
# Вернуть список списков с координатами x и y допустимых ходов для данного игрока на данном игровом поле.
|
||||
validMoves = []
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if isValidMove(board, tile, x, y) != False:
|
||||
validMoves.append([x, y])
|
||||
return validMoves
|
||||
|
||||
def getScoreOfBoard(board):
|
||||
# Определить количество очков, подсчитав фишки. Вернуть словарь с ключами 'Х' и 'О'.
|
||||
xscore = 0
|
||||
oscore = 0
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
if board[x][y] == 'Х':
|
||||
xscore += 1
|
||||
if board[x][y] == 'О':
|
||||
oscore += 1
|
||||
return {'Х':xscore, 'О':oscore}
|
||||
|
||||
def enterPlayerTile():
|
||||
# Позволить игроку ввести выбранную фишку.
|
||||
# Возвращает список с фишкой игрока в качестве первого элемента и фишкой компьютера в качестве второго.
|
||||
tile = ''
|
||||
while not (tile == 'Х' or tile == 'О'):
|
||||
print('Вы играете за Х или О?')
|
||||
tile = input().upper()
|
||||
|
||||
# Первый элемент в списке — фишка игрока, второй элемент — фишка компьютера.
|
||||
if tile == 'Х':
|
||||
return ['Х', 'О']
|
||||
else:
|
||||
return ['О', 'Х']
|
||||
|
||||
def whoGoesFirst():
|
||||
# Случайно выбрать, кто ходит первым.
|
||||
if random.randint(0, 1) == 0:
|
||||
return 'Компьютер'
|
||||
else:
|
||||
return 'Человек'
|
||||
|
||||
def makeMove(board, tile, xstart, ystart):
|
||||
# Поместить фишку на игровое поле в позицию xstart, ystart и перевернуть какую-либо фишку противника.
|
||||
# Вернуть False, если это недопустимый ход; вернуть True, если допустимый.
|
||||
tilesToFlip = isValidMove(board, tile, xstart, ystart)
|
||||
|
||||
if tilesToFlip == False:
|
||||
return False
|
||||
|
||||
board[xstart][ystart] = tile
|
||||
for x, y in tilesToFlip:
|
||||
board[x][y] = tile
|
||||
return True
|
||||
|
||||
def getBoardCopy(board):
|
||||
# Сделать копию списка board и вернуть ее.
|
||||
boardCopy = getNewBoard()
|
||||
|
||||
for x in range(WIDTH):
|
||||
for y in range(HEIGHT):
|
||||
boardCopy[x][y] = board[x][y]
|
||||
|
||||
return boardCopy
|
||||
|
||||
def isOnCorner(x, y):
|
||||
# Вернуть True, если указанная позиция находится в одном из четырех углов.
|
||||
return (x == 0 or x == WIDTH - 1) and (y == 0 or y == HEIGHT - 1)
|
||||
|
||||
def getPlayerMove(board, playerTile):
|
||||
# Позволить игроку ввести свой ход.
|
||||
# Вернуть ход в виде [x, y] (или вернуть строки 'подсказка' или 'выход').
|
||||
DIGITS1TO8 = '1 2 3 4 5 6 7 8'.split()
|
||||
while True:
|
||||
print('Укажите ход, текст "выход" для завершения игры или "подсказка" для вывода подсказки.')
|
||||
move = input().lower()
|
||||
if move == 'выход' or move == 'подсказка':
|
||||
return move
|
||||
|
||||
if len(move) == 2 and move[0] in DIGITS1TO8 and move[1] in DIGITS1TO8:
|
||||
x = int(move[0]) - 1
|
||||
y = int(move[1]) - 1
|
||||
if isValidMove(board, playerTile, x, y) == False:
|
||||
continue
|
||||
else:
|
||||
break
|
||||
else:
|
||||
print('Это недопустимый ход. Введите номер столбца (1-8) и номер ряда (1-8).')
|
||||
print('К примеру, значение 81 перемещает в верхний правый угол.')
|
||||
|
||||
return [x, y]
|
||||
|
||||
def getComputerMove(board, computerTile):
|
||||
# Учитывая данное игровое поле и данную фишку компьютера, определить,
|
||||
# куда сделать ход, и вернуть этот ход в виде списка [x, y].
|
||||
possibleMoves = getValidMoves(board, computerTile)
|
||||
random.shuffle(possibleMoves) # Сделать случайным порядок ходов
|
||||
|
||||
# Всегда делать ход в угол, если это возможно.
|
||||
for x, y in possibleMoves:
|
||||
if isOnCorner(x, y):
|
||||
return [x, y]
|
||||
|
||||
# Найти ход с наибольшим возможным количеством очков.
|
||||
bestScore = -1
|
||||
for x, y in possibleMoves:
|
||||
boardCopy = getBoardCopy(board)
|
||||
makeMove(boardCopy, computerTile, x, y)
|
||||
score = getScoreOfBoard(boardCopy)[computerTile]
|
||||
if score > bestScore:
|
||||
bestMove = [x, y]
|
||||
bestScore = score
|
||||
return bestMove
|
||||
|
||||
def printScore(board, playerTile, computerTile):
|
||||
scores = getScoreOfBoard(board)
|
||||
print('Ваш счет: %s. Счет компьютера: %s.' % (scores[playerTile], scores[computerTile]))
|
||||
|
||||
def playGame(playerTile, computerTile):
|
||||
showHints = False
|
||||
turn = whoGoesFirst()
|
||||
print(turn + ' ходит первым.')
|
||||
|
||||
# Очистить игровое поле и выставить стартовые фишки.
|
||||
board = getNewBoard()
|
||||
board[3][3] = 'Х'
|
||||
board[3][4] = 'О'
|
||||
board[4][3] = 'О'
|
||||
board[4][4] = 'Х'
|
||||
|
||||
while True:
|
||||
playerValidMoves = getValidMoves(board, playerTile)
|
||||
computerValidMoves = getValidMoves(board, computerTile)
|
||||
|
||||
if playerValidMoves == [] and computerValidMoves == []:
|
||||
return board # Ходов нет ни у кого, так что окончить игру.
|
||||
|
||||
elif turn == 'Человек': # Ход человека
|
||||
if playerValidMoves != []:
|
||||
if showHints:
|
||||
validMovesBoard = getBoardWithValidMoves(board, playerTile)
|
||||
drawBoard(validMovesBoard)
|
||||
else:
|
||||
drawBoard(board)
|
||||
printScore(board, playerTile, computerTile)
|
||||
|
||||
move = getPlayerMove(board, playerTile)
|
||||
if move == 'выход':
|
||||
print('Благодарим за игру!')
|
||||
sys.exit() # Завершить работу программы.
|
||||
elif move == 'подсказка':
|
||||
showHints = not showHints
|
||||
continue
|
||||
else:
|
||||
makeMove(board, playerTile, move[0], move[1])
|
||||
turn = 'Компьютер'
|
||||
|
||||
elif turn == 'Компьютер': # Ход компьютера
|
||||
if computerValidMoves != []:
|
||||
drawBoard(board)
|
||||
printScore(board, playerTile, computerTile)
|
||||
|
||||
input('Нажмите клавишу Enter для просмотра хода компьютера.')
|
||||
move = getComputerMove(board, computerTile)
|
||||
makeMove(board, computerTile, move[0], move[1])
|
||||
turn = 'Человек'
|
||||
|
||||
|
||||
|
||||
print('Приветствуем в игре "Реверси"!')
|
||||
|
||||
playerTile, computerTile = enterPlayerTile()
|
||||
|
||||
while True:
|
||||
finalBoard = playGame(playerTile, computerTile)
|
||||
|
||||
# Отобразить итоговый счет.
|
||||
drawBoard(finalBoard)
|
||||
scores = getScoreOfBoard(finalBoard)
|
||||
print('X набрал %s очков. O набрал %s очков.' % (scores['Х'], scores['О']))
|
||||
if scores[playerTile] > scores[computerTile]:
|
||||
print('Вы победили компьютер, обогнав его на %s очков! Поздравления!' % (scores[playerTile] - scores[computerTile]))
|
||||
elif scores[playerTile] < scores[computerTile]:
|
||||
print('Вы проиграли. Компьютер победил вас, обогнав на %s очков.' % (scores[computerTile] - scores[playerTile]))
|
||||
else:
|
||||
print('Ничья!')
|
||||
|
||||
print('Хотите сыграть еще раз? (да или нет)')
|
||||
if not input().lower().startswith('д'):
|
||||
break
|
||||
Reference in New Issue
Block a user