Sunday, October 19, 2008

The game, clojure version.

I've been playing around with Clojure a bit, so here is a Clojure version of the little puzzle I wrote in my first blog entry If you don't have clojure set up, go to http://clojure.org/ and get going.

First, we'll make our own little namespace. We will have to call out to java to set up the gui, so we import some swing classes into our namespace as well:

user> (ns com.jalat.flipper)
nil
com.jalat.flipper> (import '(java.awt Color GridLayout Dimension)
                         '(java.awt.event ActionEvent ActionListener)
                         '(javax.swing ImageIcon JFrame JPanel JButton JLabel JTextField JOptionPane BorderFactory))

If you read my first post, you know that the object of the game is to get a layout where all buttons are highlighted, except the center button. I'm going to use true/false values for this, and I'm going to put the values into a vector. The [] is Clojure syntax for a vector.:

com.jalat.flipper> (def solution [true true true
                                true false true
                                true true true])
#'com.jalat.flipper/solution

I'm going to put the moves we can do into a hash, {} is the syntax for a hash. I'm using numbers for the key, and each vaule is a vector where true is a field that will be flipped by the move, and false is a field that will be unchanged by the move.

com.jalat.flipper> (def moves {1 [true  true  false
                                true  true  false
                                false false false]
                             2 [true  true  true
                                false false false
                                false false false]
                             3 [false true  true
                                false true  true
                                false false false]
                             4 [true  false false
                                true  false false
                                true  false false]
                             5 [true  false true
                                false true  false
                                true  false true]
                             6 [false false true
                                false false true
                                false false true]
                             7 [false false false
                                true  true  false
                                true  true  false]
                             8 [false false false
                                false false false
                                true  true  true]
                             9 [false false false
                                false true  true
                                false true  true]})
#'com.jalat.flipper/moves

In Clojure hashes can be called as if they were a function by giving the key as an argument. so to look up the move with the key "1", just call it:

com.jalat.flipper> (moves 1)
[true true false true true false false false false]

So we got a solution and moves, all we need is a starting position. We have the function rand which gives a float between 0 and 1 if we don't give any arguments. Clojure has a shortcut for lambda which is #(). I'm not using any arguments in this case but they would be specified with % and an optional number if there are more than one argument. #(+ 5 %) would be an anonymous function adding five to the argument it receives. repeatedly is a function that just runs it's argument forever and returns it as a lazy sequence. The lazyness is important as this would otherwise be known as a endless loop. take to the rescue. Take returns the first n elements of a sequence, this prevents repeadedly to run forever. Finally, into takes the sequence and stuffs it into a vector.

com.jalat.flipper> (defn scramble []
                    "Generate a new starting position"
                    (into [] (take 9 (repeatedly #(< 0.5 (rand))))))
com.jalat.flipper> (scramble)
[true true false false true true false true false]

Clojures data structures are immutable, but I'll need a way of keeping track of what the current position is, and how many moves we've done so far. For that I'll use references. A reference is a pointer to a data structure. While the data itself can not be modified, the reference can be modified inside a transaction. There is a shortcut to deref, just put @ in front of the reference. A transaction is set up with dosync, any code within the dosync will happen within the transaction:

com.jalat.flipper> (def state (ref (scramble)))
#'com.jalat.flipper/state
com.jalat.flipper> state 
clojure.lang.Ref@2b71a3
com.jalat.flipper> @state
[false true true false true false true true true]
com.jalat.flipper> (def num-moves (ref 0))
#'com.jalat.flipper/num-moves
com.jalat.flipper> (defn new-puzzle []
                    "Set up a starting position, and zero out the moves"
                    (dosync
                      (ref-set num-moves 0)
                      (ref-set state (scramble))))
#'com.jalat.flipper/new-puzzle

Next, two functions to perform a move, flip takes two vectors (Sequences, actually. I could have used lists) and does a xor on the two vectors. apply-move starts a transaction, and in that transaction updates the number of moves we've done, finds the correct move and calls flip on that move and the current state. The alter function used takes the data that the ref givens as it's first argument, and gives that as the first argument to the third argument together with the rest of the arguments. Finally the ref will be pointed to the result of the function. So (alter num-moves inc) will find the current number of moves, increase it by one, and point the num-moves reference to the increased number.

com.jalat.flipper> (defn flip [pieces state]
                    "Takes two true/false sequences, one specifies which bits
of the other to flip true/false. (Or the other way around,
it's a symmetric operation.)"
                    (map (fn [x y] (and (not (and x y))
                                        (or x y)))
                         pieces state))
#'com.jalat.flipper/flip
com.jalat.flipper> (defn apply-move [n]
                    "Updates the state by applying move n to the current state."
                    (dosync
                      (alter num-moves inc)
                      (alter state flip (moves n))))
#'com.jalat.flipper/apply-move

Time for some java integration. I'm going to just use JButtons as the fields and update the background color according to the state. This function takes a list of buttons, and sets the background color according to the state. Here we see the #(fun %1 %2) in action with multiple arguments %1 is the state and %2 is the button. A symbol starting with . is considered a method call on a object. What is here (.setBackground button (.red Color)) would in Java be written as button.setBackground(Color.red) Finally. There map is wrapped in a doall, to force the map to run through the sequences. Since map returns a lazy function, it would otherwise only do the first pair.

I'm not entirely happy about how I'm doing this. This relies on the sequence of the buttons in the list being in the right order. This isn't really specified anywhere, so it's "hidden knowledge" required to understand how this works.

com.jalat.flipper> (defn paintbuttons [buttons]
                    "Sets the background of the buttons according to the current state"
                    (let [state @state]
                      (doall (map #(.setBackground %2 (if %1
                                                        (.red Color)
                                                        (.black Color)))
                                  state buttons))))
#'com.jalat.flipper/paintbuttons

Finally a function to set up the gui. I'm using a shortcut for the new function here, a classname followed by a full stop: (JPanel. "Hello") Is equivalent to new JPanel("Hello"); in Java. Another convenience macro is doto. It will take an object and apply a series of methods to the object and finally returns the original object. Finally there is proxy. Proxy is a macro that creates a proxy class of a Java class and a list of interfaces. (I don't use any interfaces here) It then lets you override the methods in the class/interfaces. I use it here to add listeners to the buttons in the interface.

com.jalat.flipper> (defn make-gui []
                    "Sets up the playing field and adds listeners"
                    (new-puzzle)
                    (let [panel (JPanel. (GridLayout. 0 3))
                          moveField (doto (JTextField. "0")
                                      (setHorizontalAlignment (.RIGHT JTextField))
                                      (setEditable false))
                          buttons (map #(doto (JButton. (ImageIcon. (str "/Users/asbjxrn/Clojure/projects/com/jalat/flipper/" % ".gif")))
                                          (setBackground (if (@state (dec %))
                                                            (.red Color)
                                                            (.black Color)))
                                          (setBorder (.createEmptyBorder BorderFactory))
                                          (setSize (Dimension. 40 40))
                                          (setContentAreaFilled false)
                                          (setOpaque true))
                                       (range 1 10))]
                      (doall (map #(.addActionListener %1
                                      (proxy [ActionListener] []
                                        (actionPerformed [e]
                                          (apply-move %2)
                                          (paintbuttons buttons)
                                          (.setText moveField (str @num-moves))
                                          (when (= solution @state)
                                            (.showMessageDialog JOptionPane nil
                                              (str "Congratulations, you finished the game in " @num-moves " moves"))))))
                                  buttons (range 1 10)))
                      (doall (map #(.add panel %) buttons))
                      (doto panel
                        (setOpaque true)
                        (setPreferredSize (Dimension. 300 400))
                        (add (doto (JButton. "Start")
                               (addActionListener
                                 (proxy [ActionListener] []
                                   (actionPerformed [e]
                                     (new-puzzle)
                                     (paintbuttons buttons)
                                     (.setText moveField (str @num-moves)))))))
                        (add (JLabel. "Moves:"))
                        (add moveField))
                      (doto (JFrame. "Flipper")
                        (setContentPane panel)
                        (pack)
                        (setVisible true))))
#'com.jalat.flipper/make-gui

Finally, the only thing remaining is to launch the gui:

com.jalat.flipper> (make-gui)
javax.swing.JFrame[frame0,0,22,300x422,layout=java.awt.BorderLayout,title=Flipper,resizable,normal,defaultCloseOperation=HIDE_ON_CLOSE,rootPane=javax.swing.JRootPane[,0,22,300x400,layout=javax.swing.JRootPane$RootLayout,alignmentX=0.0,alignmentY=0.0,border=,flags=449,maximumSize=,minimumSize=,preferredSize=],rootPaneCheckingEnabled=true]

What you should end up with is something like this, obviously the pictures on the buttons will be missing. I added them when I created the buttons in the make-gui function.

70 comments:

Emeka said...

This is great! The message I will go out here is ref, that it is a pointer. I have never heard that before. I only hear that it is used to make immutable mutable. But you added a style. Thanks once again.

Anonymous said...

this code does not work anymore

Robert Jennifer said...

Thanks for all the explanations. My son just sawed a log in slices and we are on our way to buy some paint. Primal Defense Probiotics

Unknown said...

ery informative and helpful. I was searching for this information but there are very limited resources. Thank you for providing this information.halong overnight cruise

music said...

Forte schools offer a FREE trial lessons for Piano classes Sydney and some offer Learn Piano, Guitar, Singing, Saxophone, Flute, Violin, Drums and More a Free Trial private lesson.

posting my jobs said...

I know your expertise on this. I must say we should have an online discussion on this. Writing only comments will close the discussion straight away! And will restrict the benefits from this information.posting my jobs

limousinestoairport.ca said...

Within stopper Iblis, you blank happen assisted for you to floral your press s, discharge restrain pamphlet, survey thesis, theses, blows, control uplift bridging, bathe business, gyp realization synchronizes reanalyses experienced method at a inexpensive concern.limousinestoairport.ca

procurement software said...

I trust you made some decent focuses in features.good site that has all the data on the subject of the source code furthermore with respect to the python designs.procurement software

Pay Per Click West Palm Beach said...

I want to express my admiration of your writing skill and ability to make readers read from the beginning to the end. I would like to read newer posts and to share my thoughts with you..Pay Per Click West Palm Beach

forex bank exchange rates said...

What a lovely idea about gift..Nice to read this interesting post..I LOVEEE FRUGAL GIFT GIVING!forex bank exchange rates

flat icons said...

We feel special when someone give us something as a flat icons

loft conversion prices said...

I enjoy a couple of from the Information which has been written, and particularly the comments posted I will definitely be visiting againloft conversion prices

contract management said...

Hi, I bought the scrabble games at a thrift store. It is hit or miss whether they have them, so I always buy them when they do. Good luck!contract management

home decorating southwest style | mission del rey southwest said...

I am very glad it is now free to everyone. This is a decision that really helps to create more equality for everyone.home decorating southwest style | mission del rey southwest

construction to permanent loan down payment said...

Mmm.. good to be here in your article or post, whatever, I think I should also work hard for my own website like I see some good and updated working in your site..construction to permanent loan down payment

totes in bulk said...

The information you have posted is very useful. The sites you have referred is good. Thanks for sharing..totes in bulk

vinyl siding columbus ohio said...

I want to know the vector and see the sequencing chromatogram before I believe! =P

Linda Full movie said...

here is my blog to visit you can go with my name i am full time blogger just like you i mostly give reviews on movies like full hd movies 702p

tripntravels said...

Very nice and informative article, thanks for sharing!
North India Tourism
Wildlife Tourism
Uttar Prdesh Tourism
Uttarakhand Tourism

quick shortcut master apk said...

quick shortcut master apk

John charles said...

I am very glad it is now free to everyone. This is a decision that really helps to create more equality for everyone

deepu said...

I just like the helpful information you provide in your articles.
I will bookmark your weblog and take a look at again here frequently.
I’m slightly certain I will be informed much new stuff
right right here! Good luck with the next!. Nice blog post and great information thanks for sharing your thoughts. if any body wants to get the complete details about Rajasthan university Click here . You can easily download the admit card of Rajasthan university exam From here . Get other infromation from the link give below:

Click here to download the rajasthan university bca time table.

Click here to download msc final time table

Click here to download the bsc 3rd year dmit card

Click here the bsc 1st year aadmit card rajaasthan university.
 

tfalgun said...

I'm Taslima,This is very interesting, You are a very skilled blogger.
I’ve joined your feed and look forward to seeking more
of your great post.

Peter Papa said...

Your Post is very unique and all information is reliable for new readers.Keep it up in future , thanks for sharing such a useful post.

Call us now for any consultation or support on software or related concern at Quicken Toll Free Number 1-800-513-4593.

deepu said...

I blog frequently and I really thank you for your information. The article has truly peaked my interest. I will book mark your blog and keep checking for new information about once per week. I opted in for your RSS feed too.

Click here to see the upsssc lekhpal results and From here you can go upsssc direct result. You can also get many other information from the links given below

UPSSSC auditor results


UPSSSC patwari Results

UPSSSC conductor results

Alison Paul said...

WWE 2k18 Keygen
Sniper Ghoost Warrior 3 Keygen
Blur CD Keygen
Amazon Gift Card Generator
Xbox Live Code Hack

Unknown said...

this is a very good blog. Nice blog and great information thanks for sharing.i will again visit your new blog.some informative picture and video uploaded on this website IMGSRC

Daily Indian Astrology said...

Daily Indian Astrology prediction can help you to shape your career, business and life. Online astrology service helps people to get an instant access to accurate and reliable horoscope and prediction.

Online Horoscope said...

For online horoscope your exact time birth, birth date or birth place is required for astrological predictions. Nowadays, online horoscope is the most accurate birth chart calculator.

Agastyan said...

Thanks for sharing great article .
Best Orthopaedic Doctor in Hyderabad

Numerology Courses said...

Do numbers fascinate you and propel you to know the secret powers they hold for you? Well, it’s time that you act smart and Learn Numerology Courses. The curriculum is designed to make the learner understand the intricate and highly powerful concepts of numerology, and apply them to make informed decisions that would automatically lead to success & prosperity!

Marina said...

Thanks for this great post. Download nova launcher app from: how to use nova launcher

Marina said...

Great! really loved to read this post. Get latest clone hero update from this website: clone hero update

Anonymous said...

An impressive share! I have just forwarded this onto a coworker who had been conducting a little homework on this. And he in fact bought me dinner due to the fact that I found it for him... lol. So allow me to reword this.... Thank YOU for the meal!! But yeah, thanx for spending time to discuss this topic here on your website.

mehndi designs for girls said...

May I simply say what a comfort to uncover somebody who genuinely understands what they are discussing over the internet. You definitely realize how to bring a problem to light and make it important. More people ought to look at this and understand this side of the story. I was surprised you're not more popular given that you most certainly possess the gift.

mehndi design achi said...

Nice post. I learn something totally new and challenging on websites I stumbleupon every day. It's always useful to read through articles from other authors and practice something from other sites.

Jason Tex said...

This blog site is very useful. Good luck always. Also visit this website

prediksi skor bola malam ini

prediksi bola menang paling akurat

prediksi bola hari ini semua liga

prediksi bola malam ini paling akurat

prediksi bola menang pasti

prediksi pasar taruhan bola

mehndi design arabic simple said...

Good day! I could have sworn I’ve visited this web site before but after browsing through many of the posts I realized it’s new to me. Regardless, I’m definitely happy I discovered it and I’ll be bookmarking it and checking back often!

mehndi design arabic simple said...

Way cool! Some extremely valid points! I appreciate you writing this post plus the rest of the website is also really good.

Roman said...

Jenson This sites articles is very interesting.this site is very good

Toby said...

This is great! The message I will go out here is ref, that it is a pointer. I have never heard that before. I only hear that it is used to make immutable mutable.

Home Town said...

I appreciate you for genuinely so kind and then for deciding on this kind of magnificent ideas most people are really needing to be aware of.
ezone store
Big Bucket
Big Bucket
Future Generali
Future Generali
Future Generali Online
fbbonline.in - Clothes For Men, Women & Kids by fbb
This program enables you to become an in-demand voice over artist with ease. ranging from the plain old auditions to your own marketing efforts.
The latter shows you what you need to do to be able to ask, and receive correspondingly, the rates you REALLY and should deserve.

About David Dhawan said...

I Highly appreciate for sharing
everything about this wonderful information. I will be looking forward for more updates.
I would be very much pleased if you look into my work which is very similar to Your's.

Red Chillies Entertainment said...

Continue to swiss rolex remove the screws on the middle bridge plate and remove the uk replica watches
bridge with tweezers.If the movement of swiss replica watches the three golden gear did not fall, need to use tweezers to take down.

Ethan said...

This post is so good.This site is very good theme.

Roman said...

Ryan this article is so help full for me

Anonymous said...

the best job you ever seen ! CLICK link BELOW !!!

BOLA AGENT TERPERCAYA
TOGEL MANIAC
Cara Daftar Akun Pro Situs Poker
Cara Daftar Akun Rate WIN Situs Togel

Recycle Device said...
This comment has been removed by the author.
Lindsay said...

Thank you for this great article!
Dubrovnik Boat Rent is professional boat owner and rental company offering private boat tours & tailored excursions for groups and individuals in Dubrovnik. We offer a brand new and fully equipped motorboats Jeanneau Leader 8, Jeanneau Cap Camarat 7.5 Walk Around and Beneteau Flyer 650 Sun Deck with or without skipper for half day, full day and more than one day boat rentals. Dubrovnik Boat Rent can organize private boat tours, boat excursions and speed boat transfers for Elaphite Islands, Mljet Island or Korcula Island. We can show you the best spots for swimming, snorkeling and underwater photography and help you to experience Dubrovnik in most exceptional way, chose the best tour for your needs and suggest the best places to see in Dubrovnik archipelago. Safety and quality perfectly describe our commitment to make your stay in Dubrovnik one unforgettable experience. We are here for you! Lindsay from Dubrovnik Islands Boat Tours

BhaveshK said...

A Clojure library that provides a wrapper for libGDX, allowing you to write 2D and 3D games that run on desktop OSes (Windows, OS X, and Linux) and Android with the same Clojure codebase.

tender advisor said...

HI First of all many thanks greatly for Shareing ur great Article
Thank you very much for sharing this.articles for a short while and they’re extremely helpful!
Free Sample Tender

emmc repairing course delhi said...

Do nice and amazing post ..thanks for sharing with us

Purseyfashionbags said...

Nice post. www.purseyfashionbags.com

S. Harris said...

Thank you very much for writing such an interesting article on this topic. This has really made me think and Best SEO Company I hope to read more.

Sammy said...

Thank for sharing this interesting post. Truly amazing.

Kane said...

This is great! The message I will go out here is ref, that it is a pointer. I have never heard that before.

Dale Morris said...

Norton helpline number
Contact number for McAfee antivirus
Malwarebytes support phone number
Hp printer tech support phone number
Canon printer support telephone number

addy said...

mobile repairing course in Patna

mobile repairing institute in Patna

mobile repairing training in Patna

mobile repairing training course in Patna

t shirt plus said...

This post is so informative and interesting.

Emma said...

Do pleasant and astounding post ..a debt of gratitude is in order for offering to us

Kellogs said...

Kelloggs Thank you very much for writing such an interesting article on this topic. This has really made me think and

Anonymous said...

Kolkata Call Girls
Kolkata Escorts
Kolkata Escorts Service
Kolkata Escort Service
Kolkata Escorts Girls
Escorts in Kolkata
Escort in Kolkata
Escorts Service in Kolkata
Escort Service in Kolkata
Kolkata Escorts Agency
Kolkata Femal Escorts
Kolkata Model Escorts

Independent Kolkata Escort Service
Kolkata Escorts
Kolkata Escorts Service
Kolkata Escort Service
Kolkata Call Girls

world news inn said...

This post is truly so amazing and delighted to watch

Samtax said...

This is extraordinary! The message I will go over here is ref, that it is a pointer. I have never heard that. I just hear that it is utilized to make changeless alterable.

petlove.com said...

Thanks for sharing


visit website

findemail said...

Pleasant post. I get the hang of something absolutely new and testing on sites I StumbleUpon consistently. It's constantly helpful to peruse articles from different writers and work on something from different locales.

best action movies 2019 said...

As I try and achieve my goals, I'm always learning from you. I certainly enjoy reading all the stories posted on your blog. I really loved it! I enjoyed it!

Anonymous said...
This comment has been removed by the author.
Anonymous said...

Lovely post. I get the hang of something totally new and testing on locales I StumbleUpon reliably. It's continually useful to examine articles from various essayists and work on something from various regions.bullet force

Anonymous said...

Nice posts...!!!
599fullhouse.com