Array of drawables

This is a fairly substantial application that we worked through in class, to create a random selection of images on cards for a memory game.

You’ll need files in res/drawable-mdpi named card1.png, card2.png, etc. I used 64×64 pixel images from Gravatar: http://www.gravatar.com/avatar/205e460b4fff2e5b48aec07710c08d50?s=64&d=retro where you can change any hex digits you want in that long code (205…d50) to generate different ones.

menu.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Easy Game"
            android:id="@+id/easyB" android:layout_gravity="center"
            android:onClick="selectLevel"/>
    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Medium Game"
            android:id="@+id/mediumB" android:layout_gravity="center"
            android:onClick="selectLevel"/>
    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Difficult Game"
            android:id="@+id/difficultB" android:layout_gravity="center"
            android:onClick="selectLevel"/>
</LinearLayout>

MenuActivity.java

package com.example.memory;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;

public class MenuActivity extends Activity {

    static String GAME_LEVEL_KEY = "SelectedLevel";

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.menu);
    }

    public void selectLevel(View v) {
        Intent i = new Intent(this, GameActivity.class);
        switch(v.getId()) {
            case R.id.easyB:
                i.putExtra(GAME_LEVEL_KEY, 1);
                break;
            case R.id.mediumB:
                i.putExtra(GAME_LEVEL_KEY, 2);
                break;
            case R.id.difficultB:
                i.putExtra(GAME_LEVEL_KEY, 3);
                break;
        }
        startActivity(i);
    }
}

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
        >
    <TextView
            android:layout_width="fill_parent"
            android:layout_height="wrap_content"
            android:text="Hello World, GameActivity"
            android:id="@+id/textView" android:textSize="32dp"/>
    <GridLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center" android:rowCount="3"
            android:columnCount="3" android:id="@+id/grid">
    </GridLayout>
    <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Shuffle"
            android:id="@+id/shuffle" android:layout_gravity="center"
            android:onClick="clickShuffle"/>
</LinearLayout>

GameActivity.java

package com.example.memory;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.GridLayout;
import android.widget.ImageView;
import android.widget.TextView;

import java.util.Random;

public class GameActivity extends Activity {

    // The "value" (image) on each card, or -1 if unknown or blank.
    int NUM_CARDS;
    int[] cards;
    TextView helloText;
    int NUM_IMAGES = 13;
    boolean[] used = new boolean[NUM_IMAGES];
    Random rng = new Random();
    GridLayout grid;
    int[] drawables = {
            R.drawable.card1,
            R.drawable.card2,
            R.drawable.card3,
            R.drawable.card4,
            R.drawable.card5,
            R.drawable.card6,
            R.drawable.card7,
            R.drawable.card8,
            R.drawable.card9,
            R.drawable.card10,
            R.drawable.card11,
            R.drawable.card12,
            R.drawable.card13
    };

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        // Read the parameter
        int level = getIntent().getIntExtra(MenuActivity.GAME_LEVEL_KEY, 1);
        int size = level+2; // 1->3x3, 2->4x4, 3->5x5
        NUM_CARDS = size*size; //  9    16       25
        cards = new int[NUM_CARDS];
        grid = (GridLayout) findViewById(R.id.grid);
        grid.setRowCount(size);
        grid.setColumnCount(size);
        // Embed the image views in each location
        for(int i = 0; i < NUM_CARDS; i++) {
            grid.addView(new ImageView(this), i);
        }

        helloText = (TextView) findViewById(R.id.textView);
        helloText.setText("Welcome to level " + level);
        shuffleCards();
    }

    public void showCards() {
        // Display array in text view to help debug
        String buf = "";
        for(int i = 0; i < NUM_CARDS; i++) {
            buf += cards[i] + " ";
        }
        helloText.setText(buf);
        // Put the images in the GridLayout.
        for(int i = 0; i < NUM_CARDS; i++) {
            ImageView v = (ImageView) grid.getChildAt(i);
            v.setImageResource(drawables[cards[i]]);
        }
    }

    public void clickShuffle(View v) {
        shuffleCards();
    }

    public int chooseUnusedLocation() {
        int loc = rng.nextInt(NUM_CARDS);
        while(cards[loc] != -1) {
            loc = rng.nextInt(NUM_CARDS); // Try again
        }
        return loc;
    }

    public int chooseUnusedImage() {
        int im = rng.nextInt(NUM_IMAGES);
        while(used[im]) { // Already used, try again
            im = rng.nextInt(NUM_IMAGES);
        }
        used[im] = true;
        return im;
    }

    public void shuffleCards() {
        // First set all to unknown.
        for(int i = 0; i < NUM_CARDS; i++) {
            cards[i] = -1;
        }
        // Start with all images unused
        for(int i = 0; i < NUM_IMAGES; i++) {
            used[i] = false;
        }
        // For each pair
        for(int i = 0; i < NUM_CARDS / 2; i++) {
            // Choose a random image
            int im = chooseUnusedImage();
            int loc1 = chooseUnusedLocation();
            cards[loc1] = im;
            int loc2 = chooseUnusedLocation();
            cards[loc2] = im;
        }
        // There might be one remaining card (if NUM_CARDS was odd)
        // we have to fill with an image.
        for(int i = 0; i < NUM_CARDS; i++) {
              if(cards[i] == -1) {
                  cards[i] = chooseUnusedImage();
              }
        }
        showCards();
    }

}