Tip/Android2021. 1. 3. 15:53

2021년 새해 연휴기간 만들어 본 지뢰 찾기 입니다.

1. 안드로이드 지뢰 찾기 소스 코드

github.com/chobocho/minesweeper

 

chobocho/minesweeper

Android Minesweeper Game. Contribute to chobocho/minesweeper development by creating an account on GitHub.

github.com

 

2. 동작화면

2.1 플레이 스토어 다운로드 링크

play.google.com/store/apps/details?id=com.chobocho.minesweeper

 

클래식 지뢰찾기 For Android - Google Play 앱

클래식 지뢰찾기 For Android 클래식 지뢰 찾기 게임 입니다. 지뢰찾기 게임에 대한 추억이 있다면, 이 게임과 함께 추억을 떠올리시기 바랍니다. 이 게임은 광고가 없습니다. 이 게임은 오프라인에

play.google.com

지뢰찾기 게임 실행 화면

 

3. UML

UML

 

4. 어떻게 만들었나

4.1 게임 요구 사항 정리하기

대부분 한번은 해보았을 지뢰찾기 규칙은 대부분 알기에 아래와 간단히 개발 바운더리를 정하였습니다.

1. 구현목표
* 윈도우 지뢰찾기 게임의 클론

2. 요구사항

2.1 운영체제
* Android에서 동작 한다

2.2 게임의 구성
* 화면의 타일의 크기는 10x10 이다
* 지뢰의 개수는 12개 이다
* 지뢰의 위치는 매번 랜덤하게 정해 진다

2.3 게임의 동작
* 지뢰가 없는 빈 칸을 클릭시, 해당 칸을 중심으로 8칸 안에 있는 지뢰의 개수가 표시 된다.
* 1초 마다 시간이 업데이트 된다
* 5999초가 넘어가면 자동으로 게임 오버가 된다
* 깃발/지뢰 선택 버튼을 클릭시 깃발 -> 지뢰 순으로 표시 된다.
* 깃발을 표시 할 때 마다
, 표시 할 수 있는 남은 깃발의 개수가 업데이트 된다.
* Pause 상태로 돌입시, 현재의 게임 상태가 유지 되어야 한다.
* 게임 플레이 중 언제든지 Pause 상태로 변경 할 수 있어야 한다.
* Pause 상태에서는 이어하기와  새 게임 하기가 가능해야 한다.
* 깃발 선택 상태에서 타일을 클릭시 깃발이 사라지거나 표시된다.
* 지뢰 상태에서 버튼을 클릭시 타일이 열린다. 이때 지뢰가 있으면, 게임 오버가 된다.

 

5. 설계 하기

5.1 UML

지뢰찾기 기본 구조 (UI제외)

먼저 게임의 상태를 IDLE / PLAY / PAUSE / WIN / GAMEOVER 로 정의 하고,

이를 반영하여 UML를 그리면 위와 같습니다.

 

Play상태에서 지뢰를 모두 찾거나, 혹은 지뢰를 누른 경우,

Game State를 Win State 또는 Game over state 상태로 변경하기 위하여,

위와 같이 NotifyCallBack interface를 PLAY state가 가지도록 합니다.

 

package com.chobocho.minesweeper;

public interface MineSweeperNotifyCallback {
    public void setWinState();
    public void setGameOverState();
}

 

6. 구현 하기

6.1 Tile 클래스 구현

6.1.1 Tile 클래스

6.1.2 Test code 만들기

6.2 Board 클래스 수현

6.2.1 Board 클래스

6.2.2 Test code 만들기

Posted by chobocho

댓글을 달아 주세요

Tip/Android2020. 11. 1. 22:32

PC에서 휴대폰의 Termux 위에 돌아가는 Jupyter notebook 접속하기

휴대폰의 IP는 192.168.35.195 임

1. Termux 실행

2. Jupyter notebook 실행

jupyter notebook --no-browser --port=8889

3. Port forwarding

ssh -L 8282:127.0.0.1:8889 192.168.35.195 -p 8022

4. PC의 웹브라우저를 열고 접속

Posted by chobocho

댓글을 달아 주세요

Tip/Android2020. 10. 28. 00:02

1. web server 가 8080 포트로 실행되어 있다

2. PC에서 8282 포트로 접속을 하고 싶은 경우

  • 휴대폰은 192.168.35.102 ip를 사용하고 있다

ssh -L 8282:127.0.0.1:8080 192.168.35.102 -p 8022

'Tip > Android' 카테고리의 다른 글

[Termux] PC에서 Jupyter notebook 접속 하기  (0) 2020.11.01
[Termux] SSH port forwarding  (0) 2020.10.28
[Termux] Web server 돌리기  (0) 2020.10.27
[Termux] ssh 사용하기  (0) 2020.10.26
Posted by chobocho
TAG ssh

댓글을 달아 주세요

Tip/Android2020. 10. 27. 23:45

Termux 에서 web server를 실행하는 방법

1. Apache2 설치

apt install apache2

2. httpd.conf 수정

/data/data/com.termux/files/usr/etc/apache2/httpd.conf

DocumentRoot "/data/data/com.termux/files/usr/share/apache2/default-site/htdocs"
<Directory "/data/data/com.termux/files/usr/share/apache2/default-site/htdocs">

↓↓↓↓↓

DocumentRoot "/data/data/com.termux/files/home/storage/downloads/localhost/myweb"
<Directory "/data/data/com.termux/files/home/storage/downloads/localhost/myweb">

저의 localhost의 위치는 폰의 downloads 폴더의 /localhost/myweb 입니다.

3. Html 파일 복사

저는 아래의 tetris.html 과 스크립트를 복사했습니다.
https://github.com/chobocho/JsTetris/tree/master/src/app/src/main/assets

4. Apache 웹서버 실행

apachectl start

'Tip > Android' 카테고리의 다른 글

[Termux] SSH port forwarding  (0) 2020.10.28
[Termux] Web server 돌리기  (0) 2020.10.27
[Termux] ssh 사용하기  (0) 2020.10.26
[Gradle] Version 명 자동 업데이트  (0) 2020.04.11
Posted by chobocho

댓글을 달아 주세요

Tip/Android2020. 10. 26. 23:31

1. ".bashrc" 파일에 아래와 같이 sshd를 추가한다.

2. termux를 재실행 한다.

3. ssh 192.168.35.12 -p 8022 와 같이 port 8022번으로 접속한다.

'Tip > Android' 카테고리의 다른 글

[Termux] Web server 돌리기  (0) 2020.10.27
[Termux] ssh 사용하기  (0) 2020.10.26
[Gradle] Version 명 자동 업데이트  (0) 2020.04.11
[ChooseOne] 안드로이드 제비뽑기 앱 만들기 (I)  (0) 2019.09.02
Posted by chobocho
TAG ssh

댓글을 달아 주세요

Tip/Android2020. 4. 11. 15:15

Android로 APK를 생성하면서 자동으로 파일 이름 생성 및 버전 명을 업데이트 하는 스크립트를 구성해 보았다

미래의 나를 위하여 기록을 남긴다

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    def versionPropsFile = file('versioninfo.properties')
    def Properties versionInfo = new Properties()

    if (versionPropsFile.canRead()) {
        versionInfo.load(new FileInputStream(versionPropsFile))
    } else {
        versionInfo['VERSION_HEADER'] = "0.1105"
        versionInfo['VERSION_NUMBER'] = 0
        versionInfo['VERSION_COUNT'] = 0
        versionInfo['BUILD_COUNT'] = 0
    }

    def versionHeader = versionInfo['VERSION_HEADER']
    def versionNubmer = versionInfo['VERSION_NUMBER'].toInteger()
    def versionCount = versionInfo['VERSION_COUNT'].toInteger()
    def buildCount = versionInfo['BUILD_COUNT'].toInteger()

    def taskName = gradle.startParameter.taskNames
    def addVersion = 1
    def isReleaseVersion = false

    if (":app:bundleRelease" in taskName) {
        println '---[bundleRelease]---'
        versionNubmer += addVersion
        versionCount += addVersion
        isReleaseVersion = true
    }

    buildCount += addVersion

    versionInfo['VERSION_HEADER'] = versionHeader.toString()
    versionInfo['VERSION_NUMBER'] = versionNubmer.toString()
    versionInfo['VERSION_COUNT'] = versionCount.toString()
    versionInfo['BUILD_COUNT'] = isReleaseVersion ? "1" : buildCount.toString()

    versionInfo.store(versionPropsFile.newWriter(), null)

    def date = new Date();
    def alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    def thisYear =  alphabet.charAt(date.getYear() + 1900 - 2001)
    def thisMonth = alphabet.charAt(date.getMonth())
    def monthVersion = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(versionCount)

    println '-------------------'
    println taskName
    println "${versionHeader}.${thisYear}${thisMonth}${monthVersion}.${buildCount}"
    println '-------------------'

    defaultConfig {
        applicationId "com.chobocho.ColorMatch"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode versionNubmer
        versionName "${versionHeader}.${thisYear}${thisMonth}${monthVersion}.${buildCount}"
        setProperty("archivesBaseName", "imagematch_$versionName")
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

미래의 우둔한 나를 위하여, 주석을 남긴다.

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    // 프로퍼티 파일 이름
    def versionPropsFile = file('versioninfo.properties')
    def Properties versionInfo = new Properties()

    if (versionPropsFile.canRead()) {
        versionInfo.load(new FileInputStream(versionPropsFile))
    } else {
        // 프로퍼티 파일이 없으면 생성을 하기위해 기본 값을 설정한다
        versionInfo['VERSION_HEADER'] = "0.1105"
        versionInfo['VERSION_NUMBER'] = 0
        versionInfo['VERSION_COUNT'] = 0
        versionInfo['BUILD_COUNT'] = 0
    }

    def versionHeader = versionInfo['VERSION_HEADER']
    def versionNubmer = versionInfo['VERSION_NUMBER'].toInteger()
    def versionCount = versionInfo['VERSION_COUNT'].toInteger()
    def buildCount = versionInfo['BUILD_COUNT'].toInteger()

    def taskName = gradle.startParameter.taskNames
    def addVersion = 1
    def isReleaseVersion = false

    // Signed APK 빌드인 경우만 versionCount를 증가 시킨다
    if (":app:bundleRelease" in taskName) {
        println '---[bundleRelease]---'
        versionNubmer += addVersion
        versionCount += addVersion
        isReleaseVersion = true
    }

    buildCount += addVersion

    // 수정된 값을 프로퍼티에 업데이트 한다
    versionInfo['VERSION_HEADER'] = versionHeader.toString()
    versionInfo['VERSION_NUMBER'] = versionNubmer.toString()
    versionInfo['VERSION_COUNT'] = versionCount.toString()
    versionInfo['BUILD_COUNT'] = isReleaseVersion ? "1" : buildCount.toString()

    versionInfo.store(versionPropsFile.newWriter(), null)

    // 빌드한 연도와 월을 남기기 위한 부분
    // 2001년 1월 > AA
    // 2020년 3월 > TC
    def date = new Date();
    def alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    def thisYear =  alphabet.charAt(date.getYear() + 1900 - 2001)
    def thisMonth = alphabet.charAt(date.getMonth())
    def monthVersion = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".charAt(versionCount)

    println '-------------------'
    println taskName
    println "${versionHeader}.${thisYear}${thisMonth}${monthVersion}.${buildCount}"
    println '-------------------'

    defaultConfig {
        applicationId "com.chobocho.ColorMatch"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode versionNubmer
        // 버전명 정보 -> 0.1105.TD1.2
        versionName "${versionHeader}.${thisYear}${thisMonth}${monthVersion}.${buildCount}"
        // 생성 되는 파일이름을 설정한다
        setProperty("archivesBaseName", "imagematch_$versionName")
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

'Tip > Android' 카테고리의 다른 글

[Termux] Web server 돌리기  (0) 2020.10.27
[Termux] ssh 사용하기  (0) 2020.10.26
[Gradle] Version 명 자동 업데이트  (0) 2020.04.11
[ChooseOne] 안드로이드 제비뽑기 앱 만들기 (I)  (0) 2019.09.02
Posted by chobocho

댓글을 달아 주세요

Tip/Android2019. 9. 2. 00:44

Android 제비뽑기 앱 만들기 (I)


결과물
 
 

앱의 목적
 
2명이상의 사용자들 중 한 명을 뽑아 준다 (사다리 타기)
 
  • 사용 예:  커피 쏘기

앱의 기본 동작 설계
 
 
앱의 요구 사항 분석
 
  • 앱을 실행 후 2명 이상이 화면에 손가락을 올리면, 3초 뒤에 한 명을 선택해 준다
  • 손가락을 올려 둔 상태에서 3초 안에 손가락을 떼거나, 추가하면 다시 3초를 센다
  • 손가락을 올려 둔 상태에서 3초 안에 손가락을 모두 떼면, 동작을 멈춘다
  • 60초 동안 아무도 손가락을 올리지 않으면 자동으로 앱이 종료 된다
 
 
기초 설계
 
  • 앱의 동작을 위하여 내부적으로 IDLE, SELECTING, SELECTED 3개의 State를 가지는 State machie 을 구상하였다.
  • State의 변화는 아래와 같다. (편의 상 시간의 변화를 tick이란 단어로 표시했다.)
 
 
 
State pattern
 
 
 
Code 생성
 
IState.java
package com.chobocho.chooseone.state;
 
import com.chobocho.chooseone.manager.ChooseManager;
 
public abstract class IState {
    public static final int IDLE = 0;
    public static final int SELECTING = 1;
    public static final int SELECTED = 2;
 
    ChooseManager manager;
    int mTick;
    int mPointNum;
 
    public IState() {
 
    }
 
    public void Init() {
        mTick = 0;
    }
 
    public void tick() {
        // TODO implement here
    }
 
    public void updatePointList(int point) {
        // TODO implement here
    }
}
 
IdleState.java
package com.chobocho.chooseone.state;
 
import androidx.annotation.NonNull;
import com.chobocho.chooseone.manager.ChooseManager;
 
public class IdleState extends IState {
    public IdleState(ChooseManager manager) {
        this.manager = manager;
        super.Init();
        mPointNum = 0;
    }
 
    @Override
    public void updatePointList(int point) {
        mPointNum = point;
        if (mPointNum >= 2) {
            manager.transit(IState.SELECTING);
        }
    }
 
    @Override
    @NonNull
    public String toString(){
        return "IdleState";
    }
}
 

'Tip > Android' 카테고리의 다른 글

[Termux] Web server 돌리기  (0) 2020.10.27
[Termux] ssh 사용하기  (0) 2020.10.26
[Gradle] Version 명 자동 업데이트  (0) 2020.04.11
[ChooseOne] 안드로이드 제비뽑기 앱 만들기 (I)  (0) 2019.09.02
Posted by chobocho

댓글을 달아 주세요