Interaction Lab Midterm Project: Tic-Tac-Mole

Tic-Tac-Mole – Amelia Zhang – Instructor: Gottfried Haider

The midterm project created by my teammate Mike Zhu and I named “Tic-Tac-Mole” is an interactive competitive game between the user and the computer. I hope this blog post can be informative and hopefully raise your interest in it to some degree.

Before Production: Inspiration, Concept, and Design

My understanding of interaction built by former readings is mainly about feedback and meta-exploration. I deem that an interactive project should be designed to attract the user to actively try to interact with the project and feedback should be given not only for the project’s integrity but also to attract the user to interact further times to explore different possibilities. Before thinking about the original proposal for our midterm project, I was attracted by a few game-like interactive projects, such as “INVISIBLE – The Shadow Chaser”, created by Yoshinobu Nakano and Team Shadow, that aligned with my definition of interaction. Most of them give feedback, especially “win” or “lose” to the users which encourages them to take part in further exploration. Our project Tic-Tac-Mole, whose name is obviously a combination of “Tic-Tac-Toe” and “Whack-a-Mole”, is also a combination and re-creation of the two games mentioned above. My group member and I deemed that the game “Whack-a-Mole” is a great game that satisfies the standard of interaction. What contributed to the developed version of “Whack-a-Mole” is some competitive elements in the form of “Tic-Tac-Toe”. I think this project is attractive to whoever is willing to enjoy interactive games for fun, especially those who want to try a new updated and re-created version of classical games. Our project was designed to become not only a new re-creation of two classic games, but also a multiplayer game. We would like to show a spirit of innovation and competition which allows more people to enjoy their time together.

Our project was designed to have two players taking turns stepping on a place where the “mole” appears (indicated by sticks rotated by servos). If the player is quick enough, he/she/they could occupy that point and the corresponding LED would light up. There are 9 points on a 3*3 chessboard and the rule of win and loss for each player is similar to the rule of Tic-Tac-Toe that whoever succeeds in placing three of the same marks (here, the same color) in a horizontal, vertical, or diagonal row is the winner. Since I am convinced that the instructions should be intuitive in interactive projects, the chessboard position and LED position are corresponding. There was also a more complicated game rule about panelty round for situations when a wrong position was stepped onto.

Considering the complexity of this rule, we abandoned this version soon and changed it into a simplified version which is a competition of the computer mole and the real-life player, using only fingers. The first reason for our change is that the initial plan will have to use 18 LEDs, 9 servos, and 9 capacitive sensors. It would be far too complicated and the Arduino pins might not be enough as well. The second reason is that we found out stepping on the tape for capacitive sensors might not work and we users have to touch it with their skin while the welded joints on tape are less likely to be damaged if only fingers are needed. After the suggestions of our instructors, we decided to use NeoPixels instead of single-colored LEDs because they could change color using RGB code and use only one pin in total to save space for the 9 inevitable pins for the sensors. Since the color could be freely changed, we gave up the unrealistic plan of 9 servos and chose to use blinking Neopixels to indicate the appearance of the mole. In short, the final blueprint of our project is combined with two parts: the hitting points and the chessboard. The mole would randomly appear at one point among the 9 points in total on the chessboard with a blinking yellow light and the user should hit the corresponding hitting point. If successful, the corresponding point on the chessboard turns green to indicate a position owned by the user, otherwise, the mole occupied the position and the NeoPixel would turm red. The whole gaming process is a Tic-Tac-Toe game between the user and the mole, and once 3 points in a horizontal, vertical, or diagonal row would lead to the victory of one side and defeat of the other.

During Production: Fabrication and Improvement

After deciding on the final version of the project’s blueprint, we started the process of production. In general, throughout the whole fabrication and production process, I mainly focused on the overall structure construction, soldering, decoration, and circuit improvement while my teammate completed the rest part, especially coding. However, it was really hard to directly go into the physical construction part since we were totally started with 0. Therefore, I got started with one of the most insignificant but simple parts: beautifying and decorating. I drew the character of a cartoon mole:

(In our final outcome, the hat was removed)

Thanks to our instructor, the 18 LEDs we planned to use to indicate the chessboard were finally changed into NeoPixels which could change color. Since we will need to solder 9 NeoPixels LEDs together, it was really time-consuming and, consequently, we decided to start the soldering as soon as possible, which was actually the real first part I stepped into. Here I was met with the first challenge when I found out that the soldering point for each NeoPixel was too small to make sure no short circuit would be created during my soldering.

As a result, I tried to minimize the size of each piece of soldering iron to make sure that they would not be connected to each other. I successfully soldered four NeoPixels together. However, the problem happened when we tried to stick them onto the cardboard.

The way we decided to fix the LEDs was like threading the needle to hide the wires behind the cardboard, and the condition for each NeoPixel looks like the picture shown above. However, the accident happened when we were dragging the wire of the third NeoPixel and one of the welding points was directly broken, which means we need to repeat the soldering process to fix it. To make sure that such problem will be happen again, we decided to utilize another soldering and connecting way by sticking the LEDs on the cardboard and sticking another cardboard with “windows” to show each illuminating points.

After connecting the cardboard with 4 capacitive sensors (completed by my teammate) and sticking the mole character on the board, our Prototype with 4 available interactive points was then created for user testing. My teammate also completed the coding part for the game logic, what I did was to improve the basic structure by using game states for further extention on the final version.

void setup() {
}

void loop() {
  if (state == 1) {//game time
    state1();
  } else if (state == 2) {// win/lose/draw time
    state2();
  }
}
void state1() {

}
void state2() {

}
 

Apart from completing the size into a 3*3 “Tic-Tac-Mole”, some other feedback was given by the users. First, the soldering placed on the tape for each sensor is really dangerous because if the players press hard with their fingers, it was possible for them to press on an irregular piece of iron, causing injury. My solution to this problem was to create a hammer that is more realistic in the way of “whack-a-mole”. I also used electric tapes to make sure the capacitive sensors would still work.

Second, my teammate and I spent a lot of explaining the specific game rules and the corresponding relationship between lights and sensors to the users. There might be some a lack of instructions. He decided to create another rule cardboard to stick onto the original prototype cardboard and I started changing the mole character with a crying facial expression. I stuck them on the new tape on which the sensors were resoldered to ensure that the shape of the tape could fit the oval mole pattern.

At last, our prototype did not have too much feedback after the game was ended. My teammate and I edited the code to complete the “state2” part to make sure there would be different feedback of “win” (rainbow), “lose”(red cross), and “draw”(white illumination). The video below shows what would happen if the user winned the game.

After addressing almost all of the problems mentioned in the user testing, we constructed the complete “Tic-Tac-Mole” project in a more organized and instructive way. I also added a servo on the top and stuck a cardboard hammer on it to keep hitting the mole cardboard. The video below is a  complete demonstration of the situation where players get a draw.

The full code of our project is as follows.

#include <FastLED.h>
#include <time.h>
int cur_pos; //The current position of the mole
#define NUM_LEDS 9// How many leds on your strip?、
#define DATA_PIN 11

CRGB leds[NUM_LEDS];
int chessboard[9] = {0,0,0,0,0,0,0,0,0}; //0 for no one, 1 for player, 2 for mole
int sensor_array[9] = {0,0,0,0,0,0,0,0,0};
int state = 1;//control state
long startTime;
int WoL_state = 0;

void setup() {
  Serial.begin(9600);
  // make the digital sensor's pin an input
  pinMode(2, INPUT);
  pinMode(3, INPUT);
  pinMode(4, INPUT);
  pinMode(5, INPUT);
  pinMode(6, INPUT);
  pinMode(7, INPUT);
  pinMode(8, INPUT);
  pinMode(9, INPUT);
  pinMode(10, INPUT);
  randomSeed(analogRead(A0));
  FastLED.addLeds<NEOPIXEL, DATA_PIN>(leds, NUM_LEDS);
  FastLED.setBrightness(50); 
}

void loop() {
  // Serial.println(state);
  if (state == 1) {//game time
    state1();
  } else if (state == 2) {// win/lose/draw time
    state2();
  }
}


// main game
void state1() {
  for (int i = 0; i <= 8; i++){
    sensor_array[i] = digitalRead(i + 2);
  }
  cur_pos = random(0,9);
  while (chessboard[cur_pos] != 0) {
  cur_pos = random(0,9);
  }
  chessboard[cur_pos] = 2;
  for (int i = 0; i <= 3; i++){
    leds[cur_pos] = CRGB(255, 165, 0);
    FastLED.show();
    if (sensor_array[cur_pos] == 1) {
      chessboard[cur_pos] = 1;
      leds[cur_pos] = CRGB(0, 255, 0);
      FastLED.show();
    }
    delay(100);
    if (sensor_array[cur_pos] == 1) {
      chessboard[cur_pos] = 1;
      leds[cur_pos] = CRGB(0, 255, 0);
      FastLED.show();
    }
    leds[cur_pos] = CRGB(0, 0, 0);
    FastLED.show();
    if (sensor_array[cur_pos] == 1) {
      chessboard[cur_pos] = 1;
      leds[cur_pos] = CRGB(0, 255, 0);
      FastLED.show();
    }
    delay(100);
    if (sensor_array[cur_pos] == 1) {
      chessboard[cur_pos] = 1;
      leds[cur_pos] = CRGB(0, 255, 0);
      FastLED.show();
    }
    for (int i = 0; i <= 8; i++){
    sensor_array[i] = digitalRead(i + 2); 
  }

    if (sensor_array[cur_pos] == 1) {
      chessboard[cur_pos] = 1;
      leds[cur_pos] = CRGB(0, 255, 0);
      FastLED.show();
      break;
    }
  }
  if (chessboard[cur_pos] == 2){
      leds[cur_pos] = CRGB(255, 0, 0);
      FastLED.show();
  }
  delay(1000);
  if (chessboard[2] == 1 && chessboard[1] == 1 && chessboard[0] == 1 || 
  chessboard[3] == 1 && chessboard[4] == 1 && chessboard[5] == 1 || chessboard[8] == 1 && chessboard[7] == 1 && chessboard[6] == 1 || chessboard[2] == 1 && chessboard[3] == 1 && chessboard[8] == 1 || chessboard[1] == 1 && chessboard[4] == 1 && chessboard[7] == 1|| chessboard[0] == 1 && chessboard[5] == 1 && chessboard[6] == 1||chessboard[2] == 1 && chessboard[4] == 1 && chessboard[6] == 1||chessboard[0] == 1 && chessboard[4] == 1 && chessboard[8] == 1){
    state = 2;
    WoL_state = 1;
  }
  else if (chessboard[2] == 2 && chessboard[1] == 2 && chessboard[0] == 2 ||
   chessboard[3] == 2 && chessboard[4] == 2 && chessboard[5] == 2 || chessboard[8] == 2 && chessboard[7] == 2 && chessboard[6] == 2 || chessboard[2] == 2 && chessboard[3] == 2 && chessboard[8] == 2 || chessboard[1] == 2 && chessboard[4] == 2 && chessboard[7] == 2|| chessboard[0] == 2 && chessboard[5] == 2 && chessboard[6] == 2||chessboard[2] == 2 && chessboard[4] == 2 && chessboard[6] == 2||chessboard[0] == 2 && chessboard[4] == 2 && chessboard[8] == 2){
    state = 2;
    WoL_state = 2;
  }
  else if (chessboard[0] != 0 && chessboard[1] != 0 && chessboard[2] != 0 && chessboard[3] != 0 && chessboard[4] != 0 && chessboard[5] != 0 && chessboard[6] != 0 && chessboard[7] != 0 && chessboard[8] != 0){
    state = 2;
  }
}
// outro
void state2() {
  
  leds[0] = CRGB(0,0,0);
  leds[1] = CRGB(0,0,0);
  leds[2] = CRGB(0,0,0);
  leds[3] = CRGB(0,0,0);
  leds[4] = CRGB(0,0,0);
  leds[5] = CRGB(0,0,0);
  leds[6] = CRGB(0,0,0);
  leds[7] = CRGB(0,0,0);
  leds[8] = CRGB(0,0,0);

  if (WoL_state == 1){
    leds[0] = CRGB(255,0,0);
    FastLED.show();
    delay(50);
    leds[1] = CRGB(255,165,0);
    FastLED.show();
    delay(50);
    leds[2] = CRGB(255,255,0);
    FastLED.show();
    delay(50);
    leds[3] = CRGB(0,255,0);
    FastLED.show();
    delay(50);
    leds[4] = CRGB(0,255,255);
    FastLED.show();
    delay(50);
    leds[5] = CRGB(0,0,255);
    FastLED.show();
    delay(50);
    leds[6] = CRGB(128,0,255);
    FastLED.show();
    delay(50);
    leds[7] = CRGB(255,0,255);
    FastLED.show();
    delay(50);
    leds[8] = CRGB(255,0,128);
    FastLED.show();
    delay(50);
    leds[0] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[1] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[2] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[3] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[4] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[5] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[6] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[7] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
    leds[8] = CRGB(0,0,0);
    FastLED.show();
    delay(50);
  }
if (WoL_state == 2){
    leds[0] = CRGB(255,0,0);
    leds[2] = CRGB(255,0,0);
    leds[4] = CRGB(255,0,0);
    leds[6] = CRGB(255,0,0);
    leds[8] = CRGB(255,0,0);
    FastLED.show();
    delay(200);
    leds[0] = CRGB(0,0,0);
    leds[2] = CRGB(0,0,0);
    leds[4] = CRGB(0,0,0);
    leds[6] = CRGB(0,0,0);
    leds[8] = CRGB(0,0,0);
    FastLED.show();
    delay(200);
}
if (WoL_state == 0){
  leds[0] = CRGB(255,255,255);
  leds[1] = CRGB(255,255,255);
  leds[2] = CRGB(255,255,255);
  leds[3] = CRGB(255,255,255);
  leds[4] = CRGB(255,255,255);
  leds[5] = CRGB(255,255,255);
  leds[6] = CRGB(255,255,255);
  leds[7] = CRGB(255,255,255);
  leds[8] = CRGB(255,255,255);
  FastLED.show();
}
}

 

After Production: Conclusions and Reflections

The original goal of our project is to re-create a multiplayer game based on two classical games. It should be well-instructed by itself and encourage the user to interact with it several times. I think “Tic-Tac-Mole” successfully combined “Tic-Tac-Toe” and “Whack-a-Mole”, and had satisfactory instructions such as asking the users to hit the mole with the help of the hammer in the hand and the servo-based whack-a-mole scene since the users were interacting with it as expected. However, I did not consider it was perfectly instructed since I still needed to explain the game rules to them at the very beginning of their first round. Moreover, most of the users who would like to play for several rounds actually lost their game in the first few rounds. In other words, the game feedback is strong enough to stir their ambition to prove that they could win. However, when they could win, the feedback seemed not to be attractive enough. Another point that made me reflect a lot was our choice of the materials and the sensors. The choice of the capacitive sensor is somehow intuitive, but indeed it might not be the best choice since it is much too sensitive and would have a “High” measurement even if no one has touched it. If time permits, I would like to try the availability of other sensors, such as a magnet sensor to figure out the best choice. If I had more time, I would also try to make better instructions with other devices (such as a laptop with Processing) to minimize the content that should be explained.

My failure during the midterm project gave me an important lesson that when constructing something, we should always take practical considerations first, instead of directly starting to build something too grand or complicated. However, I also mastered some skills, especially the ability to solder or use a hot glue gun. Collaborating with friends to build a project, and watching it transform from 2D paintings and pieces of cardboard into a three-dimensional project, gave me a strong sense of accomplishment and achievement. I am looking forward to the surprises that the next project will bring to me

Disassembly:

sensors removed from our project

Appendix:

The feedback for “draw” and “win” is already included in the blog. This is how “lose” looks like: 

Leave a Reply

Your email address will not be published. Required fields are marked *