Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I need to draw a Hex board. I would like to be able to mark each hexagon and mark the size. Being able to control the thickness of the lines would be nice, but it is not something I need to have. Could anyone suggest a simple way of doing this?

Here is a picture of what I had in mind:

http://i.imgur.com/VUkqMYE.png

EDIT: Cmhughes brought up some pointers on making this post better, so here it goes!

I have found very little material to help me through this. However, I found this on the stackexchange forum. I have tried modifying the code (from the first answer) to fit my needs (as shown in the picture), but every time I change something the graph does some very weird things, like creating a large line of hexagons in what appears to be a random direction.

My problem, then, is that I have no idea how I would modify the code to make it a Hex board, rather than a Hex map.

This is the code I am referring to:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{shapes}

\begin{document}
  \begin{tikzpicture}[
    hexa/.style={ 
      shape=regular polygon,
      regular polygon sides=6,
      minimum size=1cm,
      draw,
      inner sep=0,
      anchor=south,
      fill=lightgray!85!blue,
      rotate=30
    }
  ]
    \foreach \j in {0,...,5}{%
      \pgfmathsetmacro\end{5+\j} 
      \foreach \i in {0,...,\end}{%
        \node[hexa] (h\i;\j) at ({(\i-\j/2)*sin(60)},{\j*0.75}) {};
      }
    }
    \foreach \j in {0,...,4}{%
      \pgfmathsetmacro\end{9-\j} 
      \foreach \i in {0,...,\end}{%
        \pgfmathtruncatemacro\k{\j+6}  
        \node[hexa] (h\i;\k) at ({(\i+\j/2-2)*sin(60)},{4.5+\j*0.75}) {};
      }
    }
    \foreach \k in {0,...,10} {%
      \node[circle,red,minimum size=1cm] at (h3;\k) {3;\k};
    }
    \foreach \k in {0,...,10} {%
      \node[circle,blue,minimum size=1cm] at (h1;\k) {1;\k};
    }
  \end{tikzpicture}
\end{document}

Does anyone have any pointers on how to modify the code?

Further, does anyone know how to mark the sides, like in the picture, and how to create a random-looking marking of the hexagons (although I this may have to simply be a lot of copying and pasting)?

share|improve this question
    
Welcome to TeX.SX! You can have a look on our starter guide to familiarize yourself further with our format. Could you show the community what you have tried so far? Posting a screenshot and asking folks to produce it from scratch may not receive much attention- posting an attempt and describing a specific detail that is holding you up may get more :) –  cmhughes Nov 2 '13 at 15:03
    
There's some code for drawing Chinese Checkers boards that might come in handy here. –  Jake Nov 2 '13 at 15:04
2  
There's an excellent, very detailed article on approaches to representing hexagonal grids. Very insightful, with fun interactive graphics =). –  Jake Nov 2 '13 at 19:53
    
I've got to ask: Is this for tabletop RPG or wargaming by any chance? –  Canageek Nov 4 '13 at 6:01
    
No, I am writing an essay where I am, in one part, discussing the proof of Brouwer's fixed-point theorem using the board game Hex. The paper, by D. Gale, is called "The Game of Hex and the Brouwer Fixed-Point Theorem" in case you're interested in the proof! –  Surculus Nov 5 '13 at 14:07
add comment

6 Answers

up vote 21 down vote accepted

enter image description here

This MWE with Asymptote uses struct hexboard from hexboard.asy module (attached). The board hb is created with the command hexboard hb=hexboard(11,xo); is 11 cells wide, the marks are prepared in the array of strings string[] xo;

Cell nodes and directions are as follows (direction is named after the node of destination):

enter image description here

The thick line is constructed by the start cell, optional prefix and suffix (if the line goes outside the grid), the node number to start with and a sequence of the directions. For example a command

hb.oline((-10,0), prefix=(0,-1),3,4,5,0);

uses the node 3 of the bottom cell (-10,0) as a starting point, prepends it with the line from below point (0,-1) and continue with directions 4,5 and 0 (4 segments in total).

Position of the leftmost cell is (0,0), rightmost cell is (n-1,0) the top is at (0,n-1), and the bottom is at (0,-(n-1)).

%
% hexboard.tex :
%
\begin{filecontents*}{hexboard.asy}
struct hexboard{
  int n;
  string[] xo;
  string xmark,omark;
  real dx,dy;

  pen gridPen;
  pen xCellBg;
  pen oCellBg;

  guide ghex;

  pair hexCenter(int k, int j){ // k= +/-
    return ((j+abs(k)/2)*dx,k*dy);
  }

  pair hexCorner(int k, int j, int a){ 
    return shift(hexCenter(k,j))*point(ghex,a%6);
  }

  void dot(int k, int j, int a, pen p=gridPen){
    dot(hexCorner(k,j,a),p,UnFill);
  }

  void dots(int k, int j, int a, int b, pen p=gridPen){
    for(int i=a;i<=b;++i){
      dot(hexCorner(k,j,i),p,UnFill);
    }
  }

  void oline(explicit pair start, explicit pair prefix=(0,0), explicit pair suffix=(0,0), 
         explicit pen lpen=orange+2bp+opacity(0.8) ... int[]dirs){
    pair p=hexCorner((int)start.x,(int)start.y,dirs[0]);
    guide g=(p+prefix)--p;
    for(int i=1;i<dirs.length;++i){
      p+=dir(150+(dirs[i]%6)*60);
      g=g--p;
    }
    g=g--(p+suffix);
    draw(g,lpen);
  }

  void drawHex(int k, int j){
    pen bg=(substr(xo[n-1-k],j,1)=="x")?xCellBg:oCellBg;
    filldraw(shift((j+abs(k)/2)*dx,k*dy)*ghex,bg,gridPen);
  }

  void markCell(int k, int j, string v){
    if(v=="x")v=xmark;
    if(v=="o")v=omark;
    label(v,hexCenter(k,j));
  }

  void mark(){
    assert(xo.length==2n-1);
    bool b;
    string c;
    int k;
    for(int i=0;i<n;++i){
      assert(length(xo[i])==i+1);
      k=n-1-i;
      for(int j=0;j<i+1;++j){
        c=substr(xo[i],j,1);
        drawHex(k,j);
        markCell(k,j,c);
      }
    }
    for(int i=n;i<2n-1;++i){
      assert(length(xo[i])==2n-1-i);
      k=n-1-i;
      for(int j=0;j<2n-1-i;++j){
        c=substr(xo[i],j,1);
        drawHex(k,j);
        markCell(k,j,c);
      }
    }
  }

  void operator init(int n // board width
      ,string[] xo         // board marks
      ,string xmark="$\times$"
      ,string omark="$\circ$"
      ,pen gridPen=deepblue+0.4bp
      ,pen xCellBg=palered
      ,pen oCellBg=palegreen
    ){
    this.n=n; 
    this.xo=copy(xo);
    this.xmark=xmark; this.omark=omark;
    this.xCellBg=xCellBg; this.oCellBg=oCellBg;
    this.dx=sqrt(3);
    this.dy=1+1/2;
    this.ghex=dir(90)--dir(150)--dir(210)--dir(270)--dir(330)--dir(30)--cycle;
    mark();
  }
}
\end{filecontents*}
%
\documentclass{article}
\usepackage[inline]{asymptote}
\usepackage{lmodern}
\begin{document}
\begin{figure}
\centering
\begin{asy}
size(10cm);

// === test hexboard
import hexboard;
string[] xo={
"o",
"xo",
"xxx",
"ooox",
"xxoox",
"xxoooo",
"oxxoxxo",
"xoxooxxx",
"oxooxooox",
"xooxooxooo",
"oxxxoxooxxo",
"oooxoxxoxx",
"xxxoxooxo",
"ooxooxxo",
"xxoooxo",
"ooxxxo",
"xoxoo",
"xoxx",
"oxo",
"xo",
"x",
};

hexboard hb=hexboard(11,xo);

label("$v$",hb.hexCorner(0,0,2)-(1,0),W);
label("$v^\prime$",hb.hexCorner(0,10,5)+(1,0),E);

label("$w$",hb.hexCorner(-10,0,3)-(0,1),S);
label("$w^\prime$",hb.hexCorner(10,0,0)+(0,1),N);

label("$o^\prime$",hb.hexCorner(5,0,1)-(1,0),W);
label("$x^-$",hb.hexCorner(5,5,5)+(1,0),E);

hb.oline((5,0),0,1,2,3,2,3,2,3,4,5,4,5,0,5, 4,5,0,1,0,1,2);
hb.oline((10,0), prefix=(0,1) ,suffix=(1,0)
,0
,3,2,3,2,1,0,5,0,1,2,1,2,3,4,3,4,3,2,3,2,3,4
,3,2,3,2,1,0,5,0,1,0,1,2,3,2,3,4
,3,2,3,4
,3,4,3,2,3);

hb.oline((0,0), prefix=(-1,0),2,3,2,3,4);

hb.oline((-10,0), prefix=(0,-1),3,4,5,0);

hb.dot(9,0,3);
hb.dot(7,1,4);
hb.dots(5,1,0,3);

shipout(bbox(Fill(lightyellow)));

\end{asy}
\caption{Hex Board}
\end{figure}
\end{document}
%
% Process :
%
% pdflatex hexboard.tex    
% asy hexboard-*.asy    
% pdflatex hexboard.tex
share|improve this answer
    
One question, how do I make the figure larger? Preferably so that it fills the whole page. Other than that, this worked perfectly, although the co-ordinates of the hexagons is confusing. Maybe it will make sense after I get some sleep, the co-ordinate system led to a huge guessing game but I got the final product! –  Surculus Nov 3 '13 at 1:41
1  
@Surculus: One way to scale the figure to fit the whole page would be as follows: make it a standalone using standalone document class (don't forget to remove the figure environment) and then include it with pdfpages package. As for co-ordinates: perhaps it would be less confusing with the edited picture: direction is named after the node of destination. –  g.kov Nov 3 '13 at 8:02
add comment

Just for fun with PSTricks. It is not a complete solution.

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{pst-poly}
\psset{PstPicture=false,PolyRotation=30}

\def\Cell(#1,#2)#3{\rput(!3 sqrt #1 #2 2 mod 0 eq {} {.5 add} ifelse mul 1.5 #2 mul){\PstHexagon\rput(0,0){#3}}}

\begin{document}
\begin{pspicture}(-7,-7)(8,7)
    \multido{\ix=-3+1}{7}{\multido{\iy=-3+1}{7}{\Cell(\ix,\iy){$(\ix,\iy)$}}}
\end{pspicture}
\end{document}

enter image description here

share|improve this answer
    
We can reduce the file size by a factor of 2 if we can make each edge drawn just once. But the algorithm to draw becomes more complicated. –  Fifa Earth Cup 2014 Nov 4 '13 at 0:04
add comment

I modified some snippets from Jake's answer about Chinese checkers and from Alain's answer about an hexagonal grid. Using the node labeling you can draw thick lines in between. It's better to use the corners as references, like I did in this answer about naming corners of a polygon, rather than the usual north, east because the polygons are rotated.

The corners go counter-clockwise. I don't know of any way to change this, and I didn't find any mention in the manual. This is how it goes:

corners image

Here is a picture of it with the node names printed in each one (you can use those to reference the nodes like I did in the code below).

Below there is an example of the line. I didn't do all of them because it's time consuming and I wanted just to show how it worked. When you want to remove the label from the nodes, delete this line label=center:{\count-\n}.

full hex map image

\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,calc}

\tikzset{hexa/.style={shape=regular polygon,
                      regular polygon sides=6,
                      minimum size=1cm, 
                      draw,
                      inner sep=0mm,
                      outer sep=0mm,
                      anchor=south,
                      fill=white,
                      rotate=-30},
        hl/.style={line width=3pt,line cap=round} 
}

\begin{document}
\begin{tikzpicture}%[x=9mm, y=5mm]

\foreach \m [count=\count] in {1,...,10,11,10,...,1}{
            \foreach \n in {1,...,\m}
                \node at ({(\n-\m/2)*sin(60)},{\count*.75})
                [hexa, 
                name=\count-\n,
                label=center:{\count-\n}] {};
                }

\draw[hl]   ($(1-1.corner 5)+(0,-1)$) -- (1-1.corner 5) -- (1-1.corner 6) -- 
            (1-1.corner 1) -- (1-1.corner 2) -- (2-2.corner 3) --
            (2-2.corner 2);

\end{tikzpicture}
\end{document}   
share|improve this answer
add comment

Here's a slightly different approach from the others offered:

\documentclass{article}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes}

%% styles for the hexboard
\tikzset{
    hexa/.style={ 
      shape=regular polygon,
      regular polygon sides=6,
      minimum size=1cm/sin(60),
      draw,
      inner sep=0,
      anchor=south,
      %%fill=#1,
      rotate=210,%%so ".corner 1" is at bottom of hexa shape
    },
  set hex board dimensions/.style={x=0.5cm, y=1cm*sin(60)},
  my hex path/.style={line width=2pt,line cap=round},
}

\makeatletter
\newif\if@surculus@shownodenames
\def\showmynodenames{\@surculus@shownodenamestrue}
\def\surculus@topcnt{4}
\def\surculus@botcnt{5}
\def\surculus@set@boardwidth#1{%%
  \def\surculus@botcnt{#1}%%
  \def\surculus@topcnt{\number\numexpr#1-1\relax}}

%% Here's a command to set up the board.  The argument 
%% is the width of widest row in the board
\def\drawhexboard#1{%%
  \surculus@set@boardwidth{#1}
  \tikzset{set hex board dimensions}
    \foreach \row in {1,...,\surculus@botcnt}{%
      \foreach \pos in {1,...,\row}
        {%%
          \node[hexa=red!20] (H\row;\pos) at (2*\pos-\row,\row) {};
          \if@surculus@shownodenames
            \node at (H\row;\pos) {\row;\pos};
          \fi
        }
    }
    \def\startcnt{\number\numexpr\surculus@botcnt+1\relax}
    \def\endcnt{\number\numexpr\surculus@topcnt+\surculus@botcnt\relax}
    \foreach \row in {\endcnt,...,\startcnt}{%
      \foreach \pos in {\endcnt,...,\row}{%
        \edef\surculus@rowpos{\number\numexpr\pos-\row+1\relax}
        \node[hexa=blue!10] (H\row;\surculus@rowpos) at (2*\pos-\row-2*\surculus@topcnt,\row) {};
        \if@surculus@shownodenames
          \node at (H\row;\surculus@rowpos) {\row;\surculus@rowpos};
        \fi
      }
    }
}

%% command to assist in drawing the path around the hexagons.
\def\drawhexpath(#1)#2{%%
    \let\surculus@previous\relax%%
    \foreach \x in {#2}
      { \ifx\relax\surculus@previous
          \xdef\surculus@previous{\x}%%
          %% for testing %% \node [circle,fill=red,inner sep=2pt] at (H#1.corner \x) {};
        \else
          \draw[my hex path]  (H#1.corner \surculus@previous) -- (H#1.corner \x);
          \xdef\surculus@previous{\x}%%
        \fi
    }}
\makeatother

\begin{document}

  \begin{tikzpicture}
    \showmynodenames%%<-- must precede the creation of the board if you want to see node names
    \drawhexboard{10}
    \draw[my hex path] ($(H1;1.corner 1)-(0,1cm)$) -- (H1;1.corner 1);
    \drawhexpath(1;1){1,2,3,4}
    \drawhexpath(2;2){6,5}
    \drawhexpath(3;2){1,2,3,4,5,6}
    \drawhexpath(3;1){2,1,6,5}
    \drawhexpath(4;1){1,2,3}
    \drawhexpath(5;2){1,2,3,4,5}

    \draw[my hex path] ($(H10;10.corner 3)+(1cm,0)$) -- (H10;10.corner 3);
    \drawhexpath(10;10){3,2,1,6,5}
    \drawhexpath(10;9){3,4}
    \drawhexpath(11;8){2,3,4}
    \drawhexpath(12;8){6,5,4,3,2}
  \end{tikzpicture}

\end{document}

The idea here is that \drawhexboard{<num>} creates a hex board with its widest row set to <num>. You can then draw paths around individual cells using the command

\draw(<node id>){<comma separated list of corners>}

I created a command \showmynodenames which allows you to see the names of the nodes to help define the paths. Just comment that line out and you'll get the hex diagram as you want it.

With \showmynodenames commented out, you get:

enter image description here

With \showmynodenames turned on, you get:

enter image description here

To do

Some work needs to be done to smooth out the connections along the path. I'll have to work on that later though.

Also, it's possible to define a macro which will set the content of each hex-box to either x or o. But, unfortunately, I don't have the time at this moment to write up that part of the code. I'll look at it later in the day.

share|improve this answer
add comment

Here an approach different from my first approach. It is similar in some ways to @g.kov 's approach but does not rely upon Asymptote. Also, this approach figures out where the borders should be drawn merely by examining the contents of neighboring cells.

I've added a new macro \sethexboardbaselength which takes a dimension as an argument. This macro can help you scale the hex-board to the size you want.

UPDATE I've added some garbage collection to remove and delete the macros holding cell information once the hex-board has been drawn. Without doing this, if you draw boards of different sizes, later boards may mistake hold-over information from a previous board as information about the current board. Also macros hold hex-board cell information are removed by \letting them to an undefined control sequence \ae@undefined@.

\documentclass{article}
\usepackage[margin=0.5in]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}
\usetikzlibrary{shapes}

\makeatletter

\newlength{\hexagon@base@length}
\newlength{\x@base@length}
\newlength{\y@base@length}
\setlength{\hexagon@base@length}{0.5cm}
\setlength{\x@base@length}{\hexagon@base@length}
\setlength{\y@base@length}{\dimexpr2\hexagon@base@length\relax}
%% macro to set the dimensions for each hexagon, use this to change
%% the size of the hex-board
\def\sethexboardbaselength#1{%%
  \setlength{\hexagon@base@length}{\dimexpr#1\relax}
  \setlength{\x@base@length}{\hexagon@base@length}
  \setlength{\y@base@length}{\dimexpr2\hexagon@base@length\relax}
}
%% styles for the hexboard
\tikzset{
    my hexagonal node/.style={ 
      shape=regular polygon,
      regular polygon sides=6,
      minimum size=\y@base@length/sin(60),
      draw,
      inner sep=0,
      anchor=south,
      %%fill=#1,
      rotate=210,%%so ".corner 1" is at bottom of hexa shape
    },
  set hex board dimensions/.style={x=\x@base@length, y=\y@base@length*sin(60)},
  my hex path/.style={line width=3pt,line cap=round,blue},
}


%% some booleans to help keep track of where we are on the board
%% as we're drawing border.                                     
\newif\if@in@top@of@hex@board
\newif\if@at@hex@board@equator
\newif\if@at@row@initial@position

%% Since each row of the Hex Board is passed through      
%% a \foreach loop, it is safe to assume that there are   
%% no commas in a given row of the table.  So first time  
%% this macro is called, it should be called with trailing
%% commas.  We then know we're done with the current row  
%% once we've come across those commas.                   
\def\graph@current@row@of@hexagon#1#2#3\@nil{%%
  \@create@new@hexagon@cell{#1}
  \@build@borders@between@neighbors{#1}%%
  \@at@row@initial@positionfalse
  %% recursively call this macro if there are still elements left for the row
  \if,#2\relax
  \else
    \xdef\@cur@h@pos{\number\numexpr\@cur@h@pos+2\relax}
    \graph@current@row@of@hexagon#2#3\@nil
  \fi
}

%% Define a node for the current hex board cell                               
%% Each hex-cell on the board is given a node named as as                              
%%    H<current row>;<current horizontal position>                            
\def\@create@new@hexagon@cell#1{%%                                            
  %% define a node for the current position                                   
  %% Next three lines are just "fluff" to make "x" cells stand out.           
  \if#1x
    \node[my hexagonal node,fill=red!20] at (\@cur@h@pos,-\@cur@row) {};
  \fi
  %% (1) define a macro to hold the name of the "current" cell                
  %% (2) create the hexagonal cell for "current" cell                         
  %% (3) define a macro with which to "remember" cell content                 
  %% (4) define an easily called macro for "current" cell content.            
  \edef\ae@node@name{H\@cur@row;\@cur@h@pos}
  \node[my hexagonal node,label=center:#1] ({\ae@node@name}) at (\@cur@h@pos,-\@cur@row) {};
  \expandafter\xdef\csname ae@node\ae@node@name\endcsname{#1}
  \edef\ae@tmp@c{\csname ae@node\ae@node@name\endcsname}
  %% \typeout{NODE:={H\@cur@row;\@cur@h@pos}}
  %% collect names of macros used to store cell content info for 
  %% removal once the board has been completed.
  \ifx\relax\ae@garbage@
    \xdef\ae@garbage@{\ae@node@name}%%
  \else
    \xdef\ae@garbage@{\ae@garbage@,\ae@node@name}%%
  \fi
}

%% #1 = row                                                                                     
%% #2 = horizontal position within current row                                                  
%% #3 = name of cell we're loooking at: w=west, nw=north west, ne=north east                    
%% #4 = value to assume if@at@hex@board@equator:  ie, at border between TOP and BOTTOM of board 
%% #5 = value to assume if@in@top@of@hex@board AND in top half of board                         
%% #6 = value to assume if in BOTTOM                                                            
\def\@examine@adjacent@cell#1#2#3#4#5#6{%%                                                      
  \edef\@@ae@tmp@name{ae@nodeH\number\numexpr#1\relax;\number\numexpr#2\relax}
  \ifcsname\@@ae@tmp@name \endcsname
    \edef\@@ae@tmp@csname{\expandafter\csname\@@ae@tmp@name\endcsname}
  \else
    \if@at@hex@board@equator
      \edef\@@ae@tmp@csname{#4}%%
    \else
      \if@in@top@of@hex@board
        \edef\@@ae@tmp@csname{#5}%%
      \else
        \edef\@@ae@tmp@csname{#6}%%
      \fi
    \fi
  \fi
  \expandafter\edef\csname ae@tmp@#3\endcsname{\@@ae@tmp@csname}
  %% \typeout{ ___#4___ --> \csname ae@tmp@#4\endcsname\space <=> \ae@tmp@c}
}

%% This next macro examines the contents of the cells to the WEST, NORTH WEST, and NORTH EAST 
%% If the contents of those cells differ from the content of the "current" cell, draw a       
%% border between them.z                                                                      
%% Special conditions hold on the border of the board.  If there is no cell bordering a       
%% particular side of the "current" cell, then I make various assumptions which are handled   
%% by the macro \@examine@adjacent@cell:                                                      
%%   * on the board's north west side, non-existent cells are assumed to have content of "o"  
%%   * on the board's north east side, non-existent cells are assumed to have content of "x"  
%%   * on the board's south west side, non-existent cells are assumed to have content of "x"  
%%   * on the board's south east side, non-existent cells are assumed to have content of "o"  
%% The macro \@build@borders@for@last@row@entry handles similar cases for the last cell of    
%% each row.                                                                                  
\def\@build@borders@between@neighbors#1{%%                                                    
  %% (1) check to the "WEST"                                                                  
  %% (2) check to the "NORTH WEST"                                                            
  %% (3) check to the "NORTH EAST"                                                            
  \@examine@adjacent@cell{\@cur@row}{\@cur@h@pos-2}{w}{o}{o}{x}
  \@examine@adjacent@cell{\@cur@row-1}{\@cur@h@pos-1}{nw}{o}{o}{x}
  \@examine@adjacent@cell{\@cur@row-1}{\@cur@h@pos+1}{ne}{x}{x}{o}
  %% draw borders
  \if x\ae@tmp@c
    \if o\ae@tmp@w
      \draw[my hex path] (\ae@node@name.corner 6) -- (\ae@node@name.corner 5);
    \fi
    \if o\ae@tmp@nw
      \draw[my hex path] (\ae@node@name.corner 5) -- (\ae@node@name.corner 4);
    \fi
    \if o\ae@tmp@ne
      \draw[my hex path] (\ae@node@name.corner 4) -- (\ae@node@name.corner 3);
    \fi
  \fi
  \if o\ae@tmp@c
    \if x\ae@tmp@w
      \draw[my hex path] (\ae@node@name.corner 6) -- (\ae@node@name.corner 5);
    \fi
    \if x\ae@tmp@nw
      \draw[my hex path] (\ae@node@name.corner 5) -- (\ae@node@name.corner 4);
    \fi
    \if x\ae@tmp@ne
      \draw[my hex path] (\ae@node@name.corner 4) -- (\ae@node@name.corner 3);
    \fi
    \if@at@row@initial@position
      \if@in@top@of@hex@board
      \else
        \draw[my hex path] (\ae@node@name.corner 1) -- (\ae@node@name.corner 6);
      \fi
    \fi
  \fi
}

%% Cells to the EAST and SOUTH EAST need only be examined if you are 
%% currently in the last position of the current row.
\def\@build@borders@for@last@row@entry{%%
  \if x\ae@tmp@c
    \if@in@top@of@hex@board
    \else
      \draw[my hex path] (\ae@node@name.corner 1) -- (\ae@node@name.corner 2);
      \draw[my hex path] (\ae@node@name.corner 2) -- (\ae@node@name.corner 3);
    \fi
  \fi
  \if o\ae@tmp@c
    \if@in@top@of@hex@board
      \draw[my hex path] (\ae@node@name.corner 2) -- (\ae@node@name.corner 3);
    \fi
  \fi
}

%% Find out how many rows there are.  There should always be  
%% an odd number.  Add one to this number and divide by two.  
%% This new number determines whether you're in the top or the
%% bottom of the hex board.                                   
\def\@determine@widest@row#1{%% 
  \def\@width@at@hex@board@equator{0}%%
  \foreach \x in {#1}{\xdef\@width@at@hex@board@equator{\number\numexpr\@width@at@hex@board@equator+1\relax}}%%
  \edef\@width@at@hex@board@equator{\number\numexpr(\@width@at@hex@board@equator+1)/2\relax}
  %%\typeout {NUMBER OF ROWS -> \@width@at@hex@board@equator}
}

\def\@init@positions{%%
  \def\@cur@row{1}%%
  \def\@pseudo@row{1}%%
  \def\@cur@h@pos{0}}



%% In the following macro:                                                              
%%   @cur@row      counts the current row from 1 on up.                                 
%%   @pseudo@row   counts the current row until @cur@row==\@width@at@hex@board@equator  
%%                 and then starts to count down.  The value of this macro is used      
%%                 to help determine position the first hexagon of the current row.     
%%   @cur@h@pos    is initially set to the opposite of @pseudo@row, this value is       
%%                 the position of the first hexagon on the "current" row.              
\def\drawboard#1{%%
  \let\ae@garbage@\relax
  \@in@top@of@hex@boardtrue
  \@at@hex@board@equatorfalse
  \@determine@widest@row{#1}%%
  \@init@positions
  %%\typeout{ ============================================================ }
  %%\typeout{ NEW BOARD = }
  %%\typeout{ ============================================================ }
  \begin{tikzpicture}[set hex board dimensions]
    \foreach \hexbox in {#1}
      {
        \xdef\@cur@h@pos{-\@pseudo@row}
        \@at@row@initial@positiontrue
        \expandafter\graph@current@row@of@hexagon\hexbox,,\@nil
        \@build@borders@for@last@row@entry
        \global\@at@hex@board@equatorfalse
        \xdef\@cur@row{\number\numexpr\@cur@row+1}
        \if@in@top@of@hex@board
          \xdef\@pseudo@row{\number\numexpr\@pseudo@row+1}
          \ifnum\@pseudo@row=\@width@at@hex@board@equator\relax
            \global\@at@hex@board@equatortrue
            \global\@in@top@of@hex@boardfalse
          \fi
        \else
          \xdef\@pseudo@row{\number\numexpr\@pseudo@row-1\relax}
        \fi
        %%\typeout{ ------------------------------------------------------------------ }
      }
  \ae@dump@garbage
  \end{tikzpicture}
}

%% Remove macros storing information about contents of cells
\def\ae@dump@garbage{%%
  \foreach \ae@node@name in \ae@garbage@
    {\global\expandafter\let\csname ae@node\ae@node@name\endcsname\ae@undefined@}}

\makeatother

\begin{document}

\hspace*{\fill}
%%
\drawboard{
                          x     ,
                         o x    ,
                        x o x   ,
                       x x x x  ,
                        o x o   ,
                         o o    , 
                          x 
            }
%%
\hspace*{\fill}
%%
\drawboard{
                          x     ,
                         o x    ,
                        x o x   ,
                       x x x x  ,
                      x x o x x ,
                       o o x o  ,
                        o x o   ,
                         o o    , 
                          x 
            }
%%
\hspace*{\fill}


 \hspace*{\fill}
 \drawboard{
                           x      ,
                          o x     ,
                         x o x    ,
                        x o x o   ,
                       x o o x o  ,
                      x o x o x x ,
                       x o o x x  ,
                        o o x o   ,
                         o x o    ,
                          o x     , 
                           x 
             }
 \hspace*{\fill}

\pagebreak

OP's original board

\hspace*{\fill}
\drawboard{
                          o           ,   
                         x o          ,
                        x x x         ,
                       o o o x        ,
                      x x o o x       ,
                     x x o o o o      ,
                    o x x o x x o     ,
                   x o x o o x x x    ,
                  o x o o x o o o x   ,
                 x o o x o o x o o o  ,
                o x x x o x o o x x o ,
                 o o o x o x x o x x  ,
                  x x x o x o o x o   ,
                   o o x o o x x o    ,
                    x x o o o x o     ,
                     o o x x x o      ,
                      x o x o o       ,
                       x o x x        ,
                        o x o         ,
                         x o          ,
                          x                               
            }                          
\hspace*{\fill}

\hspace*{\fill}
\drawboard{
                          o           ,   
                         o x          ,
                        x o x         ,
                       x x x o        ,
                      x o o o o       ,
                     o x x x o o      ,
                    o o o o x o x     ,
                   o o x x o x o x    ,
                  o x x o x x o o x   ,
                 x o x o x o o x x o  ,
                o x o x o x o o x o o ,
                 o x o x o x x o x o  ,
                  o x o x o o x o x   ,
                   x o x o x x o x    ,
                    x x o x o o x     ,
                     o o o x o x      ,
                      x x x o x       ,
                       x o o x        ,
                        x x x         ,
                         o x          ,
                          o                               
            }                          
\hspace*{\fill}
\end{document}

enter image description here

In particular, here's your originally posted board:

\hspace*{\fill}
\drawboard{
                          o           ,   
                         x o          ,
                        x x x         ,
                       o o o x        ,
                      x x o o x       ,
                     x x o o o o      ,
                    o x x o x x o     ,
                   x o x o o x x x    ,
                  o x o o x o o o x   ,
                 x o o x o o x o o o  ,
                o x x x o x o o x x o ,
                 o o o x o x x o x x  ,
                  x x x o x o o x o   ,
                   o o x o o x x o    ,
                    x x o o o x o     ,
                     o o x x x o      ,
                      x o x o o       ,
                       x o x x        ,
                        o x o         ,
                         x o          ,
                          x                               
            }                          
\hspace*{\fill}

enter image description here

share|improve this answer
add comment

In this approach, not much effort has gone into how to specify the contents of the board (which is basically just a 11x11 rectangle with the coordinates transformed). The OP did suggest some randomness for the hexagon contents so I went for that as it is easier.

The main idea was to show a different (although not necessarily better) way of specifying the path using the turtle library from PGF. Ideas for the appearance and the path drawn are shamelessly pinched from k.gov's answer.

\documentclass[border=1cm]{standalone}
\usepackage{tikz}
\usetikzlibrary{shapes,turtle, topaths}

\def\s{1cm}

\tikzset{hexagon/.style={%
    shape=regular polygon,
    regular polygon sides=6,
    inner sep=0pt, outer sep=0pt,
    minimum size=\s,
    draw,
    shape border rotate=-30,
    #1\space hexagon/.try
},
    o hexagon/.style={fill=blue!20, 
      execute at begin node={\tikz\draw[thick, x=(0:\s/6), y=(90:\s/6)] circle [radius=1];}},
    x hexagon/.style={fill=red!20,
      execute at begin node={\tikz\draw[thick, x=(0:\s/6), y=(90:\s/6)] (-1,-1) -- (1,1) (-1,1) -- (1,-1);}},
    turtle path/.style={
        ultra thick,
        draw=orange,
        line cap=round,
        turtle={home,#1}
    },
    turtle/.cd, f/.style={forward=\s/2}, 
    r/.style={right=#1, f}, r/.default=60, 
    l/.style={left=#1, f}, l/.default=60]
}


\begin{document}
\begin{tikzpicture}

\foreach \x in {1,...,11}
    \foreach \y [evaluate={\h=int(rnd*2) ? "o" : "x";}] in {1,...,11}
        \node [x=(60:\s*cos 30), y=(120:\s*cos 30), hexagon={\h}] at (\x, \y) (hexagon \x-\y) {};

\draw [shift=(hexagon 11-11), shift=(90:1)] node [above] {$u^\prime$}
    [turtle path={r=180,l,r,l,r,r,r,r,l,l,l,r,l,l,l,r,l,r,r,l,r,l,l,r,r,l,r,r,r,r,l,l,r,l,l,l,r,l,l,r,r,l,l,r,l,r,r,l,l=30}]
    node [right] {$c^\prime$};

\end{tikzpicture}
\end{document} 

enter image description here

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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