基于转向的安卓游戏 - 线程同步

时间:2014-07-14 23:21:44

标签: android multithreading synchronization onclicklistener

Hie guys(更好的是,编码员), 我是这个用例:

打开应用>游戏从用户的回合开始>他必须在Edittext&amp ;;进入一个国家。在 20秒之前单击提交按钮,否则num_of_faults将增加1(if(num_of_faults == 3)game_over)

现在半伪代码是:

static void Game(){
    while(true){
        getTimedInput();
        while(true){        
            if(condition 1 is false){
                num_of_faults++;
                getTimedInput();
            } else {
                continue game;          
            }
            if(num_of_faults == max_tries){
                break;
            }
        }       
        if(num_of_faults == max_tries){
            return;
        }       
    }
}

public static void getTimedInput(){
    final Thread thread=  new Thread(){
        @Override
        public void run(){
            try {
                synchronized(this){
                    wait(20000);
                }
            }
            catch(InterruptedException ex){                    
            }
        }
    };
    thread.start();

   inputSubmit.setClickable(true);
   inputSubmit.setOnClickListener(new OnClickListener() {           
        @Override
        public void onClick(View v) {
            synchronized(thread){
                thread.notifyAll();
            }
            get editText input some input validations..           

            if(condition 2 is false){ 
                inputSubmit.setClickable(false);
                inputSubmit.setOnClickListener(null);
                getTimedInput();
            } else if(condition 3 is false) {
                inputSubmit.setClickable(false);
                inputSubmit.setOnClickListener(null);
                getTimedInput();
            } else {
                continue game;
            }
        }
    });  
}

确实可能在堆栈溢出时重复“等待用户点击按钮”, 但我花了很多时间试图解决这个问题, PS:似乎无法将整个代码放在onClickListener中,我真的很感激ne1能否真正付出一些努力来解决上述逻辑,或者至少给我一些指导。 谢谢!

1 个答案:

答案 0 :(得分:0)

认为使用更标准的游戏循环会更好。 下面是一个如何解决这个问题的例子。

public class Game extends Thread {

    private static final int START_SUBMIT_COUNTRY = 1;
    private static final int FINISH_SUBMIT_COUNTRY = 2;
    private static final int COUNTRY_SUBMIT_TIMEOUT = 3;

    private final long SUBMIT_TIMEOUT = 20 * 1000;

    private long countrySubmitBeginTime;
    private boolean isRunning = false;
    private boolean submitCountry = false;
    private Handler parentHandler;
    private final GameHandler gameHandler = new GameHandler(this);

    // Constructor
    public Game(Handler parentHandler) {
        this.parentHandler = parentHandler
    }

    public Handler getHandler() {
        return gameHandler:
    }

    @Override
    public void run() {

        long timeDiff;

        try {
            isRunning = true;
            while(isRunning) {
                ...
                if (submitCountry) {
                    timeDiff = System.currentTimeMillis() - countrySubmitBeginTime;
                    if (timeDiff > SUBMIT_TIMEOUT) {

                        // the timeout has expired so message the parent to let it know
                        Message message = Message.obtain();
                        message.what = COUNTRY_SUBMIT_TIMEOUT;
                        parentHandler.sendMessage(message);
                    }
                }
                ...

        } catch (Exception e) {
            Log.e("Game", "Thread Loop Exception: " + e);
        }
    }

    // Method to start the submitting-a-country action
    private void startCountrySubmit() {
        submitCountry = true;
        countrySubmitBeginTime = System.currentTimeMillis();
    }

    // Method to end the submitting-a-country action
    private void startCountrySubmit() {
        submitCountry = false;
    }

    // Private Nested Class to handle messages to the thread
    private static class GameHandler extends Handler {

        private final WeakReference<Game> mGame;

        // Constructor
        public GameHandler(Game game) {
            mGame = new WeakReference<Game>(game);
        }

        @Override
        public void handleMessage(Message msg) {
            Game game = mGame.get();
            if (game != null) {
                switch (msg.what) {
                    case START_SUBMIT_COUNTRY:
                        game.startCountrySubmit();
                        break;
                    case FINISH_SUBMIT_COUNTRY:
                        game.finishCountrySubmit();
                }
            }
        }
    }
}

在主UI线程中创建并启动游戏游戏线程后,您可以向其发送消息,通过向其发送START_SUBMIT_COUNTRY消息来告知其何时开始计划提交国家/地区操作,并向其发送FINISH_SUBMIT_COUNTRY消息告诉它停止计时(例如,当一个国家成功进入时)。如果在向线程发送FINISH_SUBMIT_COUNTRY消息之前时间限制到期,它将通过COUNTRY_SUBMIT_TIMEOUT消息通知主UI线程。
这里有很多概念,所以如果你有任何新的想法,你可能需要做一些阅读。