Minesweeper with Tables and Gemini
Authors: Jinhwan Kim
linkedin
github
Full Description:
You can see below with independent manual page
A. Purpose of this submission
1. Enjoyable table
I was thinking about what table to create for the table contest 2024, I wanted to create a use case for a table that could be enjoyed without context or understanding of the data.
So, although I am not a professional game developer, I created a "Minesweeper" game using tables and shiny.
2. Various table
I wanted to showcase the capabilities of different tables.
There are a lot of packages available for working with tables in R, each with their own strengths and weaknesses. I haven't used all of them, but I didn't want to limit myself to just one package.
I used reactable, which is my favourite, DT, which was the first one I started using, and finally gt, which has recently been getting a lot of love in the clinical domain.
Of course, there are other valuable packages like flextable
and data.table
, but I don't have time to cover them all.
3. Interactive table
Since I'm using shiny for this submission, I wanted to create some interaction with the user or external services in the table, so I threw in a little bit of LLM functionality, which is all the rage these days.
B. How to play mine-sweeper
This can be followed as Guide with Cicerone in Shiny application
C. How to use Gemini
I skipped using Gemini in here, but you can check in quarto page I've made
D. Code explanation
1. libraries
I used 11 R packages in this mine.tables
# tables
library(reactable)
library(DT)
library(gt)
# shiny
library(shiny)
library(shinyWidgets)
library(bslib)
library(bsicons)
library(shinyjs)
library(cicerone)
# gemini
library(magrittr)
library(gemini.R)
First 3 is for table work,
and next 6 is for shiny application,
and last 2 is for API call gemini.
2. Shiny UI
Since you may see Every code, I attached image of key functions
3. Shiny server
r logic is consisted with 5 major parts. and I only cover some part of it in here.
if you're interested to detailed code, see my code
- mine sweeper game
- Randomly generate data with given size and mine (START)
- Get click input from user
- Check if it is mine or not and show results
- reactable
- To get clicked cell from user with reactable, I used
onClick
parameter of reactable to create "Shiny.setInputValue" (Javascript Event - render mine count, and mine emoji with
color_text
function which return HTML element with color.
reactable(
board_df,
onClick = JS("function(rowInfo, column) {
Shiny.setInputValue('cell_click', { row: rowInfo.index + 1, column: column.id });
}"),
defaultColDef = colDef(
align = "center",
vAlign = "center",
html = TRUE
),
columns = list(
.rownames = colDef(
width = 50,
html = TRUE,
cell = function(value) {
sprintf('<span style="font-weight: 600;">%s</span>', value)
}
)
),
pagination = FALSE,
sortable = FALSE,
bordered = TRUE,
highlight = TRUE,
theme = reactableTheme(tableBodyStyle = list(flex = "auto"))
)
- DT
- To implement Button-like table with DT. used
escape
parameter to use HTML tag. - In cell element (Button) it uses
onclick
to open github repository. - The
pagination
doesn't affect functionality, but I left it on purpose because without it, it's hard to tell it's a table.
output$about.dt <- renderDataTable({
datatable(
data.frame(c('<button
type="button"
class="btn btn-primary"
style="width:100%"
onclick="window.open(`https://github.com/jhk0530/mine.tables`)"
>See code</button>')),
escape = FALSE,
colnames = NULL,
options = list(
dom = "tp",
ordering = FALSE,
searching = FALSE
),
rownames = FALSE,
caption = htmltools::tags$caption(
style = "caption-side: bottom; text-align: center;",
"Table 3: Code Button with DT"
)
)
})
- gt
- Also, to implement Button-like table with gt, I used HTML in
tab_header
to button. (Which hasonclick
for this document) - However, gt seems must show
body
so I usedcolumn
to button and body to just show empty.
output$document.gt <- render_gt({
data.frame(intToUtf8(160)) |>
gt() |>
tab_header(
title = gt::html('<button type="button" class="btn btn-primary" style="width:100%" onclick="Shiny.setInputValue(`foo`, {priority: `event`});">Documents</button>')
) |>
tab_options(
column_labels.hidden = TRUE
) |>
tab_style(
style = cell_borders(sides = "all", weight = px(0)),
locations = cells_body()
) |>
tab_footnote("Table 4: Document button with gt")
})
observeEvent(input$foo, {
shinyjs::runjs('window.open("https://jhk0530.github.io/mine.tables/")')
})
- gemini and cicerone
- See their own repo please.
E. Summary
I made little game-like shiny application with various table R package, and I hope you enjoy it.
Table Type: interactive-Shiny
Submission Type: Single Table Example
Table: mines.tables - shinyapps.io
Code: GitHub - jhk0530/mine.tables
Language: R
Industries: -
Packages: reactable
, DT
, and gt