diff --git a/exercises/practice/state-of-tic-tac-toe/.meta/example.tcl b/exercises/practice/state-of-tic-tac-toe/.meta/example.tcl index cdb2e6c3..04afd0d5 100644 --- a/exercises/practice/state-of-tic-tac-toe/.meta/example.tcl +++ b/exercises/practice/state-of-tic-tac-toe/.meta/example.tcl @@ -28,20 +28,20 @@ namespace eval StateOfTicTacToe { proc gamestate {board} { lassign [parse $board] X O - switch [list [won $X] [won $O]] { - {true true} {error "Impossible board: game should have ended after the game was won"} + set xBits [bitCount $X] + set oBits [bitCount $O] + set xWon [won $X] + set oWon [won $O] - {true false} - - {false true} {return "win"} + if {($xWon && $oBits >= $xBits) || ($oWon && $xBits >= $oBits + 1)} { + error "Impossible board: game should have ended after the game was won" + } + if {$xWon || $oWon} then {return "win"} - default { - set xBits [bitCount $X] - set oBits [bitCount $O] - if {$xBits - $oBits > 1} then {error "Wrong turn order: X went twice"} - if {$xBits - $oBits < 0} then {error "Wrong turn order: O started"} - return [expr {$xBits + $oBits == 9 ? "draw" : "ongoing"}] - } - } + if {$xBits - $oBits > 1} then {error "Wrong turn order: X went twice"} + if {$xBits - $oBits < 0} then {error "Wrong turn order: O started"} + + return [expr {$xBits + $oBits == 9 ? "draw" : "ongoing"}] } proc parse {board} { diff --git a/exercises/practice/state-of-tic-tac-toe/.meta/template.j2 b/exercises/practice/state-of-tic-tac-toe/.meta/template.j2 new file mode 100644 index 00000000..db7be86c --- /dev/null +++ b/exercises/practice/state-of-tic-tac-toe/.meta/template.j2 @@ -0,0 +1,20 @@ +{{header}} + +{% for idx, case in cases -%} +{% if idx > 0 -%} +skip {{slug}}-{{idx + 1}} +{% endif -%} +test {{slug}}-{{idx + 1}} {{ case["description"]|tclstring }} -body { + gamestate { {% for row in case["input"]["board"] %} + {{ row|tclstring }}{% endfor %} + } +{% if case["expect_error"] -%} +} -returnCodes error -result "{{ case["expect_error_msg"] }}" + +{% else -%} +} -returnCodes ok -result "{{ case["expected"] }}" + +{% endif -%} +{% endfor -%} + +{{footer}} diff --git a/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml b/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml index 8fc25e21..5f574b2a 100644 --- a/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml +++ b/exercises/practice/state-of-tic-tac-toe/.meta/tests.toml @@ -99,3 +99,9 @@ reimplements = "b1dc8b13-46c4-47db-a96d-aa90eedc4e8d" [4801cda2-f5b7-4c36-8317-3cdd167ac22c] description = "Invalid boards -> Invalid board: players kept playing after a win" + +[5a84757a-fc86-4328-aec9-a5759e6ed35d] +description = "Invalid boards -> Invalid board: O kept playing after X wins" + +[cf25543d-583a-4656-b9ab-f82dc00a4a02] +description = "Invalid boards -> Invalid board: X kept playing after O wins" diff --git a/exercises/practice/state-of-tic-tac-toe/state-of-tic-tac-toe.test b/exercises/practice/state-of-tic-tac-toe/state-of-tic-tac-toe.test index c4423798..2a1fd9e0 100644 --- a/exercises/practice/state-of-tic-tac-toe/state-of-tic-tac-toe.test +++ b/exercises/practice/state-of-tic-tac-toe/state-of-tic-tac-toe.test @@ -1,261 +1,274 @@ #!/usr/bin/env tclsh +# generated on 2026-07-15T20:43:11+00:00 package require tcltest namespace import ::tcltest::* source testHelpers.tcl +# Uncomment next line to view test durations. +#configure -verbose {body error usec} + ############################################################ source "state-of-tic-tac-toe.tcl" -# Won games - -test state-1.1 "Finished game where X won via left column victory" -body { - gamestate { +test state-of-tic-tac-toe-1 "Finished game where X won via left column victory" -body { + gamestate { "XOO" "X " "X " } } -returnCodes ok -result "win" -skip state-1.2 -test state-1.2 "Finished game where X won via middle column victory" -body { - gamestate { +skip state-of-tic-tac-toe-2 +test state-of-tic-tac-toe-2 "Finished game where X won via middle column victory" -body { + gamestate { "OXO" " X " " X " } } -returnCodes ok -result "win" -skip state-1.3 -test state-1.3 "Finished game where X won via right column victory" -body { - gamestate { +skip state-of-tic-tac-toe-3 +test state-of-tic-tac-toe-3 "Finished game where X won via right column victory" -body { + gamestate { "OOX" " X" " X" } } -returnCodes ok -result "win" -skip state-1.4 -test state-1.4 "Finished game where O won via left column victory" -body { - gamestate { +skip state-of-tic-tac-toe-4 +test state-of-tic-tac-toe-4 "Finished game where O won via left column victory" -body { + gamestate { "OXX" "OX " "O " } } -returnCodes ok -result "win" -skip state-1.5 -test state-1.5 "Finished game where O won via middle column victory" -body { - gamestate { +skip state-of-tic-tac-toe-5 +test state-of-tic-tac-toe-5 "Finished game where O won via middle column victory" -body { + gamestate { "XOX" " OX" " O " } } -returnCodes ok -result "win" -skip state-1.6 -test state-1.6 "Finished game where O won via right column victory" -body { - gamestate { +skip state-of-tic-tac-toe-6 +test state-of-tic-tac-toe-6 "Finished game where O won via right column victory" -body { + gamestate { "XXO" " XO" " O" } } -returnCodes ok -result "win" -skip state-1.7 -test state-1.7 "Finished game where X won via top row victory" -body { - gamestate { +skip state-of-tic-tac-toe-7 +test state-of-tic-tac-toe-7 "Finished game where X won via top row victory" -body { + gamestate { "XXX" "XOO" "O " } } -returnCodes ok -result "win" -skip state-1.8 -test state-1.8 "Finished game where X won via middle row victory" -body { - gamestate { +skip state-of-tic-tac-toe-8 +test state-of-tic-tac-toe-8 "Finished game where X won via middle row victory" -body { + gamestate { "O " "XXX" " O " } } -returnCodes ok -result "win" -skip state-1.9 -test state-1.9 "Finished game where X won via bottom row victory" -body { - gamestate { +skip state-of-tic-tac-toe-9 +test state-of-tic-tac-toe-9 "Finished game where X won via bottom row victory" -body { + gamestate { " OO" "O X" "XXX" } } -returnCodes ok -result "win" -skip state-1.10 -test state-1.10 "Finished game where O won via top row victory" -body { - gamestate { +skip state-of-tic-tac-toe-10 +test state-of-tic-tac-toe-10 "Finished game where O won via top row victory" -body { + gamestate { "OOO" "XXO" "XX " } } -returnCodes ok -result "win" -skip state-1.11 -test state-1.11 "Finished game where O won via middle row victory" -body { - gamestate { +skip state-of-tic-tac-toe-11 +test state-of-tic-tac-toe-11 "Finished game where O won via middle row victory" -body { + gamestate { "XX " "OOO" "X " } } -returnCodes ok -result "win" -skip state-1.12 -test state-1.12 "Finished game where O won via bottom row victory" -body { - gamestate { +skip state-of-tic-tac-toe-12 +test state-of-tic-tac-toe-12 "Finished game where O won via bottom row victory" -body { + gamestate { "XOX" " XX" "OOO" } } -returnCodes ok -result "win" -skip state-1.13 -test state-1.13 "Finished game where X won via falling diagonal victory" -body { - gamestate { +skip state-of-tic-tac-toe-13 +test state-of-tic-tac-toe-13 "Finished game where X won via falling diagonal victory" -body { + gamestate { "XOO" " X " " X" } } -returnCodes ok -result "win" -skip state-1.14 -test state-1.14 "Finished game where X won via rising diagonal victory" -body { - gamestate { +skip state-of-tic-tac-toe-14 +test state-of-tic-tac-toe-14 "Finished game where X won via rising diagonal victory" -body { + gamestate { "O X" "OX " "X " } } -returnCodes ok -result "win" -skip state-1.15 -test state-1.15 "Finished game where O won via falling diagonal victory" -body { - gamestate { +skip state-of-tic-tac-toe-15 +test state-of-tic-tac-toe-15 "Finished game where O won via falling diagonal victory" -body { + gamestate { "OXX" "OOX" "X O" } } -returnCodes ok -result "win" -skip state-1.16 -test state-1.16 "Finished game where O won via rising diagonal victory" -body { - gamestate { +skip state-of-tic-tac-toe-16 +test state-of-tic-tac-toe-16 "Finished game where O won via rising diagonal victory" -body { + gamestate { " O" " OX" "OXX" } } -returnCodes ok -result "win" -skip state-1.17 -test state-1.17 "Finished game where X won via a row and a column victory" -body { - gamestate { +skip state-of-tic-tac-toe-17 +test state-of-tic-tac-toe-17 "Finished game where X won via a row and a column victory" -body { + gamestate { "XXX" "XOO" "XOO" } } -returnCodes ok -result "win" -skip state-1.18 -test state-1.18 "Finished game where X won via two diagonal victories" -body { - gamestate { +skip state-of-tic-tac-toe-18 +test state-of-tic-tac-toe-18 "Finished game where X won via two diagonal victories" -body { + gamestate { "XOX" "OXO" "XOX" } } -returnCodes ok -result "win" -# Drawn games - -skip state-2.1 -test state-2.1 "Draw" -body { - gamestate { +skip state-of-tic-tac-toe-19 +test state-of-tic-tac-toe-19 "Draw" -body { + gamestate { "XOX" "XXO" "OXO" } } -returnCodes ok -result "draw" -skip state-2.2 -test state-2.2 "Another draw" -body { - gamestate { +skip state-of-tic-tac-toe-20 +test state-of-tic-tac-toe-20 "Another draw" -body { + gamestate { "XXO" "OXX" "XOO" } } -returnCodes ok -result "draw" - -# Ongoing games - -skip state-3.1 -test state-3.1 "Ongoing game: one move in" -body { - gamestate { +skip state-of-tic-tac-toe-21 +test state-of-tic-tac-toe-21 "Ongoing game: one move in" -body { + gamestate { " " "X " " " } } -returnCodes ok -result "ongoing" -skip state-3.2 -test state-3.2 "Ongoing game: two moves in" -body { - gamestate { +skip state-of-tic-tac-toe-22 +test state-of-tic-tac-toe-22 "Ongoing game: two moves in" -body { + gamestate { "O " " X " " " } } -returnCodes ok -result "ongoing" -skip state-3.3 -test state-3.3 "Ongoing game: five moves in" -body { - gamestate { +skip state-of-tic-tac-toe-23 +test state-of-tic-tac-toe-23 "Ongoing game: five moves in" -body { + gamestate { "X " " XO" "OX " } } -returnCodes ok -result "ongoing" -# Invalid boards - -skip state-4.1 -test state-4.1 "Invalid board: X went twice" -body { - gamestate { +skip state-of-tic-tac-toe-24 +test state-of-tic-tac-toe-24 "Invalid board: X went twice" -body { + gamestate { "XX " " " " " } } -returnCodes error -result "Wrong turn order: X went twice" -skip state-4.2 -test state-4.2 "Invalid board: O started" -body { - gamestate { +skip state-of-tic-tac-toe-25 +test state-of-tic-tac-toe-25 "Invalid board: O started" -body { + gamestate { "OOX" " " " " } } -returnCodes error -result "Wrong turn order: O started" -skip state-4.3 -test state-4.3 "Invalid board: X won and O kept playing" -body { - gamestate { +skip state-of-tic-tac-toe-26 +test state-of-tic-tac-toe-26 "Invalid board: X won and O kept playing" -body { + gamestate { "XXX" "OOO" " " } } -returnCodes error -result "Impossible board: game should have ended after the game was won" -skip state-4.4 -test state-4.4 "Invalid board: players kept playing after a win" -body { - gamestate { +skip state-of-tic-tac-toe-27 +test state-of-tic-tac-toe-27 "Invalid board: players kept playing after a win" -body { + gamestate { "XXX" "OOO" "XOX" } } -returnCodes error -result "Impossible board: game should have ended after the game was won" +skip state-of-tic-tac-toe-28 +test state-of-tic-tac-toe-28 "Invalid board: O kept playing after X wins" -body { + gamestate { + "OO " + "XXX" + " O " + } +} -returnCodes error -result "Impossible board: game should have ended after the game was won" + +skip state-of-tic-tac-toe-29 +test state-of-tic-tac-toe-29 "Invalid board: X kept playing after O wins" -body { + gamestate { + "XX " + "OOO" + " XX" + } +} -returnCodes error -result "Impossible board: game should have ended after the game was won" + cleanupTests