1
$\begingroup$

This is a bit of a follow-up question to my post here. I'm now attempting to replicate the same general code using Connect Four (7x6 grid instead of 3x3).

However, when I pass a Dynamic value to my createBox function, it seems to use values such as board$3379[[1,6]] instead of using the actual board variable. I believe this relates to the RuleDelayed issue described here but using With doesn't seem to help.

When I remove the Dynamic function before board[[x,y]] it works as intended.

createBox[elem_] := Module[{},
   Print@elem;
   Graphics[
    {{White, Rectangle[]}
     , Switch[elem
      , "A", {Red, Disk[{0.5, 0.5}, 0.4]}
      , "B", {Blue, Disk[{0.5, 0.5}, 0.4]}
      , " ", {Thick, Circle[{0.5, 0.5}, 0.4]}
      , _, {}
      ]
     }, ImageSize -> 50, Frame -> True, FrameStyle -> Thickness[.02], 
    FrameTicks -> None
    ]
   ];

CreateDialog[
  DynamicModule[
   {board = ConstantArray[" ", {7, 6}], player = "A"},
   Grid[
    Table[
     With[{y = y, x = x}
      , EventHandler[
       createBox[Dynamic@board[[x, y]]]
       , {"MouseClicked" :> (
          If[board[[y, x]] === " ",
            board[[x, y]] = "A";
            ];
          )}
       ]]
     , {y, Length@board[[1]], 1, -1}, {x, Length@board}
     ], Spacings -> {0, 0}
    ]
   ], WindowTitle -> "Connect Four", WindowSize -> All
  ];

Is there a better way to structure this?

$\endgroup$
1
$\begingroup$

I'm puzzled about what your code is really attempting to do because it only allows white circles to be changed to red disks. There is no way to get a blue disk and no logic for two players to interact. However, look at the following code, it may give you an idea on how to proceed.

Basically, what I have done is remove Module from createBox and move the wrapper Dynamic that you place around board to wrap createBox, so the front-end will deal with it. That seems to fix what I see as your principal problems.

createBox[elem_] :=
  Graphics[
    {{White, Rectangle[]},
     Switch[elem,
       "A", {Red, Disk[{0.5, 0.5}, 0.4]},
       "B", {Blue, Disk[{0.5, 0.5}, 0.4]},
       " ", {Thick, Circle[{0.5, 0.5}, 0.4]},
       _, {}]},
    ImageSize -> 50,
    Frame -> True,
    FrameStyle -> Thickness[.02],
    FrameTicks -> None]

CreateDialog[
  DynamicModule[{board = ConstantArray[" ", {7, 6}], player = "A"},
  Grid[
    Table[
      With[{y = y, x = x},
        EventHandler[
          Dynamic @ createBox[board[[x, y]]], 
          {"MouseClicked" :> 
             (If[board[[y, x]] === " ", board[[x, y]] = "A"])}]], 
      {y, Length @ board[[1]], 1, -1}, {x, Length @ board}],
    Spacings -> {0, 0}]],
  WindowTitle -> "Connect Four",
  WindowSize -> All];

dialog

| improve this answer | |
$\endgroup$
  • $\begingroup$ The code doesn't make a whole lot of sense right now, should have clarified; right now I'm just testing click interaction but later it can be a state of red, blue, or empty. I could have sworn I tried your solution but it works great. Thanks! $\endgroup$ – Chris Jan 1 '18 at 4:37
  • 1
    $\begingroup$ @Chris. I'm glad this was a help to you, and thanks for accepting the answer, but I'm surprised you that you didn't up-vote it as well. Rather unusual for someone to accept but not up-vote. $\endgroup$ – m_goldberg Jan 1 '18 at 17:14
  • $\begingroup$ Sorry, slipped my mind. $\endgroup$ – Chris Jan 1 '18 at 21:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.