Pages

Sunday, October 24, 2010

JavaScript and Canvas, woo hoo!

HTML5 standard introduces the Canvas element. We can now draw on a web page with plain JavaScript code. Isn't this exciting?

I have a few old games which I wrote in Turbo Pascal (and Delphi) and I intend to convert them into JavaScript code and post them in my blog, so anyone can play them. Woo hoo!

If your browser does support the canvas tag/element you'll be able to view a white square with a black border below. If so, try rolling the mouse over the square. If no, consider upgrading your browser ;-)


no canvas support



That's my Black Triangle.

Saturday, September 18, 2010

Tic-tac-toe, best move to start?

Tic-tac-toe game has one simple rule: the player who succeeds in placing three respective marks in a horizontal, vertical, or diagonal row, in a 3x3 grid, wins the game.

So what's the best move to start? Well, I don't know.
But I can use a computer to get an answer.
(I lied. I do know)

The tools I've used:

The computer played 10000 "random" games and saved them in a database.

Actually the games are not plain random games. I've embedded the tic-tac-toe rule in the program. The program chooses a random move only if the player can't win or can't block the opponent. The players are considered to be intermediate level tic-tac-toe players.

Even though we've played random games, the best moves dominate over the good and bad ones, and just by counting the results we get our answer:

0 | 1 | 2
--+---+--
3 | 4 | 5
--+---+--
6 | 7 | 8



As we can observe, corners lead to more victories. Yeah baby!

And what's the more defensive opening for tic-tac-toe?
(by defensing I mean a move that leads to more ties)



Hmm, it's the center (cell 4). Interesting.

Here's something way cooler: since we have a knowledge base for tic-tac-toe games, we can query the database for a specific game state and find out the next best move for any player!

An example: let's say that X (player 1) chose the upper-left corner (cell 0).

X | 1 | 2
--+---+--
3 | 4 | 5
--+---+--
6 | 7 | 8


Now what O (player 2) should choose? A move that gives the fewer wins for player X has good odds to be the next best move, right? OK, lets run a query and see...



Hey, statistically, the center (cell 4) causes fewer wins for player 1,  thus it's the next best move for player 2. Neat!


Play on-line Tic-Tac-Toe

You prefer to play with code? Here's what I've crafted:
import random
import sqlite3

def CanTicTacToe(player, cells):
    return cells.count(player) == 2 and cells.count(0) == 1

def SelectWinningMove(player, board):
    # Horizontal
    if CanTicTacToe(player, board[0:3]): return board[0:3].index(0) + 0
    if CanTicTacToe(player, board[3:6]): return board[3:6].index(0) + 3
    if CanTicTacToe(player, board[6:9]): return board[6:9].index(0) + 6
    # Vertical
    if CanTicTacToe(player, board[0::3]): return board[0::3].index(0) * 3 + 0
    if CanTicTacToe(player, board[1::3]): return board[1::3].index(0) * 3 + 1
    if CanTicTacToe(player, board[2::3]): return board[2::3].index(0) * 3 + 2
    # Diagonal
    if CanTicTacToe(player, board[0::4]): return board[0::4].index(0) * 4
    if CanTicTacToe(player, board[2::2][:3]):
         return board[2::2][:3].index(0) * 2 + 2
    return -1

def SelectRandomMove(player, board):
    moves = [i for i in range(0, len(board)) if board[i] == 0]
    if len(moves) == 0: return -1
    return moves[random.randint(0, len(moves) - 1)]

# ([0,1,2,3,4,5,6,7,8], result)
def PlayRandomGame():
    result = 0 # tie
    board = [0] * 9
    moves = []
    player = 0
    while True:
        player = player % 2 + 1 # X: 1, O: 2:
        move = SelectWinningMove(player, board)
        if move >= 0: # victory
            moves.append(move)
            result = player
            break
        # Opponent can win?
        opponent = player % 2 + 1
        move = SelectWinningMove(opponent, board)
        if move < 0: # nope, so ...
            move = SelectRandomMove(player, board)
        if move >= 0:
                moves.append(move)
                board[move] = player
        else: # no more moves; tie
            break
    return (moves, result)

def SaveRandomGames(fileName, n=10000):
    conn = sqlite3.connect(fileName)
    c = conn.cursor()
    c.execute('DROP TABLE IF EXISTS games')
    c.execute('CREATE TABLE IF NOT EXISTS games ('
        'move1 INTEGER, move2 INTEGER, move3 INTEGER,'
        'move4 INTEGER, move5 INTEGER, move6 INTEGER,'
        'move7 INTEGER, move8 INTEGER, move9 INTEGER,'
        'winner INTEGER)')
    for _ in xrange(n):
        game = PlayRandomGame()
        moves = game[0] + [None] * (9 - len(game[0]))
        result =  game[1]
        c.execute('INSERT INTO games VALUES (?,?,?,?,?,?,?,?,?,?)',
            moves + [result])
    conn.commit()
    c.close()

Tuesday, August 17, 2010

4 ways to close an application

I knew these ways
  1. Clicking on the upper-right button aka the X button
  2. Alt + F4
  3. Selecting  the Close command from the system menu (the upper-left icon on a window)
And I just found out a fourth way, after so many years of using Windows.
By double clicking the upper-left icon you execute the default command, which is the Close command.

Hooray!