Generate Bingo Cards In Many Programming Languages

Here's some programs to generate BuzzwordBingo cards for everyone in your group. We use different buzzwords depending on what kind of meeting we're going to; the examples shown use words for Marketing.


MicrosoftWord Macro

 Option Explicit

Private Const USE_WILD = True

Private Const NO_WILD = False

Public Sub MarketingBingoCard()

Const Count = 25 Dim Words(Count) As String

Words(1) = "Synergy" Words(2) = "Strategic Fit" Words(3) = "Gap Analysis" Words(4) = "Best Practice" Words(5) = "Bottom Line" Words(6) = "Revisit" Words(7) = "Bandwidth" Words(8) = "Hardball" Words(9) = "Out of the Loop" Words(10) = "Benchmark" Words(11) = "Value-Added" Words(12) = "Proactive" Words(13) = "Win-Win" Words(14) = "Think Outside the Box" Words(15) = "Fast Track" Words(16) = "Result-Driven" Words(17) = "Empower [or] Empowerment" Words(18) = "Knowledge Base" Words(19) = "Total Quality [or] Quality Driven" Words(20) = "Touch Base" Words(21) = "Mindset" Words(22) = "Client Focus[ed]" Words(23) = "Ball Park" Words(24) = "Game Plan" Words(25) = "Leverage"

MakeBingoCard Words(), NO_WILD

End Sub

Private Sub MakeBingoCard(ByRef Words() As String, UseWild As Boolean)

Dim myRange As Range Set myRange = ActiveDocument.Range(Start:=ActiveDocument.Range().End - 1, End:=ActiveDocument.Range().End - 1) ActiveDocument.Tables.Add Range:=myRange, NumRows:=5, NumColumns:=5

Dim i As Integer Dim j As Integer Dim Count As Integer Count = UBound(Words)

Randomize

For i = 1 To 5

ActiveDocument.Tables(1).Rows(i).Height = 64

For j = 1 To 5

Dim Word As String Word = ""

If UseWild And i = 3 And j = 3 Then Word = "*WILD*" Else Do While Len(Word) = 0 Dim WordIndex As Integer WordIndex = Int((Count * Rnd) + 1) If Len(Words(WordIndex)) > 0 Then Word = Words(WordIndex) Words(WordIndex) = "" End If Loop End If

With ActiveDocument.Tables(1).Cell(i, j) .Range.InsertAfter Word .Range.Font.Name = "Arial" .Range.Font.Size = 12 .VerticalAlignment = wdCellAlignVerticalCenter .Range.ParagraphFormat.Alignment = wdAlignParagraphCenter End With

Next j Next i

End Sub


RubyLanguage

 # create a shuffled word list, including wild padding to fill holes
 words = ["Synergy","Strategic Fit","Gap Analysis","Best Practice","Bottom Line",
 "Revisit","Bandwidth","Hard Ball","Out of the Loop","Benchmark",
 "Value-Added","Proactive","Win-Win","Think Outside the Box","Fast Track",
 "Result Driven","Empower","Knowledge Base","Total Quality","Mindset",
 "Client Focus[ed]","Ball Park","Game Plan","Leverage","Utilize",
 "Irregardless","Self-Starter"]
 numberOfColumns = 5
 (numberOfColumns - words.size()%numberOfColumns).times { words << "Wild!"}

#thanks to http://wiki.rubygarden.org/Ruby/page/show/ArrayShuffle class Array def shuffle each_index {|j| i = rand(size-j); self[j], self[j+i] = self[j+i], self[j]} end end srand = Time.now.to_i #seems to be a good enough seed words.shuffle

#come up with some lines and values to make the table print cleanly columnWidth = 0 words.each{|word| if( word.length > columnWidth) then columnWidth = word.length end } totalPadding = 2 columnWidth = columnWidth + totalPadding header = "." footer = "'" midline = " " numberOfColumns.times { columnWidth.times { header << "-" footer << "-" midline << "-" } header << "." footer << "'" midline << " " }

# create the card File.open("bingoCard.txt","w") do |outFile| columnCount = 0

outFile << header << "\n"

#prints the word, along with horizontal padding and separators words.each {|word| if(5 <= columnCount) outFile << "|\n" outFile << midline << "\n" columnCount = 0 end needToFill = columnWidth - word.length leftFill = needToFill/2 rightFill = leftFill + (needToFill%2)

outFile << "|" leftFill.times{ outFile << " " } outFile << "#{word}" rightFill.times{ outFile << " " }

columnCount = columnCount + 1 }

outFile << "|\n" << footer end
Small differences include using Wild! as a filler, rather than optional. This allows wordlists to be of 'unaligned' size. I didn't bother with vertical pretty printing, so I shaved some buzzword names.

Even this small task kept hitting me over the head with CreepingFeaturitis (especially prettier printing and word list management) and the urge to further generalize and objectify. Doctor Yagni, I need a pill, please.

Why *that* shuffle? I love sort_by{rand} :)

sort_by{rand} is nicer. I'm still getting used to Ruby and didn't know that was an option. I even missed the giant notice at the top of the page explaining the sort I did use trying to educate me about about sort_by{rand}. Oh, and anyone who lets the browser do the table layout for them is a pansy ;)


A nicer, more idiomatic RubyLanguage script:

 WORDS = [
 "Synergy",         "Strategic Fit",        "Gap Analysis",      "Best Practice",
 "Bottom Line",     "Revisit",              "Bandwidth",         "Hard Ball",
 "Out of the Loop", "Benchmark",            "Value-Added",       "Proactive",
 "Win-Win",         "Think Outside the Box","Fast Track",        "Result Driven",
 "Empower",         "Knowledge Base",       "Total Quality",     "Mindset",
 "Client Focus[ed]","Ball Park",            "Game Plan",         "Leverage",
 "Utilize",         "Irregardless",         "Self-Starter",
 ]

COLUMNS = 5

words = WORDS.dup words << "Wild!" until (words.size % COLUMNS).zero? words = words.sort_by { rand }

pad = words.map { |w| w.size }.max + 2 words.map! { |w| w.center pad }

def seperator(pad, string) string + Array.new(COLUMNS) { "-" * pad }.join(string) + string end

head = seperator pad, "." line = seperator pad, " " foot = seperator pad, "'"

puts head (words.size / COLUMNS).times { |a| puts line unless a.zero? print "|" COLUMNS.times { |b| print words[COLUMNS*a + b], "|" } puts } puts foot

Should output the same as above Ruby script.


This seems like a good candidate for DivisionOfLabor. The following PerlLanguage script produces HyperTextMarkupLanguage. I mussed with this for List::Util::shuffle.

 #!/usr/bin/perl                                                        
 use List::Util qw(shuffle);                                            

open(WORDS, "bingo.dat") || die("Can't open bingo.dat"); @allwords = <WORDS>; close(WORDS);

$rows = 5; $cols = 5;

@shuffled = shuffle(@allwords);

sub getword { $word = pop(@shuffled); chomp($word); $word; }

print "<table border=1>\n";

for (1..$rows) { print " <tr>\n"; for(1..$cols) { my $word = getword(); print " <td align=center width=100 height=100>$word</td>\n" } print " </tr>\n"; }

print "</table>\n";


PythonLanguage:

 import random
 import os

class CardMaker(object): # Tweaked so that it will fit in 80 columns... words = ["Synergy", "Strategic Fit", "Gap Analysis", "Best Practice", "Bottom Line", "Revisit", "Bandwidth", "Hardball", "The Loop", "Benchmark", "Value-Add", "Proactive", "Win-Win", "Think Big", "Fast Track", "Result-Driven", "Empower", "Knowledge Base", "Total Quality", "Touch Base", "Mindset", "Client Focus", "Ball Park", "Game Plan", "Leverage"] maxlen = max([len(w) for w in words]) row = "|" + ("%%%ss|"%maxlen)*5 +"\n" spacer = "+" + ("-"*maxlen + "+")*5 + "\n" template = (spacer + row)*5 + spacer

def __call__(self, use_wild=False, template=None): if not template: template = self.template words = self.words[:] random.shuffle(words) if use_wild: words[12] = "*WILD*" return template % tuple(words)
Quick and dirty usage examples - may need to fix file paths:
 def make_one_file():
    make_card = CardMaker()
    people = ["John", "Jane", "Sally", "Mark"]
    f = open("C:/bingo.txt", "w")
    for person in people:
        print>>f, "%s:"%person
        print>>f, make_card(use_wild=True)
 make_one_file()

def make_one_webpage(): row = "<tr>" + "<td align=center width=100 height=100>%s</td>"*5 + "</tr>" template = "<HTML><table border=1>" + row*5 + "</table>"+"</HTML>"

make_card = CardMaker() print>>open("C:/bingo.htm", "w"), make_card(template=template) make_one_webpage()


CommonLisp:

 (use-package :com.gigamonkeys.html)

(defparameter *phrases* #("Synergy" "Strategic Fit" "Gap Analysis" "Best Practice" "Bottom Line" "Revisit" "Bandwidth" "Hardball" "Out of the Loop" "Benchmark" "Value-Added" "Proactive" "Win-Win" "Think Outside the Box" "Fast Track" "Result-Driven" "Empower [or] Empowerment" "Knowledge Base" "Total Quality [or] Quality Driven" "Touch Base" "Mindset" "Client Focus[ed]" "Ball Park" "Game Plan" "Leverage"))

(defun randomize (vector) (loop for i from (length vector) downto 1 do (rotatef (aref vector (1- i)) (aref vector (random i)))) vector)

(defun print-bingo-card (phrases row-length) (when (< (length phrases) (expt row-length 2)) (error "Only received ~S phrases. Need at least ~S." (length phrases) (expt row-length 2))) (html (:html ((:table :border 1) (loop with index = 0 with random-phrases = (randomize (copy-seq phrases)) repeat row-length do (html (:tr (loop repeat row-length do (html ((:td :align :center :width 100 :height 100) (:format "~A" (svref random-phrases index)))) do (incf index)))))))))

(print-bingo-card *phrases* 5)
Things to keep in mind:


CeePlusPlus:

 #include <iostream>
 #include <fstream>
 #include <algorithm>
 #include <iterator>
 #include <string>
 #include <vector>
 using namespace std;

int main(int argc, char **argv){ vector<string> words; ifstream in("bingo.dat"); string line; while(getline(in, line)) words.push_back(string(line)); srand(time(0)); random_shuffle(words.begin(), words.end());

cout << "<html><head><title>Buzzword Bingo</title>" << endl << "<style>td { text-align: center; width: 6em; height: 6em; border: solid 2px black } </style>" << endl << "</head><body><table>" << endl;

for(int row = 0; row < 5; row++){ cout << "<tr>" << endl; for(int col = 0; col < 5; col++){ cout << "<td>" << (row == 2 && col == 2 ? "FREE" : words[row * 5 + col]) << "</td>" << endl; } cout << "</tr>" << endl; } cout << "</table></body></html>" << endl; }


OcamlLanguage:

     open Printf

let phrases = ["Synergy"; "Strategic Fit"; "Gap Analysis"; "Best Practice"; "Bottom Line"; "Revisit"; "Bandwidth"; "Hardball"; "Out of the Loop"; "Benchmark"; "Value-Added"; "Proactive"; "Win-Win"; "Think Outside the Box"; "Fast Track"; "Result-Driven"; "Empower[ment]"; "Knowledge Base"; "Total Quality"; "Touch Base"; "Mindset"; "Client Focus[ed]"; "Ball Park"; "Game Plan"; "Leverage"]

let max_phrase_length = (List.fold_left (fun max str -> let len = (String.length str) in if len > max then len else max) 0 phrases) + 3

let list_extract_nth list n = let rec continue list acc n = match n, list with (_, []) -> raise (Failure "nth") | (0, hd :: tl) -> (hd, (List.rev_append acc tl)) | (_, hd :: tl) -> continue tl (hd :: acc) (pred n) in continue list [] n

let shuffle list = let rec continue list acc n = match n with 0 -> acc | _ -> let i = (Random.int n) in let (elt, rest) = (list_extract_nth list i) in continue rest (elt :: acc) (pred n) in continue list [] (List.length list)

let matrix_of_list list x y = let array = Array.of_list list and matrix = Array.make x [||] in let _ = for i = 0 to x-1 do matrix.(i) <- Array.sub array (i*y) y done in matrix

let print_bingo use_wild width matrix = Array.iteri (fun i row -> begin Array.iteri (fun j cell -> begin let string = match (i, j, use_wild) with (2, 2, true) -> "*WILD*" | _ -> cell in printf "%*s" width string end) row; print_endline ""; end) matrix ;;

let _ = Random.self_init () in (print_bingo true max_phrase_length (matrix_of_list (shuffle phrases) 5 5))


See: CategoryInManyProgrammingLanguages, ProgrammingChrestomathy


EditText of this page (last edited February 11, 2007) or FindPage with title or text search