티스토리 뷰

Android/Java

[Java]  Tic-tac-toe 게임으로 보는 MVP 패턴

혀가 길지 않은 개발자 2020. 9. 18. 18:18

MVP (Model  +  View  +  Presenter)


activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical"
    android:padding="30dp"
    tools:context=".view.MainActivity">

    <GridLayout
        android:id="@+id/btnGrid"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:rowCount="3"
        android:columnCount="3">

        <Button
            android:tag="00"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="01"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="02"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="10"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="11"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="12"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="20"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="21"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

        <Button
            android:tag="22"
            android:layout_width="100dp"
            android:layout_height="100dp"
            android:onClick="onClickCell"
            android:textSize="30sp"/>

    </GridLayout>

    <LinearLayout
        android:id="@+id/winnerPlayerViewGroup"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="vertical"
        android:visibility="gone"
        tools:visibility="visible">

        <TextView
            android:id="@+id/tvWinnerPlayer"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:textSize="40sp"
            android:layout_margin="20dp"
            tools:text="X"/>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="Winner"
            android:textSize="40sp"/>

    </LinearLayout>

    <Button
        android:id="@+id/btnReset"
        android:layout_width="200dp"
        android:layout_height="70dp"
        android:layout_marginTop="40dp"
        android:textAllCaps="false"
        android:text="Reset"
        android:textSize="20dp"/>

</LinearLayout>

activity_main.xml

 

 

 

 

 

model/Player.java

package com.jwsoft.javaproject.model;

public enum Player {
    O,
    X,
    NULL
}

 

 

 

 

 

model/Cell.java

package com.jwsoft.javaproject.model;

public class Cell {

    private Player player;

    public void setPlayer(Player player) { this.player = player; }

    public Player getPlayer() { return this.player; }

}

 

 

 

 

 

model/Board.java

package com.jwsoft.javaproject.model;

public class Board {

    private Cell[][] cells;
    private Player current = Player.X;

    public Board() {        // Player.NULL로 초기화
        resetCells();
    }

    public Player mark(int row, int col) {
        if (isValid(row, col)) {
            cells[row][col].setPlayer(current);
            return cells[row][col].getPlayer();
        } else {
            return Player.NULL;
        }
    }


    public Boolean isValid(int row, int col) {
        return cells[row][col].getPlayer() == Player.NULL;
    }


    public void resetCells() {
        cells = new Cell[3][3];
        for (int i=0; i < 3; i++) {
            for (int j=0; j < 3; j++) {
                cells[i][j] = new Cell();
                cells[i][j].setPlayer(Player.NULL);
            }
        }
    }

    public void flipCurrentPlayer() {
        current = current == Player.X ? Player.O : Player.X;
    }


    public Player getWinner(int row, int col, Player player) {

        if (cells[row][0].getPlayer() == player &&
            cells[row][1].getPlayer() == player &&
            cells[row][2].getPlayer() == player ||
            cells[0][col].getPlayer() == player &&
            cells[1][col].getPlayer() == player &&
            cells[2][col].getPlayer() == player ||
            row == col &&
            cells[0][0].getPlayer() == player &&
            cells[1][1].getPlayer() == player &&
            cells[2][2].getPlayer() == player ||
            row + col == 2 &&
            cells[0][2].getPlayer() == player &&
            cells[1][1].getPlayer() == player &&
            cells[2][0].getPlayer() == player)
        {
            return player;
        } else {
            return Player.NULL;
        }

    }

}

Model 역할

 

 

 

 

 

 


presenter/PresenterInterface.java

package com.jwsoft.javaproject.presenter;

public interface PresenterInterface {

    void onCreate();
    void onResume();
    void onPause();
    void onDestroy();

}

 

 

 

 

 

 

presenter/Presenter.java

package com.jwsoft.javaproject.presenter;

import com.jwsoft.javaproject.model.Board;
import com.jwsoft.javaproject.model.Player;
import com.jwsoft.javaproject.view.MainView;

public class Presenter implements PresenterInterface {

    private MainView view;
    private Board model;


    public Presenter(MainView view) {
        this.view = view;
    }

    @Override
    public void onCreate() {        // 생명주기 관리
        model = new Board();
    }

    @Override
    public void onResume() {        // 생명주기 관리

    }

    @Override
    public void onPause() {         // 생명주기 관리

    }

    @Override
    public void onDestroy() {       // 생명주기 관리

    }

    public void onButtonSelected(int row, int col) {
        Player player = model.mark(row, col);

        if (player != Player.NULL) {
            view.setButtonText(row, col, player.toString());

            if (model.getWinner(row, col, player) != Player.NULL) {
                view.showWinner(player.toString());     // Presenter -> View
            } else {
                model.flipCurrentPlayer();      // Presenter -> Model
            }
        }

    }

    public void reset() {
        view.clearWinnerDisplay();  // Presenter -> View
        view.clearButtons();        // Presenter -> View
        model.resetCells();         // Presenter -> Model
    }

}

Presenter 역할 

 

 

 

 

 

 


view/MainView.java

package com.jwsoft.javaproject.view;

public interface MainView {

    void showWinner(String winner);
    void clearWinnerDisplay();
    void clearButtons();
    void setButtonText(int row, int col, String text);

}

 

 

 

 

 

view/MainActivity.java

package com.jwsoft.javaproject.view;

import androidx.appcompat.app.AppCompatActivity;

import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.LinearLayout;
import android.widget.TextView;

import com.jwsoft.javaproject.R;
import com.jwsoft.javaproject.presenter.Presenter;

public class MainActivity extends AppCompatActivity implements MainView {

    GridLayout btnGrid;
    LinearLayout winnerPlayerViewGroup;
    TextView tvWinnerPlayer;
    Button btnReset;

    Presenter presenter = new Presenter(this);


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnGrid = findViewById(R.id.btnGrid);
        winnerPlayerViewGroup = findViewById(R.id.winnerPlayerViewGroup);
        tvWinnerPlayer = findViewById(R.id.tvWinnerPlayer);
        btnReset = findViewById(R.id.btnReset);
        btnReset.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                presenter.reset();      // View -> Presenter
            }
        });

        presenter.onCreate();       // View -> Presenter

    }

    @Override
    protected void onResume() {
        super.onResume();
        presenter.onResume();       // View -> Presenter
    }

    @Override
    protected void onPause() {
        super.onPause();
        presenter.onPause();        // View -> Presenter
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        presenter.onDestroy();      // View -> Presenter
    }

    @Override
    public void showWinner(String winner) {     // Presenter -> View
        tvWinnerPlayer.setText(winner);
        winnerPlayerViewGroup.setVisibility(View.VISIBLE);
    }

    @Override
    public void clearWinnerDisplay() {      // Presenter -> View
        winnerPlayerViewGroup.setVisibility(View.GONE);
        tvWinnerPlayer.setText("");
    }

    @Override
    public void clearButtons() {        // Presenter -> View
        for (int i=0; i < btnGrid.getChildCount(); i++) {
            ((Button) btnGrid.getChildAt(i)).setText("");
        }
    }

    @Override
    public void setButtonText(int row, int col, String text) {      // Presenter -> View
        ((Button) btnGrid.findViewWithTag("" + row + col)).setText(text);
    }

    public void onClickCell(View view) {        // View -> Presenter

        int row = Integer.parseInt(view.getTag().toString().substring(0, 1));
        int col = Integer.parseInt(view.getTag().toString().substring(1, 2));

        presenter.onButtonSelected(row, col);
    }

}

View 역할 

 

실행 결과

 

 

 

 

 

참고.

academy.realm.io/kr/posts/eric-maxwell-mvc-mvp-and-mvvm-on-android/

 

안드로이드의 MVC, MVP, MVVM 종합 안내서

안드로이드 앱을 만드는 개발자를 위한 MVC, MVP, MVVM 패턴 사용법과 장단점에 대한 안내서입니다.

academy.realm.io

github.com/ericmaxwell2003/ticTacToe

 

ericmaxwell2003/ticTacToe

A simple tic tac toe app, to illustrate the use of MVC, MVP, and MVVM architectures to organize the application. - ericmaxwell2003/ticTacToe

github.com

 

 

 

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함