I'm trying to build a tic tac toe program using a 3x3 board list running inside of a DynamicModule with a separate window displaying the current value and accepting clicks from the user. For now I'm just trying to use EventHandler to set any empty boxes to X's when clicked.
When I click on a box, I get the error
Part::pkspec1: The expression x cannot be used as a part specification.
Is this an issue with assigning a new value for board inside of the EventHandler?
How else should I structure this?
createBox[elem_] := Show[
Graphics[{White, Rectangle[]}, Frame -> True,
FrameStyle -> Thickness[.02], FrameTicks -> None],
Graphics@Text[Style[elem, FontSize -> 100], {.5, .5}],
ImageSize -> 150
]
DynamicModule[{board = Table[Table[" ", 3], 3]},
CreateWindow[
DocumentNotebook[
(*Displaying grid*)
Dynamic@Grid[
Table[Table[
EventHandler[
createBox[board[[y]][[x]]]
, {"MouseClicked" :> (
If[board[[y]][[x]] == " ", board[[y]][[x]] = "X";];
)}]
, {x, 3}], {y, 3}],
Spacings -> {0, 0}]
],
WindowElements -> {}, WindowTitle -> "Tic Tac Toe",
WindowSize -> All, Editable -> False, Selectable -> False,
ShowCellBracket -> False, WindowFrameElements -> {"CloseBox"}];
];
Answer
Main issues:
set part
board[[y]][[x]] = valwill not work, you needboard[[y, x]] = "X"See: Part not behaving the way I expect it to
xandycan't get inside:>RuleDelayedholds and so afterTableis done you will haveboard[[y, x]]in each item, instead of expected e.g.board[[2,1]]etc.The way to go is to use
With[{i=i},...idiom, see: Function in TableDynamicModuleis 'a scoped rectangle in your screen'So instead of
DynamicModule[.. CreateWindow..it should rather beCreateWindow[.. DynamicModule..See e.g. IntroductionToDynamic
Secondary issues
you don't need
DynamicaroundGrid, only content ofboardchanges so you can put it insidecreateBox[Dynamic[...]]it is better to use
===instead of==to compare non numerical valuesShow[Graphics...]can be combined in oneGraphics[...]Unless you need it we can replace
CreateWindow[NotebookDocumentwithCreateDocument(omg, I just realized the origin of this function name, thanks)but your notebook's options suggest it may be enough to use
CreateDialogyou can combine nested
Tableinto one
Summing up:
createBox[elem_] := Graphics[
{ { White, Rectangle[] }
, Text[Style[elem, FontSize -> 100], {.5, .5}]
}
, ImageSize -> 150
, Frame -> True
, FrameStyle -> Thickness[.02]
, FrameTicks -> None
];
CreateDialog[
DynamicModule[
{board = ConstantArray[" ", {3, 3}]}
, Grid[
Table[ With[{x = x, y = y}
, EventHandler[
createBox[ Dynamic @ board[[y, x]]]
, {"MouseClicked" :> If[board[[y, x]] === " ", board[[y, x]] = "X"]
}
]]
, {x, 3}, {y, 3}
]
, Spacings -> {0, 0}
]
]
, WindowTitle -> "Tic Tac Toe"
, WindowSize -> All
];

Comments
Post a Comment