Tic-tac-toe: Difference between revisions
(New task and Python solution.) |
(→Tcl: Added implementation) |
||
Line 118: | Line 118: | ||
O wins across [1, 4, 7]</pre> |
O wins across [1, 4, 7]</pre> |
||
=={{header|Tcl}}== |
|||
{{trans|Python}} |
|||
<lang tcl>package require Tcl 8.6 |
|||
# This code splits the players from the core game engine |
|||
oo::class create TicTacToe { |
|||
variable board player letter who |
|||
constructor {player1class player2class} { |
|||
set board {1 2 3 4 5 6 7 8 9} |
|||
set player(0) [$player1class new [self] [set letter(0) "X"]] |
|||
set player(1) [$player2class new [self] [set letter(1) "O"]] |
|||
set who 0 |
|||
} |
|||
method PrintBoard {} { |
|||
lassign $board a1 b1 c1 a2 b2 c2 a3 b3 c3 |
|||
puts [format " %s | %s | %s" $a1 $b1 $c1] |
|||
puts "---+---+---" |
|||
puts [format " %s | %s | %s" $a2 $b2 $c2] |
|||
puts "---+---+---" |
|||
puts [format " %s | %s | %s" $a3 $b3 $c3] |
|||
} |
|||
method WinForSomeone {} { |
|||
foreach w { |
|||
{0 1 2} {3 4 5} {6 7 8} {0 3 6} {1 4 7} {2 5 8} {0 4 8} {2 4 6} |
|||
} { |
|||
set b [lindex $board [lindex $w 0]] |
|||
if {$b ni "X O"} continue |
|||
foreach i $w {if {[lindex $board $i] ne $b} break} |
|||
if {[lindex $board $i] eq $b} { |
|||
foreach p $w {lappend w1 [expr {$p+1}]} |
|||
return [list $b $w1] |
|||
} |
|||
} |
|||
return "" |
|||
} |
|||
method status {} { |
|||
return $board |
|||
} |
|||
method IsDraw {} { |
|||
foreach b $board {if {[string is digit $b]} {return false}} |
|||
return true |
|||
} |
|||
method legalMoves {} { |
|||
foreach b $board {if {[string is digit $b]} {lappend legal $b}} |
|||
return $legal |
|||
} |
|||
method DoATurn {} { |
|||
set legal [my legalMoves] |
|||
my PrintBoard |
|||
while 1 { |
|||
set move [$player($who) turn] |
|||
if {$move in $legal} break |
|||
puts "Illegal move!" |
|||
} |
|||
lset board [expr {$move - 1}] $letter($who) |
|||
$player($who) describeMove $move |
|||
set who [expr {1 - $who}] |
|||
return [my WinForSomeone] |
|||
} |
|||
method game {} { |
|||
puts " Tic-tac-toe game player. |
|||
Input the index of where you wish to place your mark at your turn.\n" |
|||
while {![my IsDraw]} { |
|||
set winner [my DoATurn] |
|||
if {$winner eq ""} continue |
|||
lassign $winner winLetter winSites |
|||
my PrintBoard |
|||
puts "\n$winLetter wins across \[[join $winSites {, }]\]" |
|||
return $winLetter |
|||
} |
|||
puts "\nA draw" |
|||
} |
|||
} |
|||
# Stupid robotic player |
|||
oo::class create RandomRoboPlayer { |
|||
variable g |
|||
constructor {game letter} { |
|||
set g $game |
|||
} |
|||
method turn {} { |
|||
set legal [$g legalMoves] |
|||
return [lindex $legal [expr {int(rand()*[llength $legal])}]] |
|||
} |
|||
method describeMove {move} { |
|||
puts "I go at $move" |
|||
} |
|||
} |
|||
# Interactive human player delegate |
|||
oo::class create HumanPlayer { |
|||
variable g char |
|||
constructor {game letter} { |
|||
set g $game |
|||
set char $letter |
|||
} |
|||
method turn {} { |
|||
set legal [$g legalMoves] |
|||
puts ">>> Put your $char in any of these positions: [join $legal {}]" |
|||
while 1 { |
|||
puts -nonewline ">>> " |
|||
flush stdout |
|||
gets stdin number |
|||
if {$number in $legal} break |
|||
puts ">>> Whoops I don't understand the input!" |
|||
} |
|||
return $number |
|||
} |
|||
method describeMove {move} { |
|||
puts "You went at $move" |
|||
} |
|||
} |
|||
# Assemble the pieces |
|||
set ttt [TicTacToe new HumanPlayer RandomRoboPlayer] |
|||
$ttt game</lang> |
|||
Sample game: |
|||
<pre> |
|||
Tic-tac-toe game player. |
|||
Input the index of where you wish to place your mark at your turn. |
|||
1 | 2 | 3 |
|||
---+---+--- |
|||
4 | 5 | 6 |
|||
---+---+--- |
|||
7 | 8 | 9 |
|||
>>> Put your X in any of these positions: 123456789 |
|||
>>> 1 |
|||
You went at 1 |
|||
X | 2 | 3 |
|||
---+---+--- |
|||
4 | 5 | 6 |
|||
---+---+--- |
|||
7 | 8 | 9 |
|||
I go at 5 |
|||
X | 2 | 3 |
|||
---+---+--- |
|||
4 | O | 6 |
|||
---+---+--- |
|||
7 | 8 | 9 |
|||
>>> Put your X in any of these positions: 2346789 |
|||
>>> 7 |
|||
You went at 7 |
|||
X | 2 | 3 |
|||
---+---+--- |
|||
4 | O | 6 |
|||
---+---+--- |
|||
X | 8 | 9 |
|||
I go at 9 |
|||
X | 2 | 3 |
|||
---+---+--- |
|||
4 | O | 6 |
|||
---+---+--- |
|||
X | 8 | O |
|||
>>> Put your X in any of these positions: 23468 |
|||
>>> 4 |
|||
You went at 4 |
|||
X | 2 | 3 |
|||
---+---+--- |
|||
X | O | 6 |
|||
---+---+--- |
|||
X | 8 | O |
|||
X wins across [1, 4, 7] |
|||
</pre> |
Revision as of 09:24, 5 February 2011
You are encouraged to solve this task according to the task description, using any language you may know.
Play a game of tic-tac-toe. Ensure that legal moves are played and that a winning position is notified.
Python
The computer enforces the rules but plays a random game. <lang python>
Tic-tac-toe game player. Input the index of where you wish to place your mark at your turn.
import random
board = list('123456789') wins = ((0,1,2), (3,4,5), (6,7,8),
(0,3,6), (1,4,7), (2,5,8), (0,4,8), (2,4,6))
def printboard():
print('\n'.join(' '.join(board[x:x+3]) for x in(0,3,6)))
def score():
for w in wins: b = board[w[0]] if b in 'XO' and all (board[i] == b for i in w): return b, [i+1 for i in w] return None, None
def finished():
return all (b in 'XO' for b in board)
def space():
return [ b for b in board if b not in 'XO']
def my_turn(xo):
options = space() choice = random.choice(options) board[int(choice)-1] = xo return choice
def your_turn(xo):
options = space() while True: choice = input(" Put your %s in any of these positions: %s " % (xo, .join(options))).strip() if choice in options: break print( "Whoops I don't understand the input" ) board[int(choice)-1] = xo return choice
def me(xo='X'):
printboard() print('I go at', my_turn(xo)) return score() assert not s[0], "\n%s wins across %s" % s
def you(xo='O'):
printboard() # Call my_turn(xo) below for it to play itself print('You went at', your_turn(xo)) return score() assert not s[0], "\n%s wins across %s" % s
print(__doc__)
while not finished():
s = me('X') if s[0]: printboard() print("\n%s wins across %s" % s) break if not finished(): s = you('O') if s[0]: printboard() print("\n%s wins across %s" % s) break
else:
print('\nA draw')
</lang>
Sample Game
Tic-tac-toe game player. Input the index of where you wish to place your mark at your turn. 1 2 3 4 5 6 7 8 9 I go at 9 1 2 3 4 5 6 7 8 X Put your O in any of these positions: 12345678 1 You went at 1 O 2 3 4 5 6 7 8 X I go at 3 O 2 X 4 5 6 7 8 X Put your O in any of these positions: 245678 4 You went at 4 O 2 X O 5 6 7 8 X I go at 2 O X X O 5 6 7 8 X Put your O in any of these positions: 5678 7 You went at 7 O X X O 5 6 O 8 X O wins across [1, 4, 7]
Tcl
<lang tcl>package require Tcl 8.6
- This code splits the players from the core game engine
oo::class create TicTacToe {
variable board player letter who constructor {player1class player2class} {
set board {1 2 3 4 5 6 7 8 9} set player(0) [$player1class new [self] [set letter(0) "X"]] set player(1) [$player2class new [self] [set letter(1) "O"]] set who 0
}
method PrintBoard {} {
lassign $board a1 b1 c1 a2 b2 c2 a3 b3 c3 puts [format " %s | %s | %s" $a1 $b1 $c1] puts "---+---+---" puts [format " %s | %s | %s" $a2 $b2 $c2] puts "---+---+---" puts [format " %s | %s | %s" $a3 $b3 $c3]
}
method WinForSomeone {} {
foreach w { {0 1 2} {3 4 5} {6 7 8} {0 3 6} {1 4 7} {2 5 8} {0 4 8} {2 4 6} } { set b [lindex $board [lindex $w 0]] if {$b ni "X O"} continue foreach i $w {if {[lindex $board $i] ne $b} break} if {[lindex $board $i] eq $b} { foreach p $w {lappend w1 [expr {$p+1}]} return [list $b $w1] } } return ""
}
method status {} {
return $board
}
method IsDraw {} {
foreach b $board {if {[string is digit $b]} {return false}} return true
}
method legalMoves {} {
foreach b $board {if {[string is digit $b]} {lappend legal $b}} return $legal
}
method DoATurn {} {
set legal [my legalMoves] my PrintBoard while 1 { set move [$player($who) turn] if {$move in $legal} break puts "Illegal move!" } lset board [expr {$move - 1}] $letter($who) $player($who) describeMove $move set who [expr {1 - $who}] return [my WinForSomeone]
}
method game {} { puts " Tic-tac-toe game player. Input the index of where you wish to place your mark at your turn.\n"
while {![my IsDraw]} { set winner [my DoATurn] if {$winner eq ""} continue lassign $winner winLetter winSites my PrintBoard puts "\n$winLetter wins across \[[join $winSites {, }]\]" return $winLetter } puts "\nA draw"
}
}
- Stupid robotic player
oo::class create RandomRoboPlayer {
variable g constructor {game letter} {
set g $game
} method turn {} {
set legal [$g legalMoves] return [lindex $legal [expr {int(rand()*[llength $legal])}]]
} method describeMove {move} {
puts "I go at $move"
}
}
- Interactive human player delegate
oo::class create HumanPlayer {
variable g char constructor {game letter} {
set g $game set char $letter
} method turn {} {
set legal [$g legalMoves] puts ">>> Put your $char in any of these positions: [join $legal {}]" while 1 { puts -nonewline ">>> " flush stdout gets stdin number if {$number in $legal} break puts ">>> Whoops I don't understand the input!" } return $number
} method describeMove {move} {
puts "You went at $move"
}
}
- Assemble the pieces
set ttt [TicTacToe new HumanPlayer RandomRoboPlayer] $ttt game</lang> Sample game:
Tic-tac-toe game player. Input the index of where you wish to place your mark at your turn. 1 | 2 | 3 ---+---+--- 4 | 5 | 6 ---+---+--- 7 | 8 | 9 >>> Put your X in any of these positions: 123456789 >>> 1 You went at 1 X | 2 | 3 ---+---+--- 4 | 5 | 6 ---+---+--- 7 | 8 | 9 I go at 5 X | 2 | 3 ---+---+--- 4 | O | 6 ---+---+--- 7 | 8 | 9 >>> Put your X in any of these positions: 2346789 >>> 7 You went at 7 X | 2 | 3 ---+---+--- 4 | O | 6 ---+---+--- X | 8 | 9 I go at 9 X | 2 | 3 ---+---+--- 4 | O | 6 ---+---+--- X | 8 | O >>> Put your X in any of these positions: 23468 >>> 4 You went at 4 X | 2 | 3 ---+---+--- X | O | 6 ---+---+--- X | 8 | O X wins across [1, 4, 7]