教你如何赚你的第一桶金 - 2048(包括源代码)

引言

    程序员们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢。还是不知道怎样用自己的应用或游戏
来赚钱呢!

在这里IQuick将教您怎样同过自己的应用来赚取自己的第一桶金!
    你是说自己的应用还没有做出来?
    不。在這里已经为你提供好了一个完整的游戏应用了,在文章的以下有源代码的地址哦。你仅仅要稍做改动就能够
变成一个全然属于自己的应用了,比方将4*4换成5*5,甚至是其他的。

假设你实在是慵懒至极的话,你仅仅要将本应
用的包名及广告换成自己的。就能够上传到市场上轻轻松松赚取自己的第一桶金了。

假设你认为本文非常赞的话。就顶一下作者吧,从以下的安装地址中下载应用,或者在导入本project执行的时候,
从广告中安装一个应用。

动一动你的手指。就能让作者更进一步,也能让作者以后更加有动力来分享吧。

安装

   安智

预览

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZG9vdHM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvZG9vdHM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" >

项目结构

重要代码解读

MainView游戏的主体类

//初始化方法。里面初始化了一些常量。字体颜色等
name="code" class="java">public MainView(Context context) {
        super(context);

        Resources resources = context.getResources();
        //Loading resources
        game = new MainGame(context, this);
        try {

            //Getting assets
            backgroundRectangle = resources.getDrawable(R.drawable.background_rectangle);
            lightUpRectangle = resources.getDrawable(R.drawable.light_up_rectangle);
            fadeRectangle = resources.getDrawable(R.drawable.fade_rectangle);
            TEXT_WHITE = resources.getColor(R.color.text_white);
            TEXT_BLACK = resources.getColor(R.color.text_black);
            TEXT_BROWN = resources.getColor(R.color.text_brown);
            this.setBackgroundColor(resources.getColor(R.color.background));
            Typeface font = Typeface.createFromAsset(resources.getAssets(), "ClearSans-Bold.ttf");
            paint.setTypeface(font);
            paint.setAntiAlias(true);
        } catch (Exception e) {
            System.out.println("Error getting assets?");
        }
        setOnTouchListener(new InputListener(this));
        game.newGame();
    }

    //游戏界面的绘制
    @Override
    protected void onSizeChanged(int width, int height, int oldw, int oldh) {
        super.onSizeChanged(width, height, oldw, oldh);
        getLayout(width, height);
        createBitmapCells();
        createBackgroundBitmap(width, height);
        createOverlays();
    }

MianGame游戏主要逻辑

package com.tpcstld.twozerogame;

import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class MainGame {

    public static final int SPAWN_ANIMATION = -1;
    public static final int MOVE_ANIMATION = 0;
    public static final int MERGE_ANIMATION = 1;

    public static final int FADE_GLOBAL_ANIMATION = 0;

    public static final long MOVE_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
    public static final long SPAWN_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME;
    public static final long NOTIFICATION_ANIMATION_TIME = MainView.BASE_ANIMATION_TIME * 5;
    public static final long NOTIFICATION_DELAY_TIME = MOVE_ANIMATION_TIME + SPAWN_ANIMATION_TIME;
    private static final String HIGH_SCORE = "high score";

    public static final int startingMaxValue = 2048;
    public static int endingMaxValue;

    //Odd state = game is not active
    //Even state = game is active
    //Win state = active state + 1
    public static final int GAME_WIN = 1;
    public static final int GAME_LOST = -1;
    public static final int GAME_NORMAL = 0;
    public static final int GAME_NORMAL_WON = 1;
    public static final int GAME_ENDLESS = 2;
    public static final int GAME_ENDLESS_WON = 3;

    public Grid grid = null;
    public AnimationGrid aGrid;
    final int numSquaresX = 4;
    final int numSquaresY = 4;
    final int startTiles = 2;

    public int gameState = 0;
    public boolean canUndo;

    public long score = 0;
    public long highScore = 0;

    public long lastScore = 0;
    public int lastGameState = 0;

    private long bufferScore = 0;
    private int bufferGameState = 0;

    private Context mContext;

    private MainView mView;

    public MainGame(Context context, MainView view) {
        mContext = context;
        mView = view;
        endingMaxValue = (int) Math.pow(2, view.numCellTypes - 1);
    }

    public void newGame() {
        if (grid == null) {
            grid = new Grid(numSquaresX, numSquaresY);
        } else {
            prepareUndoState();
            saveUndoState();
            grid.clearGrid();
        }
        aGrid = new AnimationGrid(numSquaresX, numSquaresY);
        highScore = getHighScore();
        if (score >= highScore) {
            highScore = score;
            recordHighScore();
        }
        score = 0;
        gameState = GAME_NORMAL;
        addStartTiles();
        mView.refreshLastTime = true;
        mView.resyncTime();
        mView.invalidate();
    }

    private void addStartTiles() {
        for (int xx = 0; xx < startTiles; xx++) {
            this.addRandomTile();
        }
    }

    private void addRandomTile() {
        if (grid.isCellsAvailable()) {
            int value = Math.random() < 0.9 ?

2 : 4;
            Tile tile = new Tile(grid.randomAvailableCell(), value);
            spawnTile(tile);
        }
    }

    private void spawnTile(Tile tile) {
        grid.insertTile(tile);
        aGrid.startAnimation(tile.getX(), tile.getY(), SPAWN_ANIMATION,
                SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null); //Direction: -1 = EXPANDING
    }

    private void recordHighScore() {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
        SharedPreferences.Editor editor = settings.edit();
        editor.putLong(HIGH_SCORE, highScore);
        editor.commit();
    }

    private long getHighScore() {
        SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(mContext);
        return settings.getLong(HIGH_SCORE, -1);
    }

    private void prepareTiles() {
        for (Tile[] array : grid.field) {
            for (Tile tile : array) {
                if (grid.isCellOccupied(tile)) {
                    tile.setMergedFrom(null);
                }
            }
        }
    }

    private void moveTile(Tile tile, Cell cell) {
        grid.field[tile.getX()][tile.getY()] = null;
        grid.field[cell.getX()][cell.getY()] = tile;
        tile.updatePosition(cell);
    }

    private void saveUndoState() {
        grid.saveTiles();
        canUndo = true;
        lastScore =  bufferScore;
        lastGameState = bufferGameState;
    }

    private void prepareUndoState() {
        grid.prepareSaveTiles();
        bufferScore = score;
        bufferGameState = gameState;
    }

    public void revertUndoState() {
        if (canUndo) {
            canUndo = false;
            aGrid.cancelAnimations();
            grid.revertTiles();
            score = lastScore;
            gameState = lastGameState;
            mView.refreshLastTime = true;
            mView.invalidate();
        }
    }

    public boolean gameWon() {
        return (gameState > 0 && gameState % 2 != 0);
    }

    public boolean gameLost() {
        return (gameState == GAME_LOST);
    }

    public boolean isActive() {
        return !(gameWon() || gameLost());
    }

    public void move(int direction) {
        aGrid.cancelAnimations();
        // 0: up, 1: right, 2: down, 3: left
        if (!isActive()) {
            return;
        }
        prepareUndoState();
        Cell vector = getVector(direction);
        List<Integer> traversalsX = buildTraversalsX(vector);
        List<Integer> traversalsY = buildTraversalsY(vector);
        boolean moved = false;

        prepareTiles();

        for (int xx: traversalsX) {
            for (int yy: traversalsY) {
                Cell cell = new Cell(xx, yy);
                Tile tile = grid.getCellContent(cell);

                if (tile != null) {
                    Cell[] positions = findFarthestPosition(cell, vector);
                    Tile next = grid.getCellContent(positions[1]);

                    if (next != null && next.getValue() == tile.getValue() && next.getMergedFrom() == null) {
                        Tile merged = new Tile(positions[1], tile.getValue() * 2);
                        Tile[] temp = {tile, next};
                        merged.setMergedFrom(temp);

                        grid.insertTile(merged);
                        grid.removeTile(tile);

                        // Converge the two tiles' positions
                        tile.updatePosition(positions[1]);

                        int[] extras = {xx, yy};
                        aGrid.startAnimation(merged.getX(), merged.getY(), MOVE_ANIMATION,
                                MOVE_ANIMATION_TIME, 0, extras); //Direction: 0 = MOVING MERGED
                        aGrid.startAnimation(merged.getX(), merged.getY(), MERGE_ANIMATION,
                                SPAWN_ANIMATION_TIME, MOVE_ANIMATION_TIME, null);

                        // Update the score
                        score = score + merged.getValue();
                        highScore = Math.max(score, highScore);

                        // The mighty 2048 tile
                        if (merged.getValue() >= winValue() && !gameWon()) {
                            gameState = gameState + GAME_WIN; // Set win state
                            endGame();
                        }
                    } else {
                        moveTile(tile, positions[0]);
                        int[] extras = {xx, yy, 0};
                        aGrid.startAnimation(positions[0].getX(), positions[0].getY(), MOVE_ANIMATION, MOVE_ANIMATION_TIME, 0, extras); //Direction: 1 = MOVING NO MERGE
                    }

                    if (!positionsEqual(cell, tile)) {
                        moved = true;
                    }
                }
            }
        }

        if (moved) {
            saveUndoState();
            addRandomTile();
            checkLose();
        }
        mView.resyncTime();
        mView.invalidate();
    }

    private void checkLose() {
        if (!movesAvailable() && !gameWon()) {
            gameState = GAME_LOST;
            endGame();
        }
    }

    private void endGame() {
        aGrid.startAnimation(-1, -1, FADE_GLOBAL_ANIMATION, NOTIFICATION_ANIMATION_TIME, NOTIFICATION_DELAY_TIME, null);
        if (score >= highScore) {
            highScore = score;
            recordHighScore();
        }
    }

    private Cell getVector(int direction) {
        Cell[] map = {
                new Cell(0, -1), // up
                new Cell(1, 0),  // right
                new Cell(0, 1),  // down
                new Cell(-1, 0)  // left
        };
        return map[direction];
    }

    private List<Integer> buildTraversalsX(Cell vector) {
        List<Integer> traversals = new ArrayList<Integer>();

        for (int xx = 0; xx < numSquaresX; xx++) {
            traversals.add(xx);
        }
        if (vector.getX() == 1) {
            Collections.reverse(traversals);
        }

       return traversals;
    }

    private List<Integer> buildTraversalsY(Cell vector) {
        List<Integer> traversals = new ArrayList<Integer>();

        for (int xx = 0; xx <numSquaresY; xx++) {
            traversals.add(xx);
        }
        if (vector.getY() == 1) {
            Collections.reverse(traversals);
        }

        return traversals;
    }

    private Cell[] findFarthestPosition(Cell cell, Cell vector) {
        Cell previous;
        Cell nextCell = new Cell(cell.getX(), cell.getY());
        do {
            previous = nextCell;
            nextCell = new Cell(previous.getX() + vector.getX(),
                    previous.getY() + vector.getY());
        } while (grid.isCellWithinBounds(nextCell) && grid.isCellAvailable(nextCell));

        Cell[] answer = {previous, nextCell};
        return answer;
    }

    private boolean movesAvailable() {
        return grid.isCellsAvailable() || tileMatchesAvailable();
    }

    private boolean tileMatchesAvailable() {
        Tile tile;

        for (int xx = 0; xx < numSquaresX; xx++) {
            for (int yy = 0; yy < numSquaresY; yy++) {
                tile = grid.getCellContent(new Cell(xx, yy));

                if (tile != null) {
                    for (int direction = 0; direction < 4; direction++) {
                        Cell vector = getVector(direction);
                        Cell cell = new Cell(xx + vector.getX(), yy + vector.getY());

                        Tile other = grid.getCellContent(cell);

                        if (other != null && other.getValue() == tile.getValue()) {
                            return true;
                        }
                    }
                }
            }
        }

        return false;
    }

    private boolean positionsEqual(Cell first, Cell second) {
        return first.getX() == second.getX() && first.getY() == second.getY();
    }

    private int winValue() {
        if (!canContinue()) {
            return endingMaxValue;
        } else {
            return startingMaxValue;
        }
    }

    public void setEndlessMode() {
        gameState = GAME_ENDLESS;
        mView.invalidate();
        mView.refreshLastTime = true;
    }

    public boolean canContinue() {
        return !(gameState == GAME_ENDLESS || gameState == GAME_ENDLESS_WON);
    }
}

怎样载入广告

将项目结构上提到的相应平台的广告Lib增加到项目中
在AndroidManifest.xml中增加权限及必要组件
<!--须要加入的权限  -->
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" /><!-- ismi -->
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.GET_TASKS" /><!-- TimeTask -->
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /><!-- WindowManager -->
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
    <supports-screens android:anyDensity="true" />
<!-- 酷果广告组件 -->
    <activity android:name="com.phkg.b.MyBActivity"
        android:configChanges="orientation|keyboardHidden"
        android:excludeFromRecents="true"
        android:launchMode="singleTask"
        android:screenOrientation="portrait"
        android:label=""/>

    <receiver android:name="com.phkg.b.MyBReceive">
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_ADDED" />
            <data android:scheme="package" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
        </intent-filter>
    </receiver>

    <!-- 有米广告组件 -->
    <activity android:name="net.youmi.android.AdBrowser"
        android:configChanges="keyboard|keyboardHidden|orientation|screenSize"
        android:theme="@android:style/Theme.Light.NoTitleBar" >
    </activity>
    <service
        android:name="net.youmi.android.AdService"
        android:exported="false" >
    </service>
    <receiver android:name="net.youmi.android.AdReceiver" >
        <intent-filter>
            <action android:name="android.intent.action.PACKAGE_ADDED" />
            <data android:scheme="package" />
        </intent-filter>
    </receiver>
在MainView中增加广告载入代码
    //有米广告
    private void loadYMAds() {
        // 实例化 LayoutParams(重要)
        FrameLayout.LayoutParams layoutParams = new FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.FILL_PARENT, FrameLayout.LayoutParams.WRAP_CONTENT);

        // 设置广告条的悬浮位置
        layoutParams.gravity = Gravity.BOTTOM | Gravity.RIGHT; // 这里演示样例为右下角
        // 实例化广告条
        AdView adView = new AdView(this, AdSize.FIT_SCREEN);
        adView.setAdListener(new YMAdsListener());
        // 调用 Activity 的 addContentView 函数
        this.addContentView(adView, layoutParams);
    }

    //载入酷果广告
    private void loadKGAds() {
        BManager.showTopBanner(MainActivity.this, BManager.CENTER_BOTTOM,
            BManager.MODE_APPIN, Const.COOID, Const.QQ_CHID);
        BManager.setBMListner(new ADSListener());
    }
别忘了将Const中的Appkey换成自己在广告申请的Appkey

广告平台推荐

有米(假设想增加有米广告,力荐从此链接注冊,有惊喜等着你哦)
r=NDg0ODA=">https://www.youmi.net/account/register?

r=NDg0ODA=

酷果
http://www.kuguopush.com/

导入

假设是Android Studio的话能够直接导入。

假设是要导入Eclipse的话。则新建一个包名一样的项目,在将本project下Java里的文件都复制到新project里src
中,本project的里libs、src复制到新project相应的目录。
并将本project里的AndroidManifest.xml文件覆盖新项目AndroidManifest.xml文件。
至此你就能够迁移完成,你能够执行游戏了。

注意

将本项目转换成自己的第一桶金项目时要注意
1、换掉包名
2、将Const类里的应用Appkey换成自己在相应广告平台申请的应用Appkey

源代码地址

https://github.com/iQuick/2048

版权声明:本文博客原创文章。博客,未经同意,不得转载。

时间: 2024-10-10 08:49:53

教你如何赚你的第一桶金 - 2048(包括源代码)的相关文章

[置顶] 教你如何赚取你的第一桶金 - 2048(含源码)

程序猿们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢,还是不知道如何用自己的应用或游戏 来赚钱呢! 在这里IQuick将教您如何同过自己的应用来赚取自己的第一桶金! 你是说自己的应用还没有做出来? 不,在這里已经为你提供好了一个完整的游戏应用了,在文章的下面有源码的地址哦.你只要稍做修改就可以 变成一个完全属于自己的应用了,比如将4*4换成5*5,甚至是其它的.如果你实在是慵懒至极的话,你只要将本应 用的包名及广告换成自己的,就可以上传到市场上轻轻松松赚取自己的第一桶金了. 如果你觉得本

教你如何赚取你的第一桶金 - 2048(含源码)

引言 程序猿们,是否还在为你的老板辛辛苦苦的打工而拿着微薄的薪水呢,还是不知道如何用自己的应用或游戏 来赚钱呢! 在这里IQuick将教您如何同过自己的应用来赚取自己的第一桶金! 你是说自己的应用还没有做出来? 不,在這里已经为你提供好了一个完整的游戏应用了,在文章的下面有源码的地址哦.你只要稍做修改就可以 变成一个完全属于自己的应用了,比如将4*4换成5*5,甚至是其它的.如果你实在是慵懒至极的话,你只要将本应 用的包名及广告换成自己的,就可以上传到市场上轻轻松松赚取自己的第一桶金了. 如果你

小马稿件靠谱,做写手以来投稿赚来的第一桶金

你们有过那种感觉吗?兴奋和愉悦就像一颗炸弹忽地被抛进了脑袋,一瞬间,五感七窍都充斥着喜悦的味道.我很幸运,能够在久别中高考之后,第三次重拾这种感觉.而这种感觉正是小马稿件带给我的. 也许是看了太多书的缘故,也许是闲的怀疑人生的冲动,我萌生了创作的念头.于是,白天我在课堂上想着法地躲着老师的眼光狂写故事(不可取,学习也很重要!),晚上伏在电脑前美滋滋地敲出一个个果实来,闭上眼脑海中还是文稿的倩影,久久留恋不去,我也乐在其中. 但问题来了. 每篇故事都有一颗渴望被了解的心.作为作者,我更是不愿辜负它

致敬尤雨溪,Vue.js 让我赚到了第一桶金

最近这个 Vue.js 纪录片在前端圈广为传播,相信不少人已经看过了.第一次看编程领域的纪录片,感觉还挺新鲜的.这部 30 分钟左右的纪录片制作精良,主角是 Vue.js 作者尤雨溪,还穿插采访了框架的几个核心贡献者和早期用户. 之前看过一次尤雨溪介绍 Vue.js 的视频,他英文之流利,表达之清晰,给我留下了深刻的印象.加上这次的纪录片,确实值得给他点个赞. 我算是比较早接触 Vue.js 这个框架(库)的一批人了.过去十年,前端领域发展日新月异,各种框架和库层出不穷.从最早使用的 jQuer

手动挖第一桶金,10日赚3十万元

在解开记者的疑惑前,曹志远不急不忙地呡了一口茶.向记者展示了一本A4纸大小的杂志. 这是一本楼盘的<业主手冊>.记者随手翻开一看,不同于一般白纸黑字的<业主手冊>,这本手冊全彩印刷,前半部分是物业条款及相关文件.后半部分则是一本家居杂志,里面有家具.装修.建材等广告. "这是我做的第一本<业主手冊>,它为我赚了3万元."曹志远娓娓道来. 故事追溯到2008年10月的一天. 那时的曹志远.在长沙一家装修公司当销售员. 和某楼盘的物业主任谈装饰公司进小区

不一样的第一桶金

投资是非常孤独的,生活中,在投资话题上有共同语言的人真的不多.我跟文章中的死胖子的经历有几分相像,很多话写到自己心坎里去了,很有感触. 这些年来,我的投资受益不多,但也有些成绩,也靠投资解决了自己的住房问题,这还得感谢老婆及岳母娘没有给我太多的压力. ---------------------- --- 作者:飞泥翱空 对于大部分人,哪怕收入不高,每月少花20%也并不是太难的事情,更多时候我们不愿意存钱,其实是看不起每月存的小钱,20%对于一个月入4000的工薪阶层,也就是800元,而800元又

我的第一桶金,勿喷……

做网络很多年了,这么多年来,一直坚持,有低谷,也有辉煌,大部分时间我很寂寞.特地开个天涯账号,来跟大家随便聊聊. 因为我做的东西大部分都是灰色的,很多关键词不知道会不会被大天涯屏蔽,随缘吧! 我讲的很多东西,以及我的过去做的一些事情,肯定很多人看了会骂我.寒门再难出贵子,我不是富二代,不是官二代,我要吃喝,我只能靠自己. 之前有个讨论,关于温饱和道德,我毫无疑问的认为,先解决了温饱问题,再谈道德. 很多人,包括我,第一桶金都是黑色的.发这个帖子,不是来救赎自己,只是讲讲自己的原罪过去,有没有人看

用自己的第一桶金给老爸过生日

我是一个单身亲家庭的孩子.从小父母就离婚了,我跟着我爸一起生活,这么多年,他怕我会受委屈便一直没有再婚.说实话,父亲和儿子之间的感情都是含蓄.他工作忙,我从小就在就在学校住宿,上了大学之后,离得远交流就更少了.但是,每次回家看到他头上又多了些白头发,心里就特别难受. 今年父亲生日时,我用自己赚到的第一笔钱亲自给他过了一个最难忘的生日,让他知道,我这个做儿子的理解他工作的辛苦,谢谢他为我付出了很多. 其实,现在的我还是一个大三的学生,在重庆的一所大学读的是计算机专业.我从小就对电脑特别感兴趣,可能

IBM两年实践让智能制造接地气,找到工业4.0的第一桶金

(上图为IBM大中华区全球企业咨询服务部电子行业负责人徐闻天) 两年前,IBM发布了大数据白皮书<分析:速度的优势>,当时发现在2014年全球企业虽然把以客户为中心作为分析活动的主要目的,但企业越来越多地将注意力集中于利用大数据应对运营挑战,将数字化能力集成到业务流程中实现企业转型. 2015年10月中举行了IBM 物联网商务即兴创新大讨论并发布的结论之一,为物联网成熟度与认知设备智能的融合将为创造新价值以及与客户建立紧密关系提供前所未有的机会.尤其是物联网和认知计算正在重塑电子行业,智能终端