File Coverage

blib/lib/Spreadsheet/HTML/Presets/TicTacToe.pm
Criterion Covered Total %
statement 6 20 30.0
branch 0 12 0.0
condition n/a
subroutine 2 5 40.0
pod 1 1 100.0
total 9 38 23.6


line stmt bran cond sub pod time code
1             package Spreadsheet::HTML::Presets::TicTacToe;
2 5     5   17 use strict;
  5         7  
  5         127  
3 5     5   15 use warnings FATAL => 'all';
  5         4  
  5         1310  
4              
5             sub tictactoe {
6 0     0 1   my ($self,$data,$args);
7 0 0         $self = shift if ref($_[0]) =~ /^Spreadsheet::HTML/;
8 0 0         ($self,$data,$args) = $self ? $self->_args( @_ ) : Spreadsheet::HTML::_args( @_ );
9              
10             my @args = (
11             @_,
12             table => {
13 0 0         %{ $args->{table} || {} },
14             id => 'tictactoe',
15             style => {
16             'font-family' => 'cursive, sans-serif',
17             'font-size' => 'xx-large',
18 0 0         %{ $args->{table}{style} || {} },
19             },
20             },
21             td => {
22 0 0         %{ $args->{td} || {} },
  0            
23             height => 100,
24             width => 100,
25             align => 'center',
26             },
27             -r1 => { style => 'border-top:1px solid black; border-bottom:1px solid black;' },
28             -r0c1 => { style => 'border-left:1px solid black; border-right:1px solid black;' },
29             -r1c1 => { style => 'border-left:1px solid black; border-right:1px solid black; border-top:1px solid black; border-bottom:1px solid black;' },
30             -r2c1 => { style => 'border-left:1px solid black; border-right:1px solid black;' },
31             tgroups => 0,
32             headless => 0,
33             pinhead => 0,
34             matrix => 1,
35             wrap => 0,
36             data => [],
37             fill => '3x3',
38             );
39              
40 0           my $js = _javascript( %$args );
41 0 0         my $table = $self ? $self->generate( @args ) : Spreadsheet::HTML::generate( @args );
42 0           return $js . $table;
43             }
44              
45              
46             sub _javascript {
47 0     0     my %args = @_;
48 0           $args{copyright} = 'Copyright 2017 Ray Toal http://jsfiddle.net/rtoal/5wKfF/';
49 0           return Spreadsheet::HTML::Presets::_js_wrapper( code => _js_tmpl(), %args );
50             }
51              
52             sub _js_tmpl {
53 0     0     return <<'END_JAVASCRIPT';
54              
55             /* install JavaScript::Minifier to minify this code */
56             /* Copyright 2017 Ray Toal */
57             /* http://jsfiddle.net/rtoal/5wKfF/ */
58              
59             (function () {
60              
61             var squares = [],
62             EMPTY = "\xA0",
63             score,
64             moves,
65             turn = "X",
66              
67             /*
68             * To determine a win condition, each square is "tagged" from left
69             * to right, top to bottom, with successive powers of 2. Each cell
70             * thus represents an individual bit in a 9-bit string, and a
71             * player's squares at any given time can be represented as a
72             * unique 9-bit value. A winner can thus be easily determined by
73             * checking whether the player's current 9 bits have covered any
74             * of the eight "three-in-a-row" combinations.
75             *
76             * 273 84
77             * \ /
78             * 1 | 2 | 4 = 7
79             * -----+-----+-----
80             * 8 | 16 | 32 = 56
81             * -----+-----+-----
82             * 64 | 128 | 256 = 448
83             * =================
84             * 73 146 292
85             *
86             */
87             wins = [7, 56, 448, 73, 146, 292, 273, 84],
88              
89             startNewGame = function () {
90             var i;
91            
92             turn = "X";
93             score = {"X": 0, "O": 0};
94             moves = 0;
95             for (i = 0; i < squares.length; i += 1) {
96             squares[i].firstChild.nodeValue = EMPTY;
97             }
98             },
99              
100             win = function (score) {
101             var i;
102             for (i = 0; i < wins.length; i += 1) {
103             if ((wins[i] & score) === wins[i]) {
104             return true;
105             }
106             }
107             return false;
108             },
109              
110             set = function () {
111             if (this.firstChild.nodeValue !== EMPTY) {
112             return;
113             }
114             this.firstChild.nodeValue = turn;
115             moves += 1;
116             score[turn] += this.indicator;
117             if (win(score[turn])) {
118             alert(turn + " wins!");
119             startNewGame();
120             } else if (moves === 9) {
121             alert("Draw!");
122             startNewGame();
123             } else {
124             turn = turn === "X" ? "O" : "X";
125             }
126             },
127              
128             play = function () {
129             var indicator = 1;
130             $('#tictactoe tr').each( function () {
131             var row = new Array;
132             $.each( this.cells, function () {
133             this.indicator = indicator;
134             this.onclick = set;
135             squares.push( this );
136             indicator += indicator;
137             });
138             });
139              
140             startNewGame();
141             };
142              
143             if (typeof window.onload === "function") {
144             oldOnLoad = window.onload;
145             window.onload = function () {
146             oldOnLoad();
147             play();
148             };
149             } else {
150             window.onload = play;
151             }
152              
153             }());
154             END_JAVASCRIPT
155             }
156              
157             =head1 NAME
158              
159             Spreadsheet::HTML::Presets::TicTacToe - TicTacToe board implemented with Javascript and HTML tables.
160              
161             =head1 DESCRIPTION
162              
163             This is a container for L preset methods.
164             These methods are not meant to be called from this package.
165             Instead, use the Spreadsheet::HTML interface:
166              
167             use Spreadsheet::HTML;
168             my $generator = Spreadsheet::HTML->new;
169             print $generator->tictactoe;
170              
171             # or
172             use Spreadsheet::HTML qw( tictactoe );
173             print tictactoe();
174              
175             =head1 METHODS
176              
177             =over 4
178              
179             =item * C
180              
181             Generates a tictactoe game board implemented with an HTML table
182             and Javascript. Intended for two human players but plan to
183             implement a computer opponent.
184              
185             =back
186              
187             =head1 SEE ALSO
188              
189             =over 4
190              
191             =item L
192              
193             The interface for this functionality.
194              
195             =item L
196              
197             More presets.
198              
199             =back
200              
201             =head1 AUTHOR
202              
203             Jeff Anderson, C<< >>
204              
205             =head1 LICENSE AND COPYRIGHT
206              
207             Copyright 2017 Ray Toal (Javascript) and Jeff Anderson (Perl).
208              
209             This program is free software; you can redistribute it and/or modify it
210             under the terms of the the Artistic License (2.0). You may obtain a
211             copy of the full license at:
212              
213             L
214              
215             Any use, modification, and distribution of the Standard or Modified
216             Versions is governed by this Artistic License. By using, modifying or
217             distributing the Package, you accept this license. Do not use, modify,
218             or distribute the Package, if you do not accept this license.
219              
220             If your Modified Version has been derived from a Modified Version made
221             by someone other than you, you are nevertheless required to ensure that
222             your Modified Version complies with the requirements of this license.
223              
224             This license does not grant you the right to use any trademark, service
225             mark, tradename, or logo of the Copyright Holder.
226              
227             This license includes the non-exclusive, worldwide, free-of-charge
228             patent license to make, have made, use, offer to sell, sell, import and
229             otherwise transfer the Package with respect to any patent claims
230             licensable by the Copyright Holder that are necessarily infringed by the
231             Package. If you institute patent litigation (including a cross-claim or
232             counterclaim) against any party alleging that the Package constitutes
233             direct or contributory patent infringement, then this Artistic License
234             to you shall terminate on the date that such litigation is filed.
235              
236             Disclaimer of Warranty: THE PACKAGE IS PROVIDED BY THE COPYRIGHT HOLDER
237             AND CONTRIBUTORS "AS IS' AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES.
238             THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
239             PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED TO THE EXTENT PERMITTED BY
240             YOUR LOCAL LAW. UNLESS REQUIRED BY LAW, NO COPYRIGHT HOLDER OR
241             CONTRIBUTOR WILL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, OR
242             CONSEQUENTIAL DAMAGES ARISING IN ANY WAY OUT OF THE USE OF THE PACKAGE,
243             EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
244              
245             =cut
246              
247             1;