Description
This is the good old game Memory with a twist: Every time you pick a wrong pair, the two tiles you chose will switch their location. So sometimes you might think that a tile is at one location when in fact... it has moved. And it might feel like you have no idea where it is anymore.
Author of this game is not responsible for any broken keyboards, screens and/or mouse devices.
I am using a semi-Java8-compliant version of GWT. It does not support the Stream API.
Where to play?
The game can be played here: http://www.zomis.net/codereview/memory/MemoryGWT.html
Class Summary
- MemoryGWT.java, MemoryGWT.html: Main GWT Entry Point.
- MemoryGWT.css: Just some simple CSS.
- MemoryBoard.java: The view class used for the main Memory Board
- FieldView.java: The view for each tile.
- ListUtils.java: Excluded from the review as it is not my code originally. Simply contains an implementation of
shuffle
asCollections.shuffle
does not work in GWT.
Code
FieldView.java: (39 lines, 760 bytes)
public class FieldView implements IsWidget {
private static final String HIDDEN_LABEL = "";
private final Button widget;
private int value;
public FieldView(int value) {
this.value = value;
widget = new Button(HIDDEN_LABEL);
widget.setStyleName("game-button", true);
}
@Override
public Button asWidget() {
return widget;
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
public void showValue() {
widget.setText(String.valueOf(value));
}
public void hideValue() {
widget.setText(HIDDEN_LABEL);
}
}
MemoryBoard.java: (86 lines, 2081 bytes)
public class MemoryBoard implements IsWidget {
private final Grid grid;
private final Random random = new Random();
private FieldView previousClicked;
private boolean timerRunning;
public MemoryBoard(int width, int height) {
if ((width * height) % 2 != 0) {
throw new IllegalArgumentException("width * height must be an even number");
}
grid = new Grid(height, width);
grid.setStyleName("game");
List<Integer> ints = new ArrayList<>();
for (int i = 0; i < width * height / 2; i++) {
ints.add(i);
ints.add(i);
}
ListUtils.shuffle(ints, random);
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int value = ints.remove(ints.size() - 1);
FieldView view = new FieldView(value);
view.asWidget().addClickHandler(e -> clicked(view));
grid.setWidget(y, x, view);
}
}
}
private void clicked(FieldView view) {
if (view == previousClicked) {
return;
}
if (timerRunning) {
return;
}
if (previousClicked != null) {
boolean same = previousClicked.getValue() == view.getValue();
view.showValue();
if (!same) {
Timer timer = new Timer() {
@Override
public void run() {
// switch the two values
int previous = previousClicked.getValue();
previousClicked.setValue(view.getValue());
view.setValue(previous);
view.hideValue();
previousClicked.hideValue();
previousClicked = null;
timerRunning = false;
}
};
timerRunning = true;
timer.schedule(2000);
}
else {
previousClicked = null;
}
}
else {
view.showValue();
previousClicked = view;
}
}
@Override
public Widget asWidget() {
return grid;
}
}
MemoryGWT.java: (15 lines, 345 bytes)
public class MemoryGWT implements EntryPoint {
@Override
public void onModuleLoad() {
final MemoryBoard memory = new MemoryBoard(6, 6);
RootPanel.get("gameContainer").add(memory);
}
}
MemoryGWT.css
.game-button {
width: 42px;
height: 42px;
}
MemoryGWT.html
<!doctype html>
<!-- The DOCTYPE declaration above will set the -->
<!-- browser's rendering engine into -->
<!-- "Standards Mode". Replacing this declaration -->
<!-- with a "Quirks Mode" doctype is not supported. -->
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<link type="text/css" rel="stylesheet" href="MemoryGWT.css">
<title>Memory Extreme</title>
<script type="text/javascript" src="memorygwt/memorygwt.nocache.js"></script>
</head>
<body>
<h1>Memory</h1>
<p>Good old memory with a twist: When you have picked a non-matching pair, the two tiles you have chosen switch.</p>
<!-- OPTIONAL: include this if you want history support -->
<iframe src="javascript:''" id="__gwt_historyFrame" tabIndex='-1' style="position:absolute;width:0;height:0;border:0"></iframe>
<noscript>
<div style="width: 22em; position: absolute; left: 50%; margin-left: -11em; color: red; background-color: white; border: 1px solid red; padding: 4px; font-family: sans-serif">
Your web browser must have JavaScript enabled
in order for this application to display correctly.
</div>
</noscript>
<div id="gameContainer"></div>
</body>
</html>
Questions
The main concern I have is: Is it somehow possible to cheat by debugging the Javascript variables to figure out the values of the tiles in advance? I am considering to make some more GWT stuff, but if it is possible to cheat then I will have to alter the way that I am making it (generate stuff dynamically for example, right before you actually make a move).
Other than that: How is my use of GWT?
Other than that: Any comments welcome. I am not very focused on the HTML and CSS stuff though, they are just included for the sake of completeness.