Skip to content
Snippets Groups Projects
Commit 35b4d192 authored by Visser, Anke's avatar Visser, Anke
Browse files

example

parents
No related branches found
No related tags found
No related merge requests found
Showing
with 594 additions and 0 deletions
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.DS_Store
/build
/captures
.externalNativeBuild
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<Objective-C-extensions>
<file>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
</file>
<class>
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
</class>
<extensions>
<pair source="cpp" header="h" fileNamingConvention="NONE" />
<pair source="c" header="h" fileNamingConvention="NONE" />
</extensions>
</Objective-C-extensions>
</code_scheme>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<compositeConfiguration>
<compositeBuild compositeDefinitionSource="SCRIPT" />
</compositeConfiguration>
<option name="distributionType" value="DEFAULT_WRAPPED" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="resolveModulePerSourceSet" value="false" />
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
\ No newline at end of file
/build
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
defaultConfig {
applicationId "fzj.matse.tictactoe"
minSdkVersion 21
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
}
dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
# Add project specific ProGuard rules here.
# You can control the set of applied configuration files using the
# proguardFiles setting in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}
# Uncomment this to preserve the line number information for
# debugging stack traces.
#-keepattributes SourceFile,LineNumberTable
# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="fzj.matse.tictactoe">
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:theme="@style/MyTheme" >
<activity
android:name="fzj.matse.tictactoe.StartScreen"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="fzj.matse.tictactoe.PlayingFieldScreen"
android:label="@string/title_activity_spielfeld_screen" >
</activity>
<activity
android:name="fzj.matse.tictactoe.HighscoreScreen"
android:label="@string/title_activity_spielfeld_screen" >
</activity>
<activity
android:name="fzj.matse.tictactoe.HelpScreen"
android:label="@string/title_activity_help_screen" >
</activity>
</application>
</manifest>
Spielregel:
===========
Auf einem 3x3 Felder großen Spielfeld machen die beiden Spieler abwechselnd ihre Zeichen.Der Spieler,
der als erstes drei seiner Zeichen in eine Reihe, Spalte oder eine der beiden Hauptdiagonalen setzen kann, gewinnt.
Spielablauf:
============
Der Hauptbildschirm bietet 3 Auswahlpunkte:
- Hilfe
- Spiel starten
- Highscore anzeigen
Nach Starten des Spiels wird ein 3x3 Gitter angezeigt. Durch Berühren eines Gitterfeldes wird
vom Spieler ein Kreis in seiner Farbe gesetzt. Danach setzt der Computer ein Zeichen seiner
Farbe auf ein freies Feld. Dies wird fortgeführt, bis keine Felder mehr frei sind oder einer
der Teilnehmer gewonnen hat. Durch Gewinn eines Spieles erhält man einen Punkt, beim Verlieren
einen Minuspunkt. Damit ist eine Runde beendet.
Unterhalb des Spielfeldes werden 2 Buttons "weitere Runde" und "Spiel beenden" angezeigt.
Nach Ende einer Runde kann entweder weitergespielt werden, oder das Spiel wird beendet und ggf.
ein Eintrag in die Highscore getätigt.
Klassen (s. UML-Diagramm)
=========================
- StartScreen.java
Android-Hauptklasse, startet alle weiteren Screens: HighscoreView, Help und PlayingFieldView
- HighscoreView
zeigt die aktuelle Highscoreliste an
- NewHighscoreView
ermöglicht die Eingabe eines neuen Eintrags in die Highscoreliste
- Highscore
Verwaltet die Einträge der Highscore, laedt und speichert die Eintraege
- HelpScreen
Zeigt die Spielanleitung an
- PlayingField
Speichert den aktuellen Stand des Spielfeldes
- macheZug(int s, int x, int y): setzt Spieler s auf Position (x,y)
- boolean hatGewonnen(): stellt fest, ob der letzte Zug zum Gewinn geführt hat
- interface UserSelectionListener
- public void selected(int x, int y);
wird aufgerufen, wenn der Nutzer das Spielfeld an der Position (x,y) berührt hat
- PlayingFieldScreen
- beinhaltet die graphische Darstellung des Spielfeldes (TicTacToeView)
- steuert das Spiel
- public void selected(int x, int y):
Wird aufgerufen, wenn der Nutzer das Spielfeld an der Position (x,y) berührt hat.
- der Zug wird auf Korrektheit überprüft
- ggf. wird der Computerzug gestartet
- ggf. wird eine Gewinnmitteilung gezeigt und die Score erhöht
- TicTacToeView
graphische Ansicht des 3x3 Spielfelds mit roten/blauen Ringen für die Züge der Spieler
- void addSelectionListener(UserSelectionListener l)
Benachrichtigt alle, die sich mit dieser Methode registriert haben, sobald der Nutzer
ein Feldelement des Spielfeldes berührt (selected(x,y) wird aufgerufen)
- updateView
aktualisiert die Spielfeldarstellung (alternativ: Listener der die Spielfeldänderung meldet)
- ComputerPlayer
- nextTurn()
berechnet den nächsten Zug des Computers und setzt ihn in PlayingField
app/src/main/TicTacToeUML.png

55.8 KiB

package fzj.matse.tictactoe;
public class ComputerPlayer {
private PlayingField feld;
private int playerNr;
public ComputerPlayer(PlayingField feld, int playerNr) {
this.feld = feld;
this.playerNr = playerNr;
}
/**
* macht einen mehr oder weniger guten Zug
*/
public void nextTurn() {
for (int i=0; i<feld.size(); i++) {
for (int j=0; j<feld.size(); j++) {
int value = feld.value(i, j);
if (value == 0) {
feld.macheZug(playerNr, i,j);
return;
}
}
}
}
}
package fzj.matse.tictactoe;
import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
public class HelpScreen extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_help_screen);
}
}
package fzj.matse.tictactoe;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
import android.app.Activity;
/*
Output wird im LogCat angezeigt.
Ggf. Filter einstellen, um nur Meldungen von matse.tictactoe zu sehen
*/
import android.util.Log;
public class Highscore {
private static final String TAG = "TicTacToe Highscore";
private final String fileName = "spielstand.txt";
private int idx;
private Activity parent;
public Highscore(Activity act) {
parent = act;
}
public boolean isHighscore(int score) {return false;}
public void insertHighscore(int score, String name) {}
public void loadData() {
// Ansehen unter Eclipse mit dem Android File Explorer
// (Window → Open Perspective → Other → DDMS)
// Datei liegt unter /data/data/package/files/dateiname
try { // Lesen
FileInputStream fin = parent.openFileInput(fileName);
Log.i(TAG, "file already exist:");
Scanner in = new Scanner(fin);
while (in.hasNextLine()) {
idx = in.nextInt();
String str = in.nextLine();
Log.i(TAG, "i= "+idx+" "+str);
}
} catch (IOException e) {
Log.i(TAG, e.getMessage());
//e.printStackTrace();
}
}
/**
* Schreibt Daten auf Datei
*/
public void writeData() {
try { // Schreiben
Log.i(TAG, "create File");
FileOutputStream out = parent.openFileOutput(fileName, Activity.MODE_PRIVATE);
String inhalt = ++idx + " "+"Testeintrag\n";
out.write(inhalt.getBytes());
out.close();
} catch (IOException e) {
Log.i(TAG, e.getMessage());
//e.printStackTrace();
}
}
}
package fzj.matse.tictactoe;
import android.app.Activity;
import android.os.Bundle;
public class HighscoreScreen extends Activity {
Highscore h;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_highscore_screen);
h = new Highscore(this);
System.out.println("test io");
h.loadData(); // test
h.writeData();
};
}
package fzj.matse.tictactoe;
/**
* @author zdv058
* enthält die Daten des quadratischen Spielfeldes
*/
public class PlayingField {
private int[][] feld;
TicTacToeView view;
private static final int size = 3;
public int size() {return size;}
public int value(int x, int y) {return feld[x][y];}
public PlayingField(TicTacToeView view) {
feld = new int[size][size];
this.view = view;
}
/**
*
* @param spieler spieler nr 1 oder 2
* @param x 0-2
* @param y 0-2
* @return true, falls der Zug möglich ist
*/
public boolean macheZug(int spieler, int x, int y) {
boolean ok = true;
if (x > feld.length || y > feld[0].length || x < 0 || y < 0 || feld[x][y] != 0) {
ok = false;
}
else {
feld[x][y] = spieler;
}
view.updateView();
return ok;
}
public boolean hatGewonnen() {
return false;
}
}
package fzj.matse.tictactoe;
import android.os.Bundle;
import android.view.View;
import android.app.Activity;
public class PlayingFieldScreen extends Activity {
private PlayingField field;
private int score;
private ComputerPlayer computer;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_playingfield_screen);
TicTacToeView view = this.findViewById(R.id.spielfeld_view);
field = new PlayingField(view);
view.setData(field);
view.addSelectionListener( (x,y) -> selected(x,y) ); // UserSelectionListener interface
computer = new ComputerPlayer(field, 2);
}
private void selected(int x, int y) {
if (field.macheZug(1, x, y) && !field.hatGewonnen())
{
computer.nextTurn();
}
System.out.println("usersel" +x+" "+y);
}
}
package fzj.matse.tictactoe;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.widget.*;
import android.content.Intent;
public class StartScreen extends AppCompatActivity {
PlayingFieldScreen start; // nur fuers UML
HighscoreScreen highscore;
HelpScreen help;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start_screen);
Button start = this.findViewById(R.id.start);
start.setOnClickListener( e -> startGame() );
Button highscore = this.findViewById(R.id.score);
highscore.setOnClickListener( e-> showHighscore() );
}
private void startGame() {
Intent intent = new Intent(this, PlayingFieldScreen.class);
startActivity(intent);
}
private void showHighscore() {
Intent intent = new Intent(this, HighscoreScreen.class);
startActivity(intent);
}
private void showHelp() {
// todo
}
}
package fzj.matse.tictactoe;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.view.View;
import android.view.*;
import android.view.View.*;
/**
* TODO: document your custom view class.
*/
public class TicTacToeView extends View
{
private static final int strokew=20;
private PlayingField spielfeld;
private Paint paint = new Paint();
private ArrayList<UserSelectionListener> listener = new ArrayList<UserSelectionListener>();
public TicTacToeView(Context context, AttributeSet attrs) {
super(context, attrs);
setFocusable(true);
setFocusableInTouchMode(true);
this.setOnTouchListener( (v,event) -> onTouch(event) );
}
public void setData(PlayingField s) {
spielfeld = s;
}
public void addSelectionListener(UserSelectionListener l) {
listener.add(l);
}
public void updateView() {
System.out.println("updateView wurde aufgerufen");
postInvalidate(); // ruft onDraw indirekt auf
}
@Override
protected void onDraw(Canvas canvas)
{
paint.setStyle(Paint.Style.FILL);
paint.setColor(Color.YELLOW);
canvas.drawRect(0, 0, getWidth(), getHeight(), paint);
canvas.drawRect(0, 0, 500,500, paint);
paint.setStrokeWidth(strokew);
paint.setStyle(Paint.Style.STROKE);
paint.setColor(Color.GREEN);
System.out.println("hier" + getHeight() +" "+ getWidth() +","+getRight());
int s=strokew/2;
int width = getWidth();
canvas.drawRect(s, s, width-s, getHeight()/3, paint);
canvas.drawRect(s, getHeight()*2/3, width-s, getHeight()-s, paint);
//System.out.println("hier1 "+getLeft()+" "+getRight());
canvas.drawRect(s, s, width/3, getHeight()-s, paint);
canvas.drawRect(width*2/3, s, width-s, getHeight()-s, paint);
if (spielfeld != null) {
for (int i=0; i<spielfeld.size(); i++) {
for (int j=0; j<spielfeld.size(); j++) {
int value = spielfeld.value(i, j);
if (value != 0) {
int len = (width-strokew)/3;
int x = (int) ((i+0.5)*len) + strokew/2;
int y = (int) ((j+0.5)*len) + strokew/2;
if (value == 1) {
paint.setColor(Color.BLUE);
canvas.drawCircle(x, y, 30, paint);
}
else {
paint.setColor(Color.RED);
canvas.drawCircle(x, y, 30, paint);
}
}
}
}
}
}
/**
* wird von onTouch aufgerufen, nachdem ein Element vom Benutzer angeklickt wure
* @param x
* @param y
*/
private void elementSelected(int x, int y) {
for (UserSelectionListener l : listener) {
l.selected(x, y);
}
}
/**
* wird aufgerufen, wenn der Benutzer den Bildschirm berührt
*/
public boolean onTouch(MotionEvent event)
{
// wird ausgeloest nach Berühren und Loslassen des Bildschirms
System.out.println("touch " + event.getX() +" "+ event.getY());
int elemSize = getHeight() / 3;
int x = (int) event.getX()/elemSize;
int y = (int) event.getY()/elemSize;
elementSelected(x,y);
return true;
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment