July 20th, 2024

Exercise: Minesweeper in 100 lines of Ruby

Radan Skorić implemented Minesweeper in 100 lines of Ruby code, emphasizing code reduction while maintaining readability. The implementation covers board generation, gameplay logic using Ruby features, and hints at future multiplayer functionality.

Read original articleLink Icon
ExerciseImplementationAppreciation
Exercise: Minesweeper in 100 lines of Ruby

This article on Radan Skorić's personal site discusses the implementation of the classic game Minesweeper in 100 lines of clean Ruby code. The author emphasizes the challenge of reducing code while maintaining readability, showcasing the expressive nature of Ruby. The implementation covers generating the game board with mines, determining neighboring mines for each cell, playing the game by revealing cells and recursively revealing neighboring cells, and ASCII printing of the board. The code includes classes like Board, Game, and AsciiRenderer to handle different aspects of the game. The article also touches on the use of Ruby features like Data class, endless methods, and breadth-first search for gameplay logic. The author provides insights into the thought process behind the code design and hints at future developments, such as packaging the game into a Rails + Hotwire application for multiplayer functionality. The exercise serves not only as a coding challenge but also as a demonstration of reducing bugs by minimizing lines of code.

Related

Let's write a video game from scratch like it's 1987

Let's write a video game from scratch like it's 1987

Philippe Gaultier created Minesweeper in 1987 using X11 without libraries, resulting in a compact executable. The article explores X authentication, Odin language usage, and minimalistic GUI development, offering insights into X11 intricacies. Source code is on GitHub.

The first 10k games at bgammon.org, an open source online backgammon service

The first 10k games at bgammon.org, an open source online backgammon service

The milestone of 10,000 games on bgammon.org is celebrated, with community contributions and developments noted. Optimization efforts enhance speed and user experience, including the introduction of the Universal Backgammon Engine Interface (UBEI).

I read the dictionary to make a better game (2023)

I read the dictionary to make a better game (2023)

The development of the word search game Tauggle focuses on achieving 100% completion on each board by curating a dictionary with common words. Balancing inclusivity and exclusivity enhances player satisfaction.

HAMURABI.BAS and Its Dystopian Lessons

HAMURABI.BAS and Its Dystopian Lessons

The article explores the game HAMURABI.BAS from 1973, highlighting financial and political lessons. Strategies involve resource management, disaster response, and controlled starvation for wealth. Automated testing led to a 99% win rate, emphasizing wise investments and strategic decisions in the game.

Automated Test-Case Reduction

Automated Test-Case Reduction

Adrian Sampson explains automated test-case reduction techniques using the Shrinkray reducer to debug an interpreter bug. He emphasizes the importance of effective test scripts and occasional manual intervention for efficient bug identification and resolution.

AI: What people are saying
The article on implementing Minesweeper in 100 lines of Ruby code generated various responses:
  • Several users shared their own implementations of Minesweeper or similar games in different languages, such as C#, Python, TypeScript, and Lil.
  • There was a discussion on the readability and syntax of Ruby, with some users appreciating its clarity and others noting the challenges of using it on macOS due to version compatibility.
  • Comments highlighted the differences in programming paradigms, with some preferring object-oriented programming (OOP) and others favoring imperative styles.
  • One user expressed frustration with modern software development practices, particularly the constraints imposed by code reviews and agile methodologies.
Link Icon 12 comments
By @waf - 3 months
Fun exercise! I found that the Ruby in this post resembles modern C# (probably because Ruby is a gold standard in readability, and in the last 5 years or so C# has been making big strides in readability). I've recreated the Ruby code mostly line-for-line in C# and posted it here: https://gist.github.com/waf/5c6a04899e8250cb9a89406b978c9bcc

It mapped from Ruby to C# really well. The only concept I had to add was a `BoardCell` base type for the `Mine` and `Empty` types so we could return either `Mine` or `Empty` in a typesafe way. Everything else matched conceptually 1-1.

It's 118 lines total, with 18 lines of whitespace, so 100 lines exactly. I figure the original Ruby code was also not counting whitespace so it's a fair comparison. I tried to not use any "code golf tricks" that would minimize line count. It's a full program; it could be copy/pasted into a modern .NET 8 project and run without any additional setup.

Note, I posted this same comment on the original blog post, but I've posted it here too as it might be interesting for HN folks.

By @akdfax - 3 months
Very nice syntax. Ruby is definitely underappreciated at the moment.
By @RodgerTheGreat - 3 months
I had a go at an implementation of my own in Lil, using an imperative style rather than OOP. I tried to loosely follow the organization as shown here, but opted for a very different board representation, and I included some niceties like displaying board legends to aid in choosing the proper coordinates.

https://github.com/JohnEarnest/Decker/blob/main/examples/lil...

I'm really not convinced that OOP simplifies or clarifies this type of program.

By @pooriar - 3 months
I'm currently implementing my favorite 2 player board game - Raptor - in Ruby, and this article is giving me great ideas for how to structure it better. Thanks so much to the author for writing this up!
By @igor47 - 3 months
Cool! Mine sweeper is a really fun easy game to implement. I did a version in Python a few years ago: https://github.com/igor47/sweeper but mine is closer to 500 lines
By @oneeyedpigeon - 3 months
Warning to Mac users: you'll need at least ruby 2.7 to run this because it uses a feature called 'argument forwarding'. Looks like the latest ruby installed on macOS 15 is 2.6.

I eventually got it working with a combination of techniques from [this stackoverflow post](https://stackoverflow.com/questions/8730676/how-can-i-switch...) but it's not left my system in the cleanest of states.

By @aaronpkelly - 3 months
Why are all of radanskoric's replies in this story marked as [dead]? He is replying to people here and all his comments won't show for people who don't have showdead enabled

And when I check his profile, almost every comment he's made is also marked as [dead] - but I don't see a good reason why?

By @wkjagt - 3 months
Very fun stuff, and nice post.

Reminds me of my 2048 game clone in Ruby in about 100 lines (https://github.com/wkjagt/2048)

And I just saw that I did this - oh god - 9 years ago. Time goes way too fast.

By @abhishekbasu - 3 months
This was fun. I saw a post on Pyxel a couple of days ago, and decided to write mine in Python using it.

https://github.com/abhishekbasu/minesweeper

By @twobitshifter - 3 months
don’t you have to be able to flag the mines?
By @raymond_goo - 3 months
By @henning - 3 months
The stupid thing about object-oriented programming and modern software is that code like this would never make it through code review on an "agile" team.

- "Oh, why are you doing procedural case statements? that's a SOLID anti-pattern, please refactor to polymorphism"

- "Oh, why is the Ascii Renderer class meddling in cell mine logic? `cell.neighbour_mines.zero? ? "_" : cell.neighbour_mines` should be its own method in a `Mine` class that is properly tested"

You're never allowed to just write code that solves a problem. It never ends. Your team has unlimited authority to slow you down with completely useless "feedback" that does not help anyone.