Thứ Bảy, 21 tháng 4, 2018

SOURCE CODE TIC TAC TOE: Ý TƯỞNG CƠ BẢN CHO GAME ĐÁNH CỜ DẠNG TURN BASED

SOURCE CODE TIC TAC TOE: Ý TƯỞNG CƠ BẢN CHO GAME ĐÁNH CỜ DẠNG TURN BASED

Source code của AISweigart tác giả cuốn Invent your own computer game with python, cuốn sách vở lòng của mình.
# Tic Tac Toe

import random

def drawBoard(board):
    # This function prints out the board that it was passed.

    # "board" is a list of 10 strings representing the board (ignore index 0)
    print('   |   |')
    print(' ' + board[7] + ' | ' + board[8] + ' | ' + board[9])
    print('   |   |')
    print('-----------')
    print('   |   |')
    print(' ' + board[4] + ' | ' + board[5] + ' | ' + board[6])
    print('   |   |')
    print('-----------')
    print('   |   |')
    print(' ' + board[1] + ' | ' + board[2] + ' | ' + board[3])
    print('   |   |')

def inputPlayerLetter():
    # Let's the player type which letter they want to be.
    # Returns a list with the player's letter as the first item, and the computer's letter as the second.
    letter = ''
    while not (letter == 'X' or letter == 'O'):
        print('Do you want to be X or O?')
        letter = input().upper()

    # the first element in the tuple is the player's letter, the second is the computer's letter.
    if letter == 'X':
        return ['X', 'O']
    else:
        return ['O', 'X']

def whoGoesFirst():
    # Randomly choose the player who goes first.
    if random.randint(0, 1) == 0:
        return 'computer'
    else:
        return 'player'

def playAgain():
    # This function returns True if the player wants to play again, otherwise it returns False.
    print('Do you want to play again? (yes or no)')
    return input().lower().startswith('y')

def makeMove(board, letter, move):
    board[move] = letter

def isWinner(bo, le):
    # Given a board and a player's letter, this function returns True if that player has won.
    # We use bo instead of board and le instead of letter so we don't have to type as much.
    return ((bo[7] == le and bo[8] == le and bo[9] == le) or # across the top
    (bo[4] == le and bo[5] == le and bo[6] == le) or # across the middle
    (bo[1] == le and bo[2] == le and bo[3] == le) or # across the bottom
    (bo[7] == le and bo[4] == le and bo[1] == le) or # down the left side
    (bo[8] == le and bo[5] == le and bo[2] == le) or # down the middle
    (bo[9] == le and bo[6] == le and bo[3] == le) or # down the right side
    (bo[7] == le and bo[5] == le and bo[3] == le) or # diagonal
    (bo[9] == le and bo[5] == le and bo[1] == le)) # diagonal

def getBoardCopy(board):
    # Make a duplicate of the board list and return it the duplicate.
    dupeBoard = []

    for i in board:
        dupeBoard.append(i)

    return dupeBoard

def isSpaceFree(board, move):
    # Return true if the passed move is free on the passed board.
    return board[move] == ' '

def getPlayerMove(board):
    # Let the player type in his move.
    move = ' '
    while move not in '1 2 3 4 5 6 7 8 9'.split() or not isSpaceFree(board, int(move)):
        print('What is your next move? (1-9)')
        move = input()
    return int(move)

def chooseRandomMoveFromList(board, movesList):
    # Returns a valid move from the passed list on the passed board.
    # Returns None if there is no valid move.
    possibleMoves = []
    for i in movesList:
        if isSpaceFree(board, i):
            possibleMoves.append(i)

    if len(possibleMoves) != 0:
        return random.choice(possibleMoves)
    else:
        return None

def getComputerMove(board, computerLetter):
    # Given a board and the computer's letter, determine where to move and return that move.
    if computerLetter == 'X':
        playerLetter = 'O'
    else:
        playerLetter = 'X'

    # Here is our algorithm for our Tic Tac Toe AI:
    # First, check if we can win in the next move
    for i in range(1, 10):
        copy = getBoardCopy(board)
        if isSpaceFree(copy, i):
            makeMove(copy, computerLetter, i)
            if isWinner(copy, computerLetter):
                return i

    # Check if the player could win on his next move, and block them.
    for i in range(1, 10):
        copy = getBoardCopy(board)
        if isSpaceFree(copy, i):
            makeMove(copy, playerLetter, i)
            if isWinner(copy, playerLetter):
                return i

    # Try to take one of the corners, if they are free.
    move = chooseRandomMoveFromList(board, [1, 3, 7, 9])
    if move != None:
        return move

    # Try to take the center, if it is free.
    if isSpaceFree(board, 5):
        return 5

    # Move on one of the sides.
    return chooseRandomMoveFromList(board, [2, 4, 6, 8])

def isBoardFull(board):
    # Return True if every space on the board has been taken. Otherwise return False.
    for i in range(1, 10):
        if isSpaceFree(board, i):
            return False
    return True


print('Welcome to Tic Tac Toe!')

while True:
    # Reset the board
    theBoard = [' '] * 10
    playerLetter, computerLetter = inputPlayerLetter()
    turn = whoGoesFirst()
    print('The ' + turn + ' will go first.')
    gameIsPlaying = True

    while gameIsPlaying:
        if turn == 'player':
            # Player's turn.
            drawBoard(theBoard)
            move = getPlayerMove(theBoard)
            makeMove(theBoard, playerLetter, move)

            if isWinner(theBoard, playerLetter):
                drawBoard(theBoard)
                print('Hooray! You have won the game!')
                gameIsPlaying = False
            else:
                if isBoardFull(theBoard):
                    drawBoard(theBoard)
                    print('The game is a tie!')
                    break
                else:
                    turn = 'computer'

        else:
            # Computer's turn.
            move = getComputerMove(theBoard, computerLetter)
            makeMove(theBoard, computerLetter, move)

            if isWinner(theBoard, computerLetter):
                drawBoard(theBoard)
                print('The computer has beaten you! You lose.')
                gameIsPlaying = False
            else:
                if isBoardFull(theBoard):
                    drawBoard(theBoard)
                    print('The game is a tie!')
                    break
                else:
                    turn = 'player'

    if not playAgain():
        break

Ý tưởng cơ bản ở đây là tạo một Clone Board, sau đó chạy thử tất cả các trường hợp có thể set trên Clone Board đó. Kiểm tra:
- Nếu một nước cờ có thể làm máy tính thắng à xuất ra nước cờ đó
- Nếu một nước cờ có thể làm người chơi thắng à ngăn chặn nước cờ đó
- Cuối cùng: nếu không thỏa 2 điều kiện trên, cố gắng tìm một nước cờ tối ưu. (Ví dụ dùng một hàm đếm kiểu Greedy để quét toàn bộ bàn cờ chẳng hạn)

Ý tưởng này có thể áp dụng cho nhiều game đánh cờ khác như Flippy, Cờ Vua, …

Thứ Sáu, 20 tháng 4, 2018

BƯỚC ĐẦU LẬP TRÌNH: PYTHON VÀ PYGAME – CON ĐƯỜNG ĐƠN GIẢN KHÔNG MỆT NÃO

BƯỚC ĐẦU LẬP TRÌNH: PYTHON VÀ PYGAME – CON ĐƯỜNG ĐƠN GIẢN KHÔNG MỆT NÃO

1. Tại sao là PYTHON?
Chắc không cần mình nói mấy bạn cũng biết python là gì. Nó là một ngôn ngữ bậc cao, siêu đơn giản, hỗ trợ rộng, đa nền tảng, … nói chung là thích hợp mọi thứ để học lúc mới làm quen với lập trình.
Ở nước ngoài, người ta luôn học từ cao xuống thấp, tức là học những ngôn ngữ lập trình cao trước, như python chẳng hạn (bây giờ thì có hàng tá ngôn ngữ cao hơn), rồi xuống thấp hơn như JAVA, C#, rồi đến ngôn ngữ cấp thấp như C, hay siêu thấp như ngôn ngữ ASM.

- Tiếp xúc với một ngôn ngữ bậc cao hỗ trợ mạnh, bạn không cần quan tâm nhiều quá về cú pháp, khai báo biến, cách return hay cấp pháp bộ nhớ ra sao, vân vân và mây mây. Mấy thứ tào lao đó để cho máy tính nó lo. Mình lo những thứ cao siêu hơn, như giải thuật, tư duy, cách optimize chương trình cho nó ít tốn bộ nhớ ra sao, cách làm việc với class, function ra sao, này kia nọ.
Làm việc với Python, bạn sẽ được làm quen với OOP (lập trình hướng đối tượng) rất sớm, rất tự nhiên. Từ ban đầu viết theo thủ tục nó ra sao, rồi chuyển qua OOP nó ngắn gọn dễ dàng bấy nhiêu, vân vân. Bạn cũng có thể viết game, cực đơn giản với pygame.
Bạn nghĩ sẽ mất bao lâu để viết được một game Tetris, hay flappy bird nếu sử dụng C hay C++? 2 tuần? 2 tháng? Forever?
Python mang tới cho chúng ta một thế giới lập trình thật tươi đẹp và dễ chịu. Mọi thứ đều đơn giản và cuốn hút kinh khủng.
Nói túm lại, mới bắt đầu học lập trình, học Python ngay và luôn.
2. Bắt đầu học:
Lên mạng vào trang python tải về bản 3.6 (không biết hiện tại mới nhất bản mấy). Khoảng vài chục MB thui, next next next OK, rồi xong mở lên xài thui.
Về tài liệu học, lên mạng google, không nói nhiều XD. Tất cả cú pháp, biến, các định nghĩa list, tuple, dictionary, tùm lum tà la, có hết trên google.
Về 2 quyển sách đầu tiên mình học: vở lòng 2 quyển này: Invent your own computer game with python và quyển 2 của nó: Making games with python and pygame.
Tập sau sẽ típ về 2 cuốn này