Peter’s solutions: week 104 — 15 March 2021
THE WEEKLY CHALLENGE
FUSC and NIM
Write a script to simulate the Nim Game. It is played between 2 players. For the purpose of this task, assume you play against the machine.
There are 3 simple rules to follow:
I've coded this in Perl with output in HTML. This means that the screen is reloaded for each play: a trivial matter in today's world, but if I were doing this for real I'd probably code the guts in JScript so that only one page load was needed per game.
The logic is quite simple and the machine behaves fairly predictably, although there is a random element.
Try it and see if you can win!
#!/usr/bin/perl # Blog: http://ccgi.campbellsmiths.force9.co.uk/challenge use v5.26; # The Weekly Challenge - 2021-03-15 use utf8; # Week 104 - task 2 - Nim game use warnings; # Peter Campbell Smith use Encode; require './pwc_utils.pl'; our ($base, %data, $date, $root); my ($s, @colours, $col, $gone, $e, $tokens, $start, $scores, $starts, $my_take, $messages); # standard start pwc_start(); $messages = ''; # page heading page_begin({title => 'The Weekly Challenge', description => 'The Weekly Challenge', styles => '', heading => qq[The Weekly Challenge], line1 => 'The game of Nim'}); # top stuff say qq[<div style='margin:0 1em 0 1em'> <div style='float:right;width:20em' class='this'> <p style='text-align:right; margin-top:1em'> <a href='/challenge'>Current week →</a></div> <div style='clear:both'></div>]; # left column say qq[<div style='float:left; width:49%; min-width:300px;'> <p><form action='?' method='post'>]; # restart game or series $data{news} = 1 unless defined $data{tokens}; $starts = 1 - $data{starts} if $data{newg}; if ($data{newg} or $data{news}) { $tokens = 12; if ($data{news}) { $scores = qq[0v0]; } else { $scores = $data{scores}; } $messages .= '' . ($starts == 1 ? '<p>Your' : '<b>My') . ' turn to start'; } else { $starts = $data{starts}; $tokens = $data{tokens}; $scores = $data{scores}; } # apply your play if ($data{take} =~ m|(\d)|) { $tokens -= $1; $messages .= qq[<p>You took $1]; } if ($tokens == 0) { $messages .= qq[<p style='color:green'>Well done, you win!]; $scores =~ m|(\d+)v(\d+)|; $scores = $1 . 'v' . ($2 + 1); # make my play (unless it's you to start) } else { unless ($starts == 1 and $tokens == 12) { # 1 2 3 4 5 6 7 8 9 10 11 $my_take = (0, 1, 2, 3, 1, 1, 2, 3, 1, 2, 3, 1)[$tokens]; $my_take = int(rand(3)) + 1 if $tokens == 12; $tokens -= $my_take; $messages .= qq[<p>I've taken $my_take]; } if ($tokens <= 0) { $messages .= qq[<p style='color:red'>Bad luck, you lose!]; $scores =~ m|(\d+)v(\d+)|; $scores = ($1 + 1) . qq[v$2]; } } # scoreboard $scores =~ m|(\d+)v(\d+)|; say qq[<table style='border:0; width:80%; text-align:center; font-size:20pt; color:white; font-weight:bold; background:gray;'> <tr><td colspan=2>SCOREBOARD</td></tr> <tr><td>YOU</td><td>ME</td></tr> <tr><td>$2</td><td>$1</td></tr></table>]; say qq[<span style='font-weight:bold'><br>$messages</span>] if $messages; # show tokens say qq[<p><span style='font-size:30pt;font-weight:bold'>]; for $s (0 .. 11) { $col = $s <= $tokens - 1 ? 'red' : 'silver'; print qq[<span style='color:$col'>&#] . ($s + 9312) . ' </span>'; say q[<br>] if $s == 5; say qq[</span>] if $s == 11; } # invite play if ($tokens > 0) { say qq[<h2>Choose your move</h2> <p><input name='take' type='submit' value='Remove 1' style='width:10em'>]; say qq[<p><input name='take' type='submit' value='Remove 2' style='width:10em'>] if $tokens >= 2; say qq[<p><input name='take' type='submit' value='Remove 3' style='width:10em'>] if $tokens >= 3; # game over } else { say qq[<p><input name='newg' type='submit' value='New game' style='width:10em'>]; } say qq[<br> </div>]; # right column say qq[<div style='float:left; width:49%; min-width:300px;'> <h2>Rules</h2> <ul><li>Game starts with 12 tokens <li>Play alternates between you and me <li>Each play removes 1, 2 or 3 tokens <li>Person removing last token <b>wins!</b></ul> <h2>Options</h2> <p><input name='news' type='submit' value='Clear scoreboard' style='width:10em'> <p><b><a href='/challenge/104/2'>Go back to challenge</a></b> </div> <input type='hidden' name='tokens' value='$tokens'>]; # data pass on say qq[<input type='hidden' name='starts' value='$starts'> <input type='hidden' name='scores' value='$scores'> <input type='hidden' name='tokens' value='$tokens'> </form></div>]; page_end();
88 lines of code
Completed after the closing date and not submitted to GitHub
Any content of this website which has been created by Peter Campbell Smith is in the public domain